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

news/2024/10/13 15:33:41

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何用 Python 编写公平抛硬币的代码

原文:https://towardsdatascience.com/how-to-code-a-fair-coin-flip-in-python-d54312f33da9?source=collection_archive---------7-----------------------

要掌握任何东西,你需要从头开始,理解基础。对于 python 来说,编写一个公平的抛硬币程序是一种通行的权利。这似乎是一个简单的项目,但它可以用许多不同的方式来完成。你甚至可以洞察你的编码习惯。能够评论你的代码是一个关键的程序员技能,但那是另一篇文章。让我们来看看你点击了什么,用 python 编写了一个公平的抛硬币程序。

创建蓝图

在我们开始敲敲打打,创建一个程序让计算机做一个平凡的任务,如抛硬币,让我们飞到 10,000 英尺,并得到我们的方向。程序员有惊人的创造自由(取决于你的(微观)经理,如果你在那条船上,我同情你❤),你可能开始失去对项目的主要关注。是的,即使是这样一个简单的项目,习惯也是在公众视线之内和之外形成的。你的标准只有在没人看的时候才算高。

好的。现在我们有了项目的鸟瞰图,让我们来分析它。我们知道我们将进行一次公平的掷硬币。一枚硬币由两部分组成,头和尾。由于项目描述中使用了“公平”,我们知道获得任何一方的概率都是 50%。如果描述提到有偏见或加权硬币,那么概率将被调整。

二项分布

我们如何模拟抛硬币?我们不能给电脑一个比特币,让它翻转。因为我们使用 python,一种数学语言,我们将使用概率。具体来说就是 numpy 的二项分布,np.random.binomial(n,p)。这是随机类中的一种方法,它接受试验次数(n)和事件发生的概率(p)。二项式分布,顾名思义,可以对两个事件的发生进行“抛硬币”。该调用返回 0 或 1 来表示这两个事件中的一个。这是它使用的等式:

p 是概率,N 是试验次数,N 是成功次数。我们现在知道,要使二项分布成立,我们需要两个变量,n 和 p。

这就引出了一个问题,我们是想看到每一次翻转并跟踪它,还是仅仅满足于积极事件发生的次数?我在船上看到一系列事件,只是为了好玩。所以我们需要一个数组来存储结果。谢天谢地,numpy 能做到这一切!

密码

让我们回到现实,开始编码。

首先,我们需要导入 numpy。

import numpy as np

接下来,我们将创建 n 和 p 变量。我们知道我们需要这些,因为我们将使用 np.random.binomial,这需要试验次数和概率。

'''Main Area'''
#probability of heads vs. tails. This can be changed.
probability = .5
#num of flips required. This can be changed.
n = 10

在我的代码中,我喜欢标记主要区域的位置以便于搜索,以防程序中创建了多个方法。标记任何可以安全改变而不会产生负面影响的变量也是一个很好的实践。

我们还知道,我们将需要启动一个数组来存储翻转。使用 np.arange 将创建一个包含 10 个元素的数组,用 0 到 9 的值按升序填充。

#initiate array
fullResults = np.arange(n)

在这一点上,我们可以走两条路。它要求我们创建一个函数,在 for 循环中进行翻转。由于我们关注代码的可重用性,我们将创建一个包含二项式分布的函数。如果我们决定在未来建立该程序,这将使访问变得容易。

抛硬币

有了这个决定,让我们创建这个方法。我们称之为硬币翻转,它需要考虑事件的概率。它将返回二项式的结果。一定要把这个放在主要区域之前。程序需要定义它才能使用。

def coinFlip(p):    #perform the binomial distribution (returns 0 or 1)    result = np.random.binomial(1,p) #return flip to be added to numpy array    return result

如您所见,试验次数将被设置为 1。这将只返回 0 或 1,假或真。现在可以创建调用 coinFlip 的 for 循环了。

For 循环

#perform desired numbered of flips at required probability set above
for i in range(0, n):    fullResults[i] = coinFlip(probability)    i+=1

For 循环是基本的代码结构,但是为了以防万一,让我们看看发生了什么。头中的 I 将是控制循环是否再次进行的索引。range(0,n)是我可以取的值。我们使用 n,这样我们就不会超过我们的数组大小。当程序可以进入循环时,我们创建的 coinFlip 被调用,结果被保存到数组的元素中。然后,索引 I 递增。

展示掷硬币的发现

我们差不多完成了。最后一步是计数和打印结果。这部分很简单。对于打印部分,我们将打印用于验证是否使用了正确的概率,以及 fullResult 数组。Numpy 有许多针对数组的不同函数。我们将使用 np.count _ 非零()来遍历数组,并计算我们给它的数字出现的次数。在这种情况下,我们将检查 1 和 0 出现的次数。

#print results
print("probability is set to ", probability)
print("Tails = 0, Heads = 1: ", fullResults)
#Total up heads and tails for easy user experience 
print("Head Count: ", np.count_nonzero(fullResults == 1))
print("Tail Count: ", np.count_nonzero(fullResults == 0))

就是这样!我们已经创建了一个程序来模拟公平的掷硬币。代码应该是这样的:

import numpy as npdef coinFlip(p):    #perform the binomial distribution (returns 0 or 1)    result = np.random.binomial(1,p)#return flip to be added to numpy array    return result'''Main Area'''
#probability of heads vs. tails. This can be changed.
probability = .5
#num of flips required. This can be changed.
n = 10#initiate array
fullResults = np.arange(n)#perform desired numbered of flips at required probability set above
for i in range(0, n):    fullResults[i] = coinFlip(probability)    i+=1#print results
print("probability is set to ", probability)
print("Tails = 0, Heads = 1: ", fullResults)
#Total up heads and tails for easy user experience 
print("Head Count: ", np.count_nonzero(fullResults == 1))
print("Tail Count: ", np.count_nonzero(fullResults == 0))

那很有趣!做一些简单的项目,比如抛硬币,是理解像 numpy 这样的库的好方法。Numpy 是一个强大的库,除了模拟抛硬币和创建数组之外,它还能做更多的事情。如果您有兴趣了解更多,请查看了解 python Numpy的基础知识。这篇文章将对 numpy 有一个更广泛的理解。

感谢您的阅读!

在我们重新学习之前,

原载于 https://reginaoftech.com 的

如何有效地编码而不在尝试中死去

原文:https://towardsdatascience.com/how-to-code-effectively-without-dying-in-the-attempt-f26c1de59e1d?source=collection_archive---------30-----------------------

面向非程序员的编程

更好编程的 5 条建议

Image from Émile Perron available at Unsplash

编码似乎是一项简单的任务。但是有效编码可能不行。如今,许多程序员遇到了对他们的工作效率有重大影响的多种情况;一些人帮助他们以更快更有效的方式实现目标,而另一些人只是给他们压力,让他们坚持完成任务。每个人都有不同的策略来处理这些情况,要么是因为他们经历过,要么是因为别人告诉他们如何处理。基于我的同事和个人经验,并期待着在职业生涯中帮助新的和有经验的程序员,我想分享以下 5 条我为有效地编写而编写的建议,这些建议在我的职业生涯中对我有用。希望你觉得有用。**

1.找到一个舒适的工作空间

大多数编程和编码工作都足够灵活,允许在家里、公共场所、图书馆甚至咖啡厅工作,而不必每周 5 天、每天 8 小时呆在办公室。然而,工作环境总是对你的工作效率有很大的影响。找一个让你感觉舒适的地方工作,远离干扰、噪音和可能会降低你工作节奏的情况。找出让你更有效率的因素(例如一杯咖啡或茶、背景音乐、照明、便利设施),并善加利用。想一想:谷歌和其他公司的工作空间远离传统的工作隔间是有原因的。由于他们非常清楚每天花 8 个小时在电脑前编码会带来多大的压力,所以他们一直在寻找让员工在他们的设备前感到舒适的方法。毫无疑问,他们被认为是最适合工作的公司。

2.如有疑问,请使用帮助资源

不可能知道现存的所有库和函数的语法。因此,当您对某个特定的函数或算法有疑问时,可以使用大量的文档和帮助资源。只需在谷歌搜索栏中输入“如何在 ( 编程语言)”;很可能其他人已经有了同样的问题,并把它张贴在堆栈溢出。您也可以直接访问库和包的网站进行参考(例如,Python 的 scikit-learn 库,R 的 ggplot2 包),或者查看编程软件本身的可用帮助文档(例如,在 R 中,您可以键入 help("函数名"),您将看到显示的关于该特定函数的 R 文档)。同样,如果你参加过任何提供代码模板或笔记的在线编程课程(如 Udemy、Coursera、DataCamp ),把它们放在你的电脑上作为快速参考。最后,你可以购买/下载多本编程“食谱”(例如 Paul Teetor 的 R Cookbook )和与统计学习和机器学习相关的教科书(例如 Gareth James、Daniela Witten、Trevor Hastie 和 Robert Tibshirani 的统计学习介绍)。请记住,这些资源旨在用于学习和参考,但掌握算法及其编码语法背后的概念仍然取决于您。

3.遇到困难时,寻求帮助

我知道你在想什么:冒名顶替综合症。你可能害怕向他人寻求帮助会让你和/或他们觉得你不具备作为程序员或软件开发员的技能或专业知识。但是不用担心。向比你懂得更多、更有专业知识的人寻求帮助代表着一个学习新事物、提高技能和获得建议的大好机会,同时还能解决你的编码错误。同样的,它代表了谦逊的标志;你在含蓄地告诉别人,你愿意接受反馈和不断学习。数据科学和数据分析公司应该鼓励员工之间的团队合作和协作,而不是竞争和对抗;这可能会导致更高的生产力水平和更高的员工积极性。知识是用来分享的,而不是留给自己的。

4.让你的眼睛休息一下

长时间盯着笔记本电脑的显示器会导致头痛、视力模糊和头晕,尤其是对戴眼镜的人来说。停止盯着它看几分钟,让你的眼睛休息一下,可以给你的精力充电,继续高效地工作。每当你需要开发一个需要很长时间才能完成的代码时,每小时给自己 5-10 分钟的休息时间,不要盯着笔记本电脑的显示器。在你的办公室周围散散步,吃些健康的零食,舒展一下身体,去一个公共区域,或者简单地休息一下。这对你的视力和健康都有好处。即使编码有时会令人沮丧和耗时,你也不是一台编码机器;记住,你的健康与你的工作效率密切相关。

5.不要过度紧张。明天继续工作

你的代码不能运行。你试着调试它。还是不跑。你认为你可能发现了错误。还是不跑。你要么想把你的笔记本电脑扔到墙上,要么继续调试直到它运行。如果这种情况你听起来很熟悉:放松,不要紧张。总有一天,我们在代码中如此循环,以至于我们不能简单地找到错误,不管它是多么微不足道(例如分号、错别字)。在一天的剩余时间里暂停你的任务,做不同的任务,或者如果太晚了,休息一下。没有什么比一双新鲜的眼睛更能恢复你的工作了。众所周知,程序员会花很长时间在工作、家庭或两者兼而有之的地方编码和开发程序。社交媒体充满了关于程序员社交生活和日常事务的模因。尽管我想说他们很有趣也很虚假,但有时他们很悲伤也很真实。享受做程序员的乐趣,平衡你的生活,充分利用这个令人惊叹的职业。让机器做他们的工作,让你自己成为你自己。

— —

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

罗伯特

如何用 Python 从头开始编写高斯混合模型

原文:https://towardsdatascience.com/how-to-code-gaussian-mixture-models-from-scratch-in-python-9e7975df5252?source=collection_archive---------2-----------------------

使用 NumPy 的 GMMs 和最大似然优化

在无监督学习算法领域,高斯混合模型或 GMM 是特殊公民。GMM 基于这样的假设,即所有数据点都来自具有未知参数的高斯分布的精细混合。它们是试图了解真实数据分布的参数化生成模型。因此,一旦我们知道了高斯参数,我们就可以从与源相同的分布中生成数据。

我们可以认为 GMMs 是 K-Means 聚类算法的软推广。像 K-Means 一样,GMM 也需要聚类的数 K 作为学习算法的输入。然而,这两者之间有一个关键的区别。K-Means 只能学习圆形的聚类。另一方面,GMM 可以学习任何椭圆形状的簇。

此外,K-Means 只允许一个观察值属于一个且仅属于一个聚类。不同的是,GMM 给出了将每个例子与给定的聚类相关联的概率

换句话说,GMM 允许一个观测值属于多个聚类——具有一定程度的不确定性。

对于每个观察,GMM 学习该例子属于每个聚类 k 的概率

一般来说,GMM 试图将每个聚类学习为不同的高斯分布。它假设数据是从有限的高斯混合高斯产生的。

假设一维数据和聚类数 K 等于 3,GMM 试图学习 9 个参数。

  • 平均值的 3 个参数
  • 方差的 3 个参数
  • 3 个缩放参数

这里,每个聚类由一个单独的高斯分布表示(在本例中,总共 3 个)。对于每个高斯,它从数据中学习一个均值一个方差参数。3 个缩放参数(每个高斯 1 个)仅用于密度估计。

为了学习这些参数,GMM 使用期望最大化(EM)算法来优化最大似然。在此过程中,GMM 使用贝叶斯定理计算给定观测值 xᵢ 属于每个聚类 k 的概率,其中 k = 1,2,…,k

让我们来看一个例子。为了简单起见,让我们考虑一个合成的一维数据。但是,正如我们将在后面看到的,该算法很容易扩展到 D > 1 的高维数据。你可以用这个 jupyter 笔记本跟着做。

为了建立一个玩具数据集,我们从从不同的高斯分布中采样点开始。每一个(有自己的均值和方差)代表我们合成数据中的一个不同的聚类。为了让事情更清楚,让我们用 K 等于 2。

下面,你可以看到合成的数据。我们将使用它作为训练数据,使用 GMM(从数据中)学习这些聚类。请注意,某些值在某些时候确实会重叠。

我们可以把 GMM 看作高斯分布的加权和。聚类数 K 定义了我们想要拟合的高斯数。

正如我们所说的,集群的数量需要预先定义。为简单起见,让我们假设我们知道聚类的数量,并将 K 定义为 2。在这种情况下,GMM 将尝试学习 2 个高斯分布。对于一维数据,我们需要了解每个高斯的均值和方差参数。

在开始运行 EM 之前,我们需要给出可学习参数的初始值。我们可以猜测均值和方差的值,并将权重参数初始化为 1/k。

然后,我们可以使用 EM 算法开始最大似然优化。EM 可以简化为两个阶段:E(期望)和 M(最大化)步骤。

在 e 步骤中,我们使用估计的参数计算每个观测值 xᵢ 的可能性。

1-d gaussian distribution equation

对于每个聚类 k = 1,2,3,…,K,我们使用均值和方差的估计值来计算数据的概率密度(pdf)。在这一点上,这些值仅仅是随机猜测。

然后,我们可以计算给定示例 xᵢ 属于 kᵗʰ 集群的可能性。

利用贝叶斯定理,我们得到了第 k 个高斯的后验概率来解释数据。那就是观测值 xᵢkᵗʰ 高斯产生的可能性。请注意,参数φ充当我们的先验信念,即一个例子来自我们正在建模的一个高斯模型。由于我们没有任何额外的信息来支持一个高斯模型而不是另一个,我们开始猜测一个例子来自每个高斯模型的概率相等。然而,在每次迭代中,我们改进我们的先验直到收敛。

然后,在最大化或 M 步骤中,我们如下重新估计我们的学习参数。

Parameter update equations

这里,对于每个聚类,我们更新均值( μₖ )、方差( σ₂ )和缩放参数φₖ。为了更新平均值,请注意,我们使用条件概率 bₖ 对每个观察值进行加权。

我们可以重复这些步骤,直到收敛。这可能达到参数更新小于给定容限阈值的程度。在每一次迭代中,我们更新我们的参数,使其类似于真实的数据分布。

Gaussian Mixture Models for 1D data using K equals 2

对于高维数据(D>1),只有很少的东西会改变。现在我们估算平均值和协方差,而不是估算每个高斯的平均值和方差。协方差是形状为(D,D)的方阵,其中 D 表示数据的维度。下面,我展示了一个不同的例子,其中一个 2-D 数据集被用来拟合不同数量的高斯混合。

在查看 jupyter 笔记本的二维数据。

Gaussian Mixture Models for 2D data using K equals 2

Gaussian Mixture Models for 2D data using K equals 3

Gaussian Mixture Models for 2D data using K equals 4

请注意,上面的合成数据集是从 4 种不同的高斯分布中提取的。然而,GMM 为两个三个四个不同的集群提供了一个很好的案例。

这就是高斯混合模型。这是这篇文章的一些要点。

  • GMM 是一族生成参数无监督模型,试图使用高斯分布对数据进行聚类。
  • 和 K-Mean 一样,你还是需要定义你要学习的聚类数 K。
  • 与 K-Means 不同,GMM 将聚类表示为概率分布。这允许一个数据点属于多个具有一定不确定性的聚类。

感谢阅读。

如何结合 LaTeX 和 R 生成报表

原文:https://towardsdatascience.com/how-to-combine-latex-and-r-for-report-generation-82f23787fc43?source=collection_archive---------8-----------------------

如何获得最佳数据科学报告的简单教程!

(Image by author)

如果您必须创建一个报告,LaTeX 绝对是您的选择,LaTeX 中的所有内容看起来都更好!

在你的学术生涯中,你可能用它来写论文或做一些分析。事实上,像 texstudio 或最近的 Overleaf 这样的环境非常适合单个项目。但现在在你的日常工作中,他们真的能扩大它的规模,让乳胶仍然有用吗?

你需要的是一个自动生成报告(也许,就在你的管道末端)的方法,它根据你的代码的发现动态地改变它的内容,它是视觉上令人愉快的(对你的老板来说),并且它能够到足以批量产生结果。

如果是这种情况,我最喜欢的解决方案是 R 包“knitter”,它允许我们直接从 R 代码创建 LaTeX 文档。结合了编程语言的灵活性和 LaTeX 美学。

在这篇文章中,我想给你一个基本的教程和一些如何成功做到这一点的技巧。
我知道知道 R 和 LaTeX 的人不多,我会尽量保持简单,但这两种编码系统及其组合无法在一篇文章中解释,我希望,如果您点击了这篇文章并一直阅读到现在,您已经对这两者有了一些基本的了解。

事不宜迟,让我们用 r 创建一个 LaTeX 报表。

其中两个是创建 R/tex 报告所需的步骤,一个创建最终 pdf 的“starter”R 脚本,以及。Rnw 文件,我们所有的代码都将存储在这里。让我们看看他们:

起始脚本

“starter”脚本必须完成两个基本功能:

  1. 加载并传递 Rnw 文件到编织器包的编织命令。这个过程叫做编织。这将执行 R 代码并生成一系列文件,其中有一个我们通常在 texstudio 中使用的. tex 文件。
  2. 执行两次。tex 文件,以便创建最终的 PDF 报告

为了使整个过程更容易,我建议创建一个名为 starter 的独立文件。r 使用上面的代码,并在需要时使用下面的命令运行它:

R CMD BATCH starter.R

或者,您可以在命令行或任何您可能需要的地方复制/粘贴这三行代码。

别忘了在 r 中安装 knitr。

install.packages('knitr')

Rnw 文件

的。Rnw(或 Sweave)文件本质上是一个. tex 文件,可以在其中插入 R 代码块。

文件的结构遵循 LaTeX 作品的正常结构,从 document 类的声明开始,但是在代码中的任何地方,您都可以添加 R 个代码块。

这些是在两个元素之间定义的:a < < … > > ,在其中传递 R 代码块的设置,以及一个 @ ,定义其结束。

让我们看一个例子:

到目前为止,这是一个常见的代码,你可以在任何。tex 文件并生成图 1 中的页面。它产生一个首页、目录和第一章:****

Fig 1: The first three pages of the final document (Image by author)**

让我们继续,看看第一个 R 块,它用 R 创建了一个图,并在 LaTeX 中导入图形:

其余块:

在小于号和大于号之间,我们可以传递执行 R 块的参数;要通过的最重要的要素是:

  • Name :这只是程序块的名字,每个程序块必须有一个唯一的名字。在调试阶段,识别名称将对您有很大帮助
  • echo :该 TRUE 或 FALSE 值将指示代码是否会显示在最终的 pdf 文档中。
  • ****结果可以取值‘asis’或‘hide ’,它将显示或隐藏程序块的结果(输出)

其他参数是布尔值“include ”,它决定该块是否必须运行,“warning”和“message”都决定调试消息是否必须在 pdf 最终版本中显示。

让我们看一个实际的例子,其中我们将加载 Iris 数据库并在 R 代码块中创建一个绘图:

在上面的代码中,我们定义了一个名为 CreatePlot 的代码块,其中我们要求在 pdf 中显示下划线 R 代码,但是结果图是隐藏的,它将使用\includegraphics{}加载。

Fig 2**: The resulting pages from the code above. (Image by author)

在图 2 的中,我们可以看到上面代码的结果。
标题、显示为 echo 请求的 R 代码块和用于加载图形的 latex 代码。****

我已经手动添加了图 2 中的图来显示 R 代码的结果,否则它将在不同的 pdf 页面中。

让我们以表格为例来看另一种情况:

通过这段代码,我们使用 iris 数据库创建了一个表格,代码和表格立即显示出来,如下图图 3** 所示。**

Fig 3: PDF page resulting from the code. (Image by author)**

我们可以看到,上面的块创建了一个表,其中包含 Iris 数据库(没有完全报告)和生成它的 R 代码。

提示和有用的链接

就我个人的经验来说。Rnw 文件是一个非常强大的工具,但是,我建议将 R 代码保持在最低限度,并且只使用块来导入在其他地方生成的图和 CSV/表。
如果你更喜欢直接在 Rnw 中计算和生成内容,它很快就会变得混乱。

我希望这篇文章能为你使用 LaTeX 和 r 创建第一个报告提供具体的帮助。

完整的扩展代码存在于这个 GitHub 库中:

上面的脚本会产生下面的 pdf (点击链接内的图片)。

关于编织者的更多信息:来源一和二。

我希望这篇文章对你有所帮助

关于机器学习如何沟通清楚?

原文:https://towardsdatascience.com/how-to-communicate-clearly-about-machine-learning-8731e4d1cd4c?source=collection_archive---------17-----------------------

你的用词很重要。

众所周知,机器学习领域被认为偏重于理论:主要是数学、统计学和计算机科学。虽然从业者倾向于享受深度,但“泡沫之外”的同事和客户很难参与对话。那会导致不良的沟通。

沟通不畅,项目就会失败。

糟糕的沟通扭曲了期望,影响了计划,而且,总的来说,它会降低你的团队的效率。作为从业者,这也是你的问题

机器学习工程师的刻板印象:

📊大数据的拥护者。

✨的🧠笔杆子神奇的学习算法 ✨.

🤔聪明又好奇。

😅难以沟通(如果你不喜欢 ML)。

因为你正在做的事情看起来复杂而陌生,你的一些合作者不会乐意挑战你。

尤其是因为这个原因,你有责任改善你的工作沟通方式,以打破“难以沟通”的刻板印象。

考虑业务需求。

更清晰沟通的第一步是停止将你的工作与技术需求联系起来,开始将它与业务需求联系起来。

技术需求你的需求 建立一个数学上正确、统计上合理、技术上健壮、计算上高效的机器学习模型。

这非常重要,但是这些信息与你的非技术合作者无关。他们关心业务需求你所做的事情如何让我们更接近解决实际的业务问题?

假设你正在开发一个欺诈检测系统,而你的模型召回率很低,产生了很多误报。在团队会议中,你需要交流你的进展和下一步的计划。

回忆这个词对你的同事来说没有任何实际意义,所以不要使用它。相反,你可以说你的系统是“制造很多假警报”。你的下一步可能是“调整系统的某些部分,以降低误报率”

这种语言可以确保你的同事处于循环中——它还可以促进关于可接受的假警报率的有益讨论。

制定有意义的 KPI。

损失、准确度、精确度、召回率、F1 分数、ROC 曲线和混淆矩阵是衡量模型性能的重要指标。

当模型的性能本身就是一个目标时,这些度量就很有意义,比如在研究或原型中测试一个想法是否可行。

对于真正的商业案例来说,这是一个罕见的目标!

更多的时候,你是在用数据来解决业务问题。举几个例子,你可能会尝试:

  • 自动执行任务以节省劳动力成本。
  • 帮助某人以更少的错误完成任务。
  • 通过提出智能建议来改善产品用户体验。

你的工作应该根据你正在解决的问题来衡量。

当开始一个新项目时,首先尝试从业务需求的角度来理解问题。哪些 KPI 能准确反映需求是否得到满足?有了这些知识,你就可以对制定解决方案所需的内部指标做出更好的决策。

假设您正在构建一个系统来优化一项劳动密集型任务,以便降低成本。如果你的系统是高度精确的,实际上会使过程变慢,这有什么关系吗?那不会真正降低成本。

对于这种情况,一个好的 KPI 可能是类似于平均工作流速度的东西。定义一个工作流程并测量它需要多长时间。使用您的系统测量相同的工作流程(控制经验水平)。您是否加快了流程?

您可能会了解到,模型必须达到一定程度的准确性才是有用的。也许你会发现,只有当模型的准确率至少达到 75%时,这个过程才会变得更快。如果你的目标是,你可能会尝试更高容量的模型,增加计算成本。相反,如果你的目标是 工作流速度 ,你会发现在一个足够精确的模型和快速计算 的 模型之间存在一个折中点。**

与你的合作者确定有意义的 KPI 将业务需求放在第一位,并围绕你正在解决的实际问题进行沟通。

使用一致的术语。

用不同的词来描述同一件事可能是混淆的主要来源,使所有的交流效率降低。

当你开始一个项目时,你可能想和你的团队以及你的客户一起讨论这些词语。

对于你的项目,试着回答如下问题:

什么是用户?什么是系统?什么是型号?什么是管道?什么是工作流程?确保写下这些定义。

让每个人都使用相同的词汇可以减少“在翻译中丢失”的交流量。这确实需要一些前期工作,但是从相互理解中获得的效率是值得的。

简单点,傻瓜。

处理数据并不总是简单的。事实上,数据中的信息通常是复杂的、细微的、多方面的。但是我们应该试着记住接吻。

现在我喜欢接吻。这个古老的缩写经常在编程中使用,它告诉我们“保持简单,傻瓜”

信息过载 是真实存在的事情,在呈现一个复杂的主题时很难避免。输出大量信息可能会让你看起来很聪明,但这会让你的合作者感到无能为力。

向别人展示你的作品的全部目的是让他们能够做出决定或采取行动。如果你给他们提供过多的信息,他们将无法有效地工作。

处理数据的许多微妙之处是你的工作。**当与你的同事和客户交流时,试着关注哪些信息对业务需求至关重要。这样集中信息通常需要额外的准备,所以记得为此分配一些时间。

如何在实践中比较两种分布

原文:https://towardsdatascience.com/how-to-compare-two-distributions-in-practice-8c676904a285?source=collection_archive---------2-----------------------

现实世界中的数据科学

应用离散 Kolmogorov-Smirnov 检验的快速指南

Photo by Raquel Martínez on Unsplash

我们将在本文中讨论的内容

本文演示了如何进行离散 Kolmogorov-Smirnov(KS)测试并解释测试统计。作为一个非参数检验,KS 检验可以用来比较任何两个分布,不管你假设它是正态分布还是均匀分布。在实践中,KS 检验是非常有用的,因为它在区分一个样本与另一个样本或理论分布(如正态或均匀分布)时是高效和有效的。

首先,为什么我们需要研究我们的数据?

假设你的公司推出了一款新产品,你的首席执行官问你该新产品是否比旧产品更受欢迎。你进行了 A/B 测试,发现新产品比旧产品卖得多。兴奋地分享好消息,你告诉首席执行官新产品的成功,却看到困惑的表情。

By visual inspection, the two groups have different incomes and are of similar ages. How can we verify this?

首席执行官看起来很困惑,因为我们没有提供任何故事。毕竟,首席执行官最不愿意做的事情就是在不了解谁在购买这些产品的情况下停止旧产品并销售新产品。

为了传递一个故事,我们可以分析人口统计数据并回答以下问题:

  • 这两组客户的年龄相似吗?
  • 这两组顾客的收入相似吗?

回答这些问题需要比较两个样本分布,这可以通过离散 KS 检验来完成。作为这次测试的结果,我们将发现我们是否应该保留或停止旧的产品线。

离散 KS 测试背后的思想是什么?

KS 检验背后的思想很简单:如果两个样本属于彼此,它们的经验累积分布函数 (ECDFs)一定非常相似。这表明我们可以通过测量 ECDFs 之间的差异来评估它们的相似性。

为了实现这一点,KS 测试找到了 ECDFs 之间的最大距离。更重要的是,测试需要评估距离是否大到足以声称两个样本不属于彼此。

在下图中,入站 ECDFs 之间的最大距离用红色箭头表示。红色箭头对应于 KS 测试统计数据,显示在红色圆圈中。

实际上,由于四舍五入的原因,离散型的 KS 检验通常是合适的。虽然时间和价格等变量在理论上是连续的,但由于四舍五入的原因,这些变量通常被视为离散变量,这给了我们一组有限的可能值。KS 测试的连续版本仍然可以使用,尽管它将导致更保守的结果(即,如果拒绝水平为 5%,实际水平将小于 5%)。

我们如何应用离散 KS 检验?

以下是对两个样品进行离散 KS 测试的程序:

第一阶段:宁滨山脉

  • 找出组合样本的最小值和最大值,以定义我们的范围。
  • 对范围进行分箱,使每个分箱至少有 10 个样本:
    例如,对于 500 个样本,通过选择 20 个桶,我们可以预计每个分箱有 25 个样本。

Stage 1: Binning the range

阶段 2:计算箱频率

  • 利用阶段 1 中的仓集,使用上一节中的 ECDF 公式计算每个样本的所有仓的频率。

阶段 3:计算最大距离

  • 对于每个箱,计算两个样本之间的频率差。
  • KS 检验统计量等于所有频段中频率的最大差值。

我们如何理解 KS 检验统计量?

为了找出我们是否可以拒绝零假设,我们必须使用统计技术推导出一个 KS 检验统计分布。

1.样本分布与理论分布

当我们将样本与理论分布进行比较时,我们可以使用蒙特卡罗模拟来创建测试统计分布。

例如,如果我们想要测试一个 p 值分布是否是均匀分布的(即 p 值均匀性测试,我们可以模拟均匀随机变量并计算 KS 测试统计量。通过重复这个过程 1000 次,我们将有 1000 个 KS 测试统计,这给了我们下面的 KS 测试统计分布。

The red line is the actual test statistic and the green line is the test statistic for 1000 random normal variables.

通过插入实际样本的 KS 检验统计量(即红线),我们可以看到实际的 KS 检验统计量包含在分布中。这意味着没有强有力的证据反对 p 值样本遵循均匀分布的零假设。

此外,绿线代表使用 1000 个正态随机变量模拟的 KS 测试统计数据,位于分布之外。这表明了均匀分布和正态分布之间的不同。

2.样本分布与另一个样本分布

在我们前面的年龄和收入分布的例子中,我们将一个样本分布与另一个样本分布进行比较,而不是与理论分布进行比较。在这种情况下,我们需要应用重采样技术,如置换测试或自举,以获得 KS 测试统计分布。

在这一节中,我们将进行一个排列测试,它包括组合两个样本,以随机创建两个样本的新集合。对于每个新集合,我们将计算 KS 检验统计量,并将所有这些统计量组合起来,以生成 KS 检验统计量分布。

The red vertical line is the KS test statistic value of the two original samples.

不出所料,实际收益样本的 KS 检验统计量远离分布。这表明我们可以拒绝收入样本相同(即 p 值为零)的零假设。相反,实际年龄样本的 KS 检验统计量位于其 KS 检验统计量分布内。因此,我们不能拒绝零假设,即年龄样本是相同的。

我们学到了什么

由于我们的发现,我们可以得出结论,新老产品可能针对相似的年龄组,但不同的收入组。这告诉我们,我们不应该停止旧产品,必须在两种产品之间找到最佳平衡。

除了 KS 检验外,还有卡方检验和 Anderson-Darling (AD)检验等替代方法,可在[2]中找到。与将所有重点放在具有最大差异的箱上的 KS 测试相比,这些备选方案在所有箱之间分配权重。卡方检验根据箱的预期频率分配权重,而 AD 检验则更加强调尾部。

我想鼓励读者应用离散 KS 检验或探索其他替代方法作为他们分析程序的一部分。这些测试不仅帮助我们从里到外理解数据,而且实现起来也很简单。这里有一个 R 包可用。玩得开心,好好享受吧!

来源

[1]埃尔莫尔,K. L. (2005 年)。根据集合预报评估等级直方图的卡方检验的替代方法。天气与预报20 (5),789–795。doi:10.1175/884.1

[2]m .斯蒂尔和 j .蔡斯林(2006 年)。拟合优度检验离散拟合优度检验统计量对一个均匀空值和一组备选分布的功效。

如何使用 Docker 在 Ubuntu 16.04 上编译 TensorFlow 1.12

原文:https://towardsdatascience.com/how-to-compile-tensorflow-1-12-on-ubuntu-16-04-using-docker-6ca2d60d7567?source=collection_archive---------17-----------------------

本教程将帮助您在 Ubuntu 16.04 上使用 Docker 和 nvidia-docker 的 GPU 设置 TensorFlow 1.12。

TensorFlow 是最受欢迎的深度学习库之一。它由谷歌创建,并于 2015 年作为一个开源项目发布。TensorFlow 用于研究和生产环境。安装 TensorFlow 可能很麻烦。难度因环境限制而异,如果你是一名只想构建神经网络的数据科学家,难度会更大。

在 GPU 上使用 TensorFlow 时—设置需要几个步骤。在下面的教程中,我们将回顾设置 TensorFlow 所需的过程。

要求:

  • NVIDIA GPU 机器
  • Docker 和 Nvidia-Docker 已安装。(阅读我们博客中的“如何安装 docker 和 nvidia-docker”)
  • Ubuntu 16.04

步骤 1-使用 Docker 和 Nvidia-Docker 准备您的环境

Docker 是一个工具,旨在通过使用容器来简化应用程序的创建、部署和运行。容器到底是什么?容器允许数据科学家和开发人员用环境需要的所有部分——比如库和其他依赖项——包装环境,并将其全部打包。

要将 docker 与 GPU 配合使用,并能够在您的应用程序中使用 TensorFlow,您需要安装 Docker 和 Nvidia-Docker。如果您已经安装了这些,请转到下一步。否则,你可以按照我们之前的指南安装 nvidia docker 。

先决条件:

第 2 步— Dockerfile

Docker 可以通过读取 docker 文件中的指令来自动构建映像(环境)。Dockerfile 是一个文本文档,它包含用户可以在命令行上调用的所有命令来组合一个图像。

在我们的例子中,这些命令将描述 Python 3.6、CUDA 9 和 CUDNN 7.2.1 的安装—当然还有从源代码安装 TensorFlow 1.12。

对于这种环境,我们将使用以下 docker 文件-

步骤 3 —运行 Dockerfile

要从 docker 文件构建映像,只需运行 docker build 命令。请记住,这个构建过程可能需要几个小时才能完成。我们建议使用 nohup 实用程序,这样,如果您的终端挂起,它仍将运行。

$ docker build -t deeplearning -f Dockerfile

这将输出设置过程,并以类似于以下内容结束:

>> Successfully built deeplearning (= the image ID)

您的图像已经可以使用了。要启动环境,只需输入以下命令。但是,不要忘记更换您的图像 id:

$ docker run --runtime=nvidia -it deeplearning /bin/bashStep 4 — Validating TensorFlow & start building!

验证 TensorFlow 确实在您的 docker 文件中运行

$ python
import tensorflow as tf
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
2019-02-23 07:34:14.592926: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports 
instructions that this TensorFlow binary was not compiled to use: AVX2 FMA2019-02-23 07:34:17.452780: I 
tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:964] successful NUMA
node read from SysFS had negative value (-1), but there must be at leastone NUMA node, so returning NUMA node zero
2019-02-23 07:34:17.453267: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with 
properties: 
name: Tesla K80 major: 3 minor: 7 memoryClockRate(GHz): 0.8235pciBusID: 0000:00:1e.0
totalMemory: 11.17GiB freeMemory: 11.10GiB
2019-02-23 07:34:17.453306: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu
devices: 0
2019-02-23 07:34:17.772969: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect
StreamExecutor with strength 1 edge matrix:
2019-02-23 07:34:17.773032: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:988]      0
2019-02-23 07:34:17.773054: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0:   N
2019-02-23 07:34:17.773403: I
tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow
device (/job:localhost/replica:0/task:0/device:GPU:0 with 10757 MB memory)
-> physical GPU (device: 0, name: Tesla K80, pci bus id: 0000:00:1e.0,
compute capability: 3.7)
Device mapping:
/job:localhost/replica:0/task:0/device:XLA_CPU:0 -> device: XLA_CPU device
/job:localhost/replica:0/task:0/device:XLA_GPU:0 -> device: XLA_GPU device
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Tesla K80,
pci bus id: 0000:00:1e.0, compute capability: 3.7
2019-02-23 07:34:17.774289: I
tensorflow/core/common_runtime/direct_session.cc:307] Device mapping:
/job:localhost/replica:0/task:0/device:XLA_CPU:0 -> device: XLA_CPU device
/job:localhost/replica:0/task:0/device:XLA_GPU:0 -> device: XLA_GPU device
/job:localhost/replica:0/task:0/device:GPU:0 -> device: 0, name: Tesla K80, pci bus id: 0000:0

恭喜你。您的新 TensorFlow 环境已经设置完毕,可以开始训练、测试和部署您的深度学习模型了!

结论

Tensorflow 通过提供一种大规模构建生产就绪模型的解决方案,真正颠覆了机器学习世界。但是 Tensorflow 并不总是最用户友好的。很难顺利地融入你的机器学习管道。 cnvrg.io 数据科学平台利用 Tensorflow 和其他开源工具,以便数据科学家可以专注于算法这一魔法。你可以找到更多关于如何轻松利用开源工具的教程,如 Tensorflow 、如何为你的机器学习工作流设置 Kubernetes,以及如何在 Kubernetes 上运行 Spark。找到简单的方法来集成这些有用的工具将使您的模型更接近生产。

如何计算 Keras 中命名实体识别的 f1 值

原文:https://towardsdatascience.com/how-to-compute-f1-score-for-named-entity-recognition-in-keras-6f28b31dccca?source=collection_archive---------14-----------------------

在命名实体识别中,f1 分数用于评估训练模型的性能,特别是,该评估是针对每个实体的,而不是令牌。

在许多机器学习框架中都实现了评估 f1 分数的功能。然而,它的目标是分类任务,而不是像命名实体识别那样的序列标记。

幸运的是,Keras 允许我们通过回调类在训练期间访问验证数据。通过扩展回调,我们可以评估命名实体识别的 f1 值。

下面是一个示例代码,用于在每个时期结束时计算和打印 f1 分数、召回率和精确度。你不必自己实现这段代码,它包含在 seqeval 包中:

import numpy as np
from keras.callbacks import Callback
from seqeval.metrics import f1_score, classification_reportclass F1Metrics(Callback):def __init__(self, id2label, pad_value=0, validation_data=None):"""Args:id2label (dict): id to label mapping.(e.g. {1: 'B-LOC', 2: 'I-LOC'})pad_value (int): padding value."""super(F1Metrics, self).__init__()self.id2label = id2labelself.pad_value = pad_valueself.validation_data = validation_dataself.is_fit = validation_data is Nonedef find_pad_index(self, array):"""Find padding index.Args:array (list): integer list.Returns:idx: padding index.Examples:>>> array = [1, 2, 0]>>> self.find_pad_index(array)2"""try:return list(array).index(self.pad_value)except ValueError:return len(array)def get_length(self, y):"""Get true length of y.Args:y (list): padded list.Returns:lens: true length of y.Examples:>>> y = [[1, 0, 0], [1, 1, 0], [1, 1, 1]]>>> self.get_length(y)[1, 2, 3]"""lens = [self.find_pad_index(row) for row in y]return lensdef convert_idx_to_name(self, y, lens):"""Convert label index to name.Args:y (list): label index list.lens (list): true length of y.Returns:y: label name list.Examples:>>> # assumes that id2label = {1: 'B-LOC', 2: 'I-LOC'}>>> y = [[1, 0, 0], [1, 2, 0], [1, 1, 1]]>>> lens = [1, 2, 3]>>> self.convert_idx_to_name(y, lens)[['B-LOC'], ['B-LOC', 'I-LOC'], ['B-LOC', 'B-LOC', 'B-LOC']]"""y = [[self.id2label[idx] for idx in row[:l]]for row, l in zip(y, lens)]return ydef predict(self, X, y):"""Predict sequences.Args:X (list): input data.y (list): tags.Returns:y_true: true sequences.y_pred: predicted sequences."""y_pred = self.model.predict_on_batch(X)# reduce dimension.y_true = np.argmax(y, -1)y_pred = np.argmax(y_pred, -1)lens = self.get_length(y_true)y_true = self.convert_idx_to_name(y_true, lens)y_pred = self.convert_idx_to_name(y_pred, lens)return y_true, y_preddef score(self, y_true, y_pred):"""Calculate f1 score.Args:y_true (list): true sequences.y_pred (list): predicted sequences.Returns:score: f1 score."""score = f1_score(y_true, y_pred)print(' - f1: {:04.2f}'.format(score * 100))print(classification_report(y_true, y_pred, digits=4))return scoredef on_epoch_end(self, epoch, logs={}):if self.is_fit:self.on_epoch_end_fit(epoch, logs)else:self.on_epoch_end_fit_generator(epoch, logs)def on_epoch_end_fit(self, epoch, logs={}):X = self.validation_data[0]y = self.validation_data[1]y_true, y_pred = self.predict(X, y)score = self.score(y_true, y_pred)logs['f1'] = scoredef on_epoch_end_fit_generator(self, epoch, logs={}):y_true = []y_pred = []for X, y in self.validation_data:y_true_batch, y_pred_batch = self.predict(X, y)y_true.extend(y_true_batch)y_pred.extend(y_pred_batch)score = self.score(y_true, y_pred)logs['f1'] = scoreid2label = {1: 'B-LOC', 2: 'I-LOC'}
f1score = F1Metrics(id2label)

定义模型,并在拟合函数中添加回调:

model.fit(x_train, y_train, validation_data=(x_valid, y_valid),epochs=1,batch_size=32,callbacks=[f1score])

培训期间的打印输出如下所示:

Epoch 1/1
541/541 [==============================] - 46s 85ms/step - loss: 9.5729- f1: 53.24precision    recall  f1-score   supportPER     0.5754    0.4484    0.5040      1617ORG     0.3798    0.4395    0.4075      1661MISC     0.4202    0.4387    0.4293       702LOC     0.6886    0.7650    0.7248      1668avg / total     0.5320    0.5381    0.5315      5648

格式类似于 scikit-learn 的分类 _ 报告功能。

就是这样。祝您愉快!

https://github.com/chakki-works/seqeval

如何计算卫星图像统计数据并将其用于熊猫

原文:https://towardsdatascience.com/how-to-compute-satellite-image-statistics-and-use-it-in-pandas-81864a489144?source=collection_archive---------15-----------------------

从 Sentinel 2 影像中获取分区统计数据,并与您的 Pandas 数据框合并。洪灾区 NDWI 水指数计算演练。

Example of Zonal Statistics — Elevation DEM overlayed on derived statistics (Max elevation in each grid shown)

卫星数据非常密集,使用像元来存储值。但是,在许多情况下,您只想将卫星(栅格)影像的摘要转换为表格格式 CSV 或 Pandas 数据框。

让我们举例说:您有一个数字高程模型(DEM)。DEM 图像清晰地显示了该区域的高程和地形。现在,如果您想要获取高程值并整合您拥有的表格数据(例如,建筑物)来获取每座建筑物的高程,该怎么办呢?

从光栅图像导出表格输出(汇总统计)的过程称为区域统计。

在本教程中,我们将学习如何从栅格数据中提取值,并以表格格式存储这些值(Pandas Dataframe)。

本教程的数据集和代码可以在 Github 中找到。让我们从探索数据开始。

数据探索

本教程的数据集是 2019 年 11 月 1 日在索马里贝莱德文拍摄的哨兵图像。该地区在此期间被淹没,我们计算 NDWI 来测量水压力水平。我们用的是 Google Colab 笔记本,直接从 URL 下载笔记本里的数据。

让我们导入本教程中使用的库。

import pandas as pd
import numpy as np
import geopandas as gpd
import rasterio as rio
from rasterio.plot import show
from rasterio.mask import mask
import matplotlib.pyplot as plt

使用 Rasterio,您可以读取 Sentinel 2 图像的不同波段。在这种情况下,我们读取波段 8 (NIR)、4(红色)、3(绿色)和 2(蓝色)。

b8 = rio.open(“/content/Data/20191101/B08–20191101.tif”)
b4 = rio.open(“/content/Data/20191101/B04–20191101.tif”)
b3 = rio.open(“/content/Data/20191101/B03–20191101.tif”)
b2 = rio.open(“/content/Data/20191101/B02–20191101.tif”)

让我们看看图像的宽度和高度。我只使用 b4,但你可以检查是否所有带都有相同的重量和长度。

b4.width,
b4.height

我们绘制数据,以查看和探索我们拥有的卫星图像。在这里,我只绘制波段 3。

fig, ax = plt.subplots(1, figsize=(12, 10))
show(b3, ax=ax)
plt.show()

如果你想知道如何用 Rasterio 制作 RGB 图像,我这里有一个教程你可能想看。

[## Python 和 Jupyter 笔记本中的卫星图像访问和分析

使用 Python 在 Jupyter 笔记本中访问、预处理、分析和可视化卫星图像。

towardsdatascience.com](/satellite-imagery-access-and-analysis-in-python-jupyter-notebooks-387971ece84b)

该区域的哨兵 2 影像(仅波段 3)如下所示。

让我们也读一下 buildings 表,我们将使用它来存储从卫星图像得到的统计概要。请注意,您可以使用其他多边形,如区域、矩形网格,而不是本例中的建筑多边形。

我们使用 Geopandas 来读取数据。

buildings = gpd.read_file(“/content/Data/shapefiles/osm_buildings.shp”)
buildings = buildings[[“osm_id”,”building”, “geometry”]]
buildings.head()

这是表格的前五行。我们有每个建筑的几何列、osm_id 和建筑列。

我们也可以在哨兵 2 号图像的顶部绘制建筑物。

fig, ax = plt.subplots(figsize=(12, 10))
show(b4, ax=ax)
buildings.plot(ax=ax, color=”white”, alpha=.50)
plt.show();

建筑物在图像中被标记为白色并被覆盖,如下所示。图为蜿蜒的谢贝利河延伸到城市(居民区)的范围。

现在让我们计算哨兵 2 号图像的 NDWI 值。

计算归一化差异水指数(NDWI)

为了计算 NDWI 值,我们使用以下公式:

(频段 3 —频段 8)/(频段 3 +频段 8)

所以,让我们用拉斯特里奥的这个公式来计算。

green = b3.read()
nir = b8.read()
ndwi = (nir.astype(float)-green.astype(float))/(nir+green)

可以使用 Rasterio 绘制 NDWI 阵列,如下所示。

fig, ax = plt.subplots(1, figsize=(12, 10))
show(ndwi, ax=ax, cmap=”coolwarm_r”)
plt.show()

NDWI 图清楚地显示了谢贝利河(蓝色)附近未标注日期的区域。洪水淹没了居民区。

我们可以将 NDWI 阵列保存为光栅图像,以便以后使用。

meta = b4.meta
meta.update(driver='GTiff')
meta.update(dtype=rio.float32)
with rio.open('NDWI.tif', 'w', **meta) as dst:dst.write(ndvi.astype(rio.float32))# Read the saved 
ndwi_raster = rio.open(“NDWI.tif”)

现在,我们已经计算了 NDWI 值,是时候从 NDWI 栅格影像中获取统计数据并将其合并到建筑物表中了。我们使用栅格掩膜功能从 NDWI 栅格图像中获取像元值。

以下是一个小函数,它将像元值屏蔽到数据框表中。

def derive_stats(geom, data=ndwi_raster, **mask_kw):masked, mask_transform = mask(dataset=data, shapes=geom,)crop=True, all_touched=True, filled=True)return masked

我们可以像这样得到我们想要的值。假设我们对获取每栋建筑的 NDWI 平均值感兴趣。我们为“mean_ndwi”创建了一个列,并传递我们函数来应用建筑物的几何图形,还使用 Numpy 应用到 mean。

buildings[‘mean_ndwi’] = buildings.geometry.apply(derive_stats).apply(np.mean)

或者,获取每个建筑物的最大 NDWI 值。

buildings[‘max_ndwi’] = buildings.geometry.apply(derive_stats).apply(np.max)

我们的表现在有两个新列,mean_ndwi 和 max_ndwi,我们在其中存储每个建筑物的平均和最大 ndwi 值。

该数据集还包括该地区以前数据(洪水之前)中的哨兵图像。在“数据”文件夹中,有“20191002”文件夹。尝试使用这些图像计算平均和最大 NDWI 值。将此与我们为 20191101(洪水期)计算的图像得出的统计数据进行比较。

结论

在本教程中,我们已经了解了如何从 Sentinel 2 影像中计算 NDWI 值,并从中获取汇总统计数据。代码和 Google Colab 笔记本可以在这个 Github 存储库中找到。

[## shaka som/区域统计

python-Rasterio 和 Geopandas 计算分区统计数据卫星数据密集,并使用像元存储值…

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

或者直接在这个谷歌合作实验室笔记本上

[## shaka som/区域统计

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/shakasom/zonalstatistics/blob/master/Zonal_Statistics_Sentinel.ipynb)

如何用强大的临床研究工具征服队列分析

原文:https://towardsdatascience.com/how-to-conquer-cohort-analysis-674a2dea3472?source=collection_archive---------25-----------------------

为什么你的医生比你更了解客户维系

在 SaaS 或消费者订阅环境中,客户流失的微小变化会从根本上影响收入增长。

产品经理、增长黑客、营销人员、数据科学家和投资者都需要了解商业决策如何影响用户留存。

随着如此多的经常性收入业务上市,硅谷现在应该了解情况了。

然而,信不信由你,医学研究人员比你更擅长衡量客户保持率。

什么?

听起来很大胆,但事实并非如此。几十年来,临床研究人员已经提炼出精确而严谨的方法来衡量保留率——只不过他们衡量的不是客户保留率,而是患者存活率

生死的严重性意味着研究人员在衡量治疗效果时非常小心。

为此,临床研究人员使用一种叫做 卡普兰-迈耶估计量 的统计方法。该公式巧妙地解决了队列保持分析中经常出现的一个问题:在不同寿命的队列组内部和之间进行有效的比较:

尽管公式很花哨,但使用 Kaplan-Meier (KM)的生存分析实际上非常简单,并且比其他方法提供了更好的结果:

在这篇文章中,我将解释这些结果,用简单的术语分解 KM 估算器,并说服你用它来进行保留分析。

底线:如果你是一名经营者或投资者,想要恰当地衡量客户群保持率,那么卡普兰-迈耶是一个不错的选择。

两个必然:死亡和流失

KM 估算器帮助我们处理的核心问题是缺失数据

队列数据本身就有缺陷,因为最近的队列与老队列相比数据点更少。例如,一个五个月大的队列只能与一个十个月大的队列的前五个月进行比较。七个月前获得的客户群的保留率只能合理地与前七个月老客户群的保留率进行比较。

假设您有前 12 个月的完整保留历史,并且您想要预测新获得客户的 12 个月保留曲线。怎么做一点都不明显。

为了更好地理解这一点,让我们想象一个只有五个群组的简单例子:

你可以先试着计算不同群体的平均保持率。这是有问题的,原因有二:

  • 如果我们的队列大小不同,简单的平均值就不具有代表性
  • 对于任何给定的月份,我们只能对至少存活了这么长时间的群体进行平均,因此随着时间的推移,我们实际上对越来越少的群体进行平均

下面可以看到第二期。无论是简单平均值还是加权平均值,当表现在群组间波动时,我们都会得到奇怪的结果:

假设我们不重新添加之前涌入其原始群体的返回用户,那么在下降后,保留率不可能上升——这是一条单行道。这是我们有缺陷的方法的产物,因为根据定义,5 个月的保留期不能超过 4 个月。

第三个相关的问题出现在将一组群组与其他群组进行比较时,例如,将 2016 年的每月群组与 2017 年的群组进行比较。正如我们刚刚展示的,使用平均值来估计每个群组的保留曲线是行不通的,这意味着我们也无法将一个群组与另一个群组进行比较。

有问题吗?问问你的医生

信不信由你,临床研究人员一直在处理同样的问题。

客户群类似于在不同时间开始治疗的患者群体。这里的“治疗”是获得客户的时间,“死亡”只是流失。

或者,想象一下,如果“2016 年队列”和“2017 年队列”,而不是按年份分组的队列,是在临床试验中接受不同治疗的群体。我们想量化两组患者存活率(客户保持率)的差异。

制药公司和其他研究机构经常面临这一问题。患者在不同的时间开始治疗。患者因死亡而退出研究,但也因搬家或决定停止服药而退出研究。

这在任何患者的临床试验记录的开始、中间和结尾都造成了大量的数据缺失问题,使有效性和安全性的分析变得复杂。

为了解决这个问题,1958 年,数学家爱德华·卡普兰和统计学家保罗·迈耶,共同创建了卡普兰-迈耶估计量。也被称为乘积限估计器,该方法有效地处理了缺失数据问题,提供了对任何一点的生存概率的更精确的估计。

卡普兰-迈耶背后的核心理念:

到任何时间点的估计存活概率是每个先前时间间隔的累积存活概率,计算为先前存活概率的乘积

上面那个奇怪的公式只是简单地将一堆概率彼此相乘,以找到在某一点上生存的累积概率。

这些概率从何而来?直接来自数据

KM 表示,我们对从一个月到下一个月的生存概率的最佳估计正是我们数据集中该月的加权平均保留率(在统计学术语中也称为 最大似然估计器 )。因此,如果在一组群组中,我们有 1000 个客户从第一个月开始,其中 600 个存活到第二个月,我们对从第一个月到第二个月存活的“真实”概率的最佳猜测是 60%。

下个月我们也这样做。将第 3 个月存活的客户数除以第 2 个月存活的客户数,得到第 2 个月到第 3 个月的估计存活概率。如果我们没有一个群组的第 3 个月的数据,因为它只有两个月大,我们从我们的第 3 个月生存计算中排除这些客户。

重复尽可能多的群组/月份,在每次计算中排除当前期间的任何群组缺失数据。然后,要计算任何给定月份的生存概率,将该月份的个人月度(条件)概率相乘。

虽然这是一种病态的想法,但是测量患者存活率在功能上等同于测量客户保持率,因此我们可以很容易地将知识管理转化为客户群组分析!

测试卡普兰-迈耶

让我们通过将 Kaplan-Meier 估计量应用到前面的例子中来更清楚地说明这一点。

第 1 个月存活的概率是 69% (第 1 个月存活的客户总数除以第 0 个月的总数)。假设客户在第 1 个月存活,则第 2 个月存活的概率为 72% (第 2 个月存活的客户总数除以第 1 个月的总数,不包括缺少第 2 个月数据的最后一组客户)。所以至少存活两个月的累计概率是 69% x 72% = 50% 。冲洗,洗涤,然后每个月重复一次。

并排比较揭示了 KM 的优越性:

知识管理的伟大之处在于它利用了我们拥有的所有数据,甚至是我们观察较少的年轻群体。例如,虽然第 3 个月时所有可用群组的平均值仅使用群组 1-3 的数据,但由于其累积性,KM 估计值有效地纳入了较新群组的早期保留。这产生了 38%的 3 个月保留率估计值,高于我们在第 3 个月实际测量的任何群组。

这正是我们想要的-第 4 组和第 5 组都比第 1 组和第 3 组更大,也更容易保持。因此,从这些群组中随机挑选的客户的 3 个月保留率很可能会超过历史平均水平,因为该客户很可能在群组 4 或 5 中。

使用所有的数据也很好,因为这使得我们对尾部概率的估计比我们只依赖我们保留了那么久的客户数据要精确得多。

卡普兰-迈耶曲线还通过遵守概率基本定律修正了留存曲线右尾的不稳定行为:累积概率只会随着数字的增加而下降。

95%的医生推荐

这种分析很容易扩展。让我们回到 2016 年与 2017 年的例子——我们可以对每一组队列进行卡普兰-迈耶计算,然后比较所得的生存曲线,突出两组之间预期保留的差异。

虽然我不会在这里讨论,但是你也可以计算卡普兰-迈耶曲线的 p 值、置信区间和统计显著性检验。这让你可以做出严格的陈述,如“2018 年相对于 2017 年的队列保留率的改善具有统计学意义(在 5%的水平)”-酷的东西:

对于那些花时间分析客户群体数据的人来说,Kaplan-Meier 是一个强大的工具。知识管理已经在严格的临床试验中经受了考验——如果说有什么不同的话,那就是它没有在技术运营商和投资者中更受欢迎。

如果你是一名产品经理、增长黑客、营销人员、数据科学家、投资者或任何其他理解客户保持分析的重要性的人,卡普兰-迈耶估算器应该是你的分析武库中的一件有价值的武器。

最初发表于https://whoisnnamdi.com

推特 上关注我,听听我对科技商业和经济的看法。

如何在 docker 中包含你的第一个 Django 并从 AWS 中访问它

原文:https://towardsdatascience.com/how-to-contain-your-first-django-in-docker-and-access-it-from-aws-fdb0081bdf1d?source=collection_archive---------10-----------------------

今天,许多初级软件工程工作需要一系列技术,包括 Django、python、docker 和 AWS。如果你是一个初学者,并且想了解这些技术,那么你来对地方了。通过这篇文章,我将指导您操作这些工具并创建您的第一个 Python Django 应用程序,该应用程序包含在 docker 中并可从 AWS 访问。

您只需要:

Docker Hub 免费账户:https://hub.docker.com/

AWS 免费账户https://aws.amazon.com/account/

MAC 或 Windows 笔记本电脑。

Pycharm 框架https://www.jetbrains.com/pycharm/download/

一个大脑:)

从你的宝贵时间最多一个小时。

你准备好了吗?

所以让我们开始吧…第一步是打开你的 pycharm 并创建一个新项目。

接下来,您必须在 pycharm 中安装 Django 库:

pip install django

然后,只需通过下面的命令启动您的项目(我们将项目命名为 DjangoDocker ,但是您可以命名为其他名称)。

django-admin startproject DjangoDocker

这将创建项目目录和里面的几个文件,我们稍后将详细检查它们。

之后,您需要使用下面的命令在 Django 项目中创建第一个应用程序:

python manage.py startapp myApp

这将在您的主项目目录中创建一个新目录,它将包含以下文件:

您可能会注意到,我们可以在同一个 Django 项目中创建多个应用程序,这在我们想要创建一个后端 API 并在多个项目中使用它的情况下非常有用。

现在让我们试着在我们的第一个应用程序中填充代码,看看我们如何从云中 dockerize 和访问它!!

在接下来的步骤中,我们将填充获得“Salam World”Django 应用程序所需的最低编码。

首先,打开 myApp 目录下的文件“views.py ”,并填入以下代码:

from django.shortcuts import render# Create your views here.
from django.http import HttpResponse
def index(request):return HttpResponse(**" Django on Docker on AWS "**)

然后,您应该向 Django 表明该文件将成为您的索引,为此,只需将以下代码放入 myApp => urls.py

并且只需在 urls.py (根文件夹)填充根 URL 路径即可。

from django.contrib import admin
from django.urls import include, path
path(‘<appname>/’, include(‘<appname>.urls’)),

之后,您可以启动数据库并检查您的应用程序是否正常工作:

## initiate the database
python manage.py migrate## check it works
python manage.py runserver

只要启动下面的网址,你应该会看到类似的结果:

将代码推送到 docker image 之前的一个中间步骤是将它放在 GITHUB 中,以跟踪对每次迭代所做的各种更改。这也将允许您实施您的 DevOps CI/CD 管道,以便直接将更改和“自动”推送到 AWS,而无需重复所有这些步骤。

## initiate GIT
# Go to directory and tape:
git init
## Create and fill .gitignore to untrack files
git status #( to check )
git add — all .
git commit -m “My first commit”## push to GitHIB
## Connect to Github (login/password)
## create a new repo
git remote add origin [https://github.com/](https://github.com/)<login>/<repo>.git
git push -u origin master

现在,我们将看到如何将代码包含在 docker 映像中,并将其推送到 docker hub。

要创建 docker 映像,只需在 Django 根目录中创建以下 3 个文件:

docker file
docker-compose . yml
requirements . txt

— — — — — Dockerfile
# We Use an official Python runtime as a parent image
FROM python:3.6
# The enviroment variable ensures that the python output is set straight
# to the terminal with out buffering it first
ENV PYTHONUNBUFFERED 1
# create root directory for our project in the container
RUN mkdir /<dir-in-container>
# Set the working directory to /music_service
WORKDIR /<dir-in-container>
# Copy the current directory contents into the container at /music_service
ADD . /<dir-in-container>/
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
EXPOSE 8000
CMD exec gunicorn <Django-project_name>.wsgi:application — bind 0.0.0.0:8000 — workers 3— — — — docker-compose.yml
version: ‘3’
services:web:build: .command: bash -c “python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000”container_name: <dir-in-container>volumes:— .:/<dir-in-container>ports:— “8000:8000”— — — — requirements.txt
Django==2.1.5
gunicorn==19.9.0

之后,通过运行以下命令创建 docker 映像:

docker build -t <DockerLogin>/<Docker-Image_name> .
# PS: don’t forget the “.” at the end of the above command

其中 DockerLogin 是您的 docker Hub 登录名, Docker-Image_name 是您想要的图像名称。

要测试您的映像是否正常工作,只需启动:

docker run -p 8000:8000 -i -t <DockerLogin>/<Docker-Image_name>

您应该会在路由端口 8000 上看到您声明的 IP 0.0.0.0 的结果,如下所示:

要将图像推入 docker hub,只需启动以下命令:

docker push <DockerLogin>/<Docker-Image_name>

PS :检查你的本地 docker 是否在运行,如下图所示(针对 Mac 用户)。

现在,您的 Django 应用程序被推送到 Docker Hub 映像,任何人都可以从 Hub 中取出它,并在 Docker 中实例化它,以便在他的本地环境中运行它,而不用担心依赖关系,也不用使用 Django、Python 等。本地安装。

现在让我们看看如何托管您的 docker 映像并从 AWS 访问它。

首先,您需要创建一个 JSON 文件,告诉 AWS 如何找到您的 docker 映像,请参见下面的示例:

— — — -Dockerrun.aws.json
{“AWSEBDockerrunVersion”: “1”,“Image”: {“Name”: “abdel1979/<image-name>”,“Update”: “true”},“Ports”: [{“ContainerPort”: “8000”}],“Logging”: “/var/log/nginx”
}

之后,只需在您的 AWS 帐户中导航至管理控制台:

然后交给弹性豆茎。

之后,通过命名创建一个新的应用程序,然后选择 web 服务器环境:

接下来,填写所需信息,环境名域名并选择 docker 作为平台,最后上传你的 JSON 文件。

最后,等待几分钟来创建您的环境,一旦准备好,打开您选择的域,您将看到您的应用程序显示如下:

我们到了:)
一如既往,我希望你学到了新的东西。

萨拉姆,

如何使用 R 正确解释连续变量和分类变量的相互作用

原文:https://towardsdatascience.com/how-to-correctly-interpret-your-continuous-and-categorical-variable-interactions-in-regressions-51e5eed5de1e?source=collection_archive---------4-----------------------

理解你的回归

当你有互动时,解释系数可能是棘手的。你对它们的解释正确吗?

Photo by Jon Robinson on Unsplash

理解和解释回归结果的能力是有效数据分析的基础。了解每个术语在模型规范中是如何表示的,对于准确解释模型的结果至关重要。然而,通常很容易通过查看 t 统计或 p 值得出结论,并假设模型做了您想要它做的事情,而没有真正理解在引擎盖下发生了什么。我在给本科生讲授统计学时经常观察到的一个错误是,当包含带有分类变量的交互项时,如何解释连续变量的主要效应。

这里我提供了一些 R 代码来演示为什么你不能简单地把系数解释为主要效果,除非你指定了一个对比度。

TLDR:当你指定你的分类变量是一个以 0 为中心的对比变量时,你应该只把与分类变量相互作用的连续变量的系数解释为平均主效应。如果分类变量是虚拟编码的,你不能把它解释为平均主效应。

步骤 1:模拟数据

为了举例说明,我将创建一个包含变量IncomeAgeGender的假数据集。我的规范是,对于男性,IncomeAge的相关系数 r = .80,对于女性,IncomeAge的相关系数 r = .30。

从这个规格来看,**Age**对** **Income** 的平均作用,对 **Gender** 的控制应为. 55 (= (.80 + .30) / 2)。至于平均群体差异,假设男性平均收入 2 美元,女性平均收入 3 美元。**

分别生成每个性别的数据,然后连接起来创建一个组合数据帧:data。使用包MASS中的mvrnormR中生成数据:

这段代码还检查随机生成的数据是否具有我们指定的相关性和平均值。

## Correlation between Income & Age for Male: 0.8 
## Correlation between Income & Age for Female: 0.3 
## Mean Income for Male: 2 
## Mean Income for Female: 3

第二步:错误地估计你的主要效果

现在我们有了样本数据,让我们看看当我们天真地运行一个线性模型,从AgeGender以及它们的相互作用预测Income时会发生什么。

## 
## Call: 
## lm(formula = "Income~Age*Gender", data = data) 
## 
## Residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.4916 -0.4905 -0.0051  0.5044  3.2038 
## 
## Coefficients: 
##                Estimate Std. Error t value Pr(>|t|)     
## (Intercept)     3.00000    0.02521  118.99   <2e-16 *** 
## Age             0.30000    0.02522   11.89   <2e-16 *** 
## GenderMale     -1.00000    0.03565  -28.05   <2e-16 *** 
## Age:GenderMale  0.50000    0.03567   14.02   <2e-16 *** 
## --- 
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## ## Residual standard error: 0.7973 on 1996 degrees of freedom 
## Multiple R-squared:  0.4921, Adjusted R-squared:  0.4913 
## F-statistic: 644.6 on 3 and 1996 DF,  p-value: < 2.2e-16

上面的模型摘要打印了InterceptAgeGenderMaleAge:GenderMale的系数。我们可以清楚地看到,Age的效果是 0 . 30,这当然不是控制性别的平均效果,而仅仅是对女性群体的效果。GenderMale的效果是$-1,即男性组比女性组少挣多少钱,截距为$3。最后,相互作用Age:GenderMale代表Age的相关性男性比女性多多少(0.5 = 0.8-0.3)。

重要的是,这是带有分类变量的默认 R 行为,它按字母顺序将第一个变量设置为参考级别*(即截距)。所以在我们的例子中,女性被设定为我们的参考水平。然后,我们的分类变量被虚拟编码(也称为治疗对比),因此女性为 0,男性为 1,这可以通过使用函数contrasts来验证。**

contrasts(data**$**Gender)##        Male 
## Female    0 
## Male      1

第三步:估计你的主要效果的正确方法

那么,我们需要做什么来获得AgeIncome控制Gender平均效果,同时保持交互?答案是:指定以 0 为中心的对比度,使女性编码为-.50,男性编码为. 50。让我们看看当我们指定对比度并重新运行我们的模型时会发生什么。****

## 
## Call: 
## lm(formula = "Income~Age*Gender", data = data) 
## 
## Residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.4916 -0.4905 -0.0051  0.5044  3.2038 
## 
## Coefficients: 
##             Estimate Std. Error t value Pr(>|t|)     
## (Intercept)  2.50000    0.01783  140.23   <2e-16 *** 
## Age          0.55000    0.01784   30.84   <2e-16 *** 
## Gender1     -1.00000    0.03565  -28.05   <2e-16 *** 
## Age:Gender1  0.50000    0.03567   14.02   <2e-16 *** 
## --- 
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Residual standard error: 0.7973 on 1996 degrees of freedom 
## Multiple R-squared:  0.4921, Adjusted R-squared:  0.4913 
## F-statistic: 644.6 on 3 and 1996 DF,  p-value: < 2.2e-16

我们再次得到四个术语,但是它们被指定为InterceptAgeGender1Age:Gender1Age效应是 0.55,这正是我们在生成数据时指定的跨性别平均效应(0.55 =(0.8+0.3)/2)。Age:Gender1交互作用为 0.5,这是性别间年龄效应的差异(0.5 = 0.8–0.3)。Gender1的效果是$-1,它代表两性之间的平均差异($2-$3),正如我们的对比所指定的。参考值Intercept是 2.5 美元,这是不同性别的平均收入(($2+$3) / 2)。

再一次,我们可以用下面的例子来验证我们的对比:

contrasts(data**$**Gender)##        [,1]
## Female -0.5
## Male    0.5

结论

我希望这个例子表明,当你建立连续变量和分类变量之间相互作用的线性模型时,你需要注意它们是如何指定的(虚拟编码或对比),因为这将改变你解释系数的方式。

最重要的是,当您已经将分类变量指定为以 0 为中心的对比度时,您应该只将与分类变量相互作用的连续变量的系数解释为平均主效应。如果分类变量是虚拟编码的,你不能把它解释为主要效应,因为它们成为参考水平效应的估计值。

如需了解更多信息,请访问 stackexchange 和 r-bloggers 查看这个问题的更多答案,这个问题已经在网上被多次询问。

附加信息

如果希望分类变量被视为虚拟代码,可以将其设置为处理对比。它复制了 r 提供的默认结果。

## 
## Call: 
## lm(formula = "Income~Age*Gender", data = data) 
## 
## Residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.4916 -0.4905 -0.0051  0.5044  3.2038 
## 
## Coefficients: 
##             Estimate Std. Error t value Pr(>|t|)     
## (Intercept)  3.00000    0.02521  118.99   <2e-16 *** 
## Age          0.30000    0.02522   11.89   <2e-16 *** 
## Gender2     -1.00000    0.03565  -28.05   <2e-16 *** 
## Age:Gender2  0.50000    0.03567   14.02   <2e-16 *** 
## --- 
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ## 
## Residual standard error: 0.7973 on 1996 degrees of freedom 
## Multiple R-squared:  0.4921, Adjusted R-squared:  0.4913 
## F-statistic: 644.6 on 3 and 1996 DF,  p-value: < 2.2e-16

如果你运行模型而没有交互作用,那么即使你的分类变量是虚拟编码的,年龄的主要影响也是如你所料控制性别的平均影响。****

## 
## Call: 
## lm(formula = "Income~Age+Gender", data = data) 
## 
## Residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.5525 -0.5102 -0.0055  0.5424  3.2461 
## 
## Coefficients: 
##             Estimate Std. Error t value Pr(>|t|)     
## (Intercept)  3.00000    0.02642  113.56   <2e-16 *** 
## Age          0.55000    0.01869   29.43   <2e-16 *** 
## Gender2     -1.00000    0.03736  -26.77   <2e-16 *** 
## --- 
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Residual standard error: 0.8354 on 1997 degrees of freedom 
## Multiple R-squared:  0.4421, Adjusted R-squared:  0.4416 
## F-statistic: 791.3 on 2 and 1997 DF,  p-value: < 2.2e-16

感谢您的阅读,并随时查看我的其他与数据科学相关的帖子。

** [## 为什么有重要变量的模型可能是无用的预测器

统计模型中的重要变量不能保证预测性能

towardsdatascience.com](/why-models-with-significant-variables-can-be-useless-predictors-3354722a4c05) [## 机会是不够的:用排列评估模型的重要性

当训练机器学习模型进行分类时,研究人员和数据科学家经常比较他们的模型…

towardsdatascience.com](/chance-is-not-enough-evaluating-model-significance-with-permutations-e3b17de6ba04)**

如何使用 cobra 在 golang 中创建 CLI

原文:https://towardsdatascience.com/how-to-create-a-cli-in-golang-with-cobra-d729641c7177?source=collection_archive---------1-----------------------

Photo by Marvin Meyer on Unsplash

你有没有想过为什么在 GUI 的世界里,CLI 依然存在?当你自己造一个的时候你会更好的理解它。

当你学习 golang 的时候,你经常会碰到“golang 是构建 cli 工具的好工具”。这也让我着迷。所以,我试着动手做,找到了一些创建 cli 的教程,但大多数都不是基础的。在本教程中,我将尝试平滑学习曲线。

这是基本的 CLI 应用程序,我们将在其中介绍基本的 CLI 操作。我计划写另一篇关于高级 CLI 操作的文章,但那是以后的事了。

我们正在创建一个简单的数学 cli,它将能够完成以下两项工作:

  • 数字相加
  • 仅偶数或奇数的加法

我知道这些工作不符合你的期望,但相信我,在这之后,你会觉得建立一个 cli 很舒服。

什么是 CLI?(命令行界面)

CLI 根据软件工程的基本原理工作,接受输入,对其进行处理,然后给出输出。在 CLI 工具中,它不是一个闪烁的前端,而是从 黑色窗口 获取输入。记住,黑客帝国三部曲。

如果你使用的是 窗口 只需在start中键入cmdpowershell并回车,黑色窗口或蓝色窗口就是 cli。

cmd

在 Mac 或 Linux 中,它被称为terminal

命令行界面 ( CLI ) 是一种与计算机程序交互的手段,其中用户(或客户端)以连续文本行(命令行)的形式向程序发出命令。处理接口的程序被称为命令行解释器命令行处理器。— 维基百科

你可以使用很多 CLIs,比如 npm、node、go、python、docker、Kubernetes 等等。所有这些都是与软件交互的理想界面。

为什么他们还在使用 CLI?

  • 它重量轻,速度快。
  • 最少或没有依赖性。
  • 最适合系统管理和基于任务的自动化等。

理论讲够了,让我们从需求开始:

  • golang 已安装(我使用的是 go1.11.5 windows/amd64)
  • 眼镜蛇库(go get -u github.com/spf13/cobra/cobra)
  • 您选择的任何代码编辑器。(我用的是 VS 代码)

我推荐使用 VS 代码,安装微软的go扩展。这将根据代码更新导入语句。如果您使用新包,它将在保存时导入该包。如果某个包已导入但未被使用,它会将该包从导入中移除。

Cobra图书馆简介。我们将使用 cobra cli 来使用 cobra 库。我们将使用命令行界面来构建命令行界面😃

Cobra 既是一个用于创建强大的现代 CLI 应用程序的库,也是一个用于生成应用程序和命令文件的程序。

很多应用最广泛的 Go 项目都是用 Cobra 搭建的,比如: Kubernetes 、 Hugo 、 Docker (distribution) 等。— Github

Cobra 概念

Cobra 建立在命令、参数和标志的结构上。

  • 命令代表动作
  • Args 是事物
  • 标志是那些动作的修饰符

基本结构就像一个简单的句子

APPNAME Command Args --FlagsAPPNAME Command --Flags Args

为 Ex。

  • git clone URL -bare
  • go get -u URL
  • npm install package --save
  • docker run image -d

GOPATH 的之外创建一个新的项目目录。我已经为本教程创建了**my-calc**项目目录。你可以说出你的任何选择。

GOPATH 之外创建项目简化了本地文件的导入。初始化项目中的模块。该模块将保留该项目中需要和使用的所有库和依赖项。它类似于 nodejs 中的package.json。要了解关于这些模块的更多信息,请阅读这篇伟大的文章。

一个模块是一个相关 Go 包的集合,这些包作为一个单元一起被版本化。

模块记录精确的依赖需求,并创建可重复的构建。— [维基](http://A module is a collection of related Go packages that are versioned together as a single unit. Modules record precise dependency requirements and create reproducible builds.)

在您选择的命令行中打开项目目录。我用的是**bash** 。进入项目目录后,运行下面的命令来初始化模块。

**go mod init my-calc**

你可以注意到它在项目中创建了一个**go.mod**文件。

注意:默认情况下,在***$GOPATH***内创建模块是禁用的。如果你运行上面的命令— ***go: modules disabled inside GOPATH/src by GO111MODULE=auto; see ‘go help modules’***,你会得到这个错误。如果您仍然想在**$GOPATH**中创建 go 模块,那么首先将***GO111MODULE***环境变量设置为***on*** **export GO111MODULE=on**

现在,无论何时你在项目中使用任何第三方包,它都将把它保存为与他们版本的依赖关系。这样,即使库的新版本中引入了重大更改,您的项目也会按预期工作。

如果你还没有安装**cobra** 库,你可以使用下面的命令来安装。

go get -u github.com/spf13/cobra/cobra

使用cobra init命令初始化项目的 cli 脚手架。

cobra init --pkg-name my-calc

编辑:感谢布兰登卡顿,对 init 命令的更新。

它将用cobra库初始化my-calc项目。您可以观察到它在项目中创建了几个文件。

▾ my-calc/▾ cmd/root.gomain.go

main.gocli的切入点。在main.go内部,它正在调用cmd/root.goExecute函数。

// main.go
package main**import "my-calc/cmd"**func main() {**cmd.Execute()** }

我们来考察一下root.go

rootCmd

Root 命令是任何 cli 的基本命令。为了前任。go get URL**go** 是这里的根命令,**get****go** 的子命令。在**root.go**中,用cobra命令初始化**rootCmd** 结构变量。cli 中的所有其他命令都将是**rootCmd**的子命令。

在编辑器中打开root.go并在rootCmd中取消注释

**Run: func(cmd *cobra.Command, args []string) {},**

并将fmt.Println("Hello CLI")粘贴在花括号内。

**Run: func(cmd *cobra.Command, args []string) {fmt.Println("Hello CLI"},**

⚠️不要去掉右花括号后面的逗号。它将抛出语法错误。

打开my-calc项目内的终端并运行

go install my-calc

该命令将在**$GOPATH/bin** 文件夹中生成项目的二进制或可执行文件。

现在在终端中运行**my-calc** 。因为它保存在 bin 文件夹中,所以您不必为此设置环境变量。

cli 的名称是 rootCmdmy-calc 是 rootCmd。

您将看到类似如下的输出。

hello-cli

初始化

每当一个包在 golang 中初始化时,这是第一个被调用的函数。**cobra.OnInitialize(funcDeclarations)** 在命令的初始化中追加用户自定义函数。 每当运行或调用命令时,它将首先执行命令初始化中的所有函数,然后运行 execute 方法。 这种初始化可以用于加载配置文件或者可以用作构造函数。这完全取决于你的用例以及你的创造力。

我想我在这里失去了你。我们用一个例子来理解这个。

root.go中,命令是**rootCmd**

**cobra.OnInitialize(initConfig)****rootCmd**的初始化中追加了**initConfig**函数声明。所以,每当**rootCmd** 的 execute 方法(**RUN: func**)运行时,**rootCmd** 将首先运行**initConfig**函数。一旦所有初始化函数的执行结束,它将运行**rootCmd****RUN: func**执行方法。

为了可视化,在**initConfig** 功能中添加一条打印消息。

func initConfig() { **fmt.Println("inside initConfig")
...**

保存更改。打开my-calc项目内的终端。

重建二进制**go install my-calc**

go install my-calc

运行**my-calc**。无论何时在 cli 中进行任何更改,都必须重新构建二进制文件。运行**go install my-calc**以在 cli 命令中反映它。

initConfig

可以看到initConfig先运行,后Hello CLI运行。

为了理解 cli 的完整流程,在**main.go**中的**init**函数内添加一条消息,在**main** 函数内添加一条消息。

// root.gofunc init() {**fmt.Println("inside init")** cobra.OnInitialize(initConfig)
...// main.gofunc main() {**fmt.Println("inside main")**cmd.Execute()
}

保存更改。重建二进制**go install my-calc**并运行**my-calc**

cli flow

现在,您已经了解了 cli 命令流。

init函数中最后一个是flags

标志就像命令的修饰符。你可以把它们看作是条件动作。我们将在教程的后面了解更多。

有两种类型的旗帜**Persistent Flags****Local Flags**

  • 持久标志:该标志可用于分配给它的命令以及该命令的所有子命令。
  • 本地标志:该标志仅适用于其被分配到的命令。

初始化配置

该功能设置主目录中的配置路径,配置文件名为.my-calc。如果配置文件存在,它将使用该文件。

**viper** 库以 go 应用的配置解决方案而闻名。它读取 JSON、TOML、YAML、HCL、envfile 和 Java 属性配置文件。它不仅仅是读取配置。要了解更多信息,请点击此链接。

通过该功能,我们完成了root.go检查。它有点长,但是理解我们正在使用的东西是有好处的。

注意:现在如果你愿意,你可以从*root.go**main.go*中删除所有的打印语句。为了保持代码的整洁,我已经删除了所有的打印语句。

是时候在我们的 cli 中添加一些命令了。我们已经创建了一个命令**my-calc**作为rootCmd,它返回 Hello CLI。

添加数字

在项目目录中打开终端并创建一个名为**add**的命令。添加新命令的 cobra 命令是

**cobra add <commandName>**

**cobra add add****// output**
add created at C:\Work\golang\my-calc

查看cmd文件夹,里面添加了一个add.go文件。

打开add.go。它类似于root.go

首先,一个addCmd结构变量被声明为*cobra.Command类型。

*cobra.CommandRUN,它是一个 func,带***cobra.Command**的指针和一段字符串**[]string**

然后在init函数中初始化。在init中,添加到**rootCmd**T34 中。我们可以理解为**rootCmd**的子命令或子命令**addCmd**

func init() {**rootCmd.AddCommand(addCmd)**

在终端中,使用**go install my-calc**命令重建二进制文件,并运行**my-calc add**

add called

add命令工作正常。是时候修改一下加一串数字了。

这些命令只接受一部分字符串作为参数。为了将数字相加,我们首先必须将string转换成int,然后返回结果。我们将使用strconv库将string转换成int

导入strconv包。

import ("fmt"**"strconv"** "github.com/spf13/cobra"
)

add.go内部,创建一个新的**addInt** 函数。

// add.go**func addInt(args []string) {** var sum int // iterate over the arguments// the first return value is index of args, we can omit it using _for _, ival := range args { // strconv is the library used for type conversion. for string// to int conversion Atio method is used.** itemp, err := strconv.Atoi(ival)**if err != nil {fmt.Println(err)}sum = sum + itemp} fmt.Printf("Addition of numbers %s is %d", args, sum)
}

保存更改。

addCmd变量中,更新RUN功能。删除打印信息,用args调用addInt功能。

// addCmd
Run: func(cmd *cobra.Command, args []string) {addInt(args)
},

使用go install my-calc重建二进制文件。

运行my-calc add 2 3

⚠️Don't 忘记了争论之间的空隙。

add int

您可以传递任意多个参数。如果你记得 args 是一段字符串。但是这个功能是有限制的。它只能将整数相加,不能将小数相加。在addInt函数中,我们将字符串转换成int而不是float32/64

是时候在addCmd中引入一只flag了。该标志将帮助 cli 决定是int 操作还是float操作。

add.go中,在init func 内,创建一个 bool 类型的本地标志**Flags().BoolP**。其名称为float,简称f,默认值false和描述。默认值非常重要。意味着即使命令中没有调用标志,标志值也会是false。对于 bool 类型,如果调用一个标志,它将切换默认值。

// add.gofunc init() {rootCmd.AddCommand(addCmd)**addCmd.Flags().BoolP("float", "f", false, "Add Floating Numbers")**
}

add.go中创建新的addFloat功能

// add.gofunc addFloat(args []string) { var sum float64 for _, fval := range args {// convert string to float64 **ftemp, err := strconv.ParseFloat(fval, 64)** if err != nil {fmt.Println(err)}sum = sum + ftemp} fmt.Printf("Sum of floating numbers %s is %f", args, sum)
}

该功能与addInt相同,只是将**string** 转换为**float64**

addCmd RUN函数中,会根据标志调用addIntaddFloat。如果标志--float or -f通过,那么它将调用addFloat

// add.go 
// addCmdRun: func(cmd *cobra.Command, args []string) {**// get the flag value, its default value is false****fstatus, _ := cmd.Flags().GetBool("float")** if fstatus { // if status is true, call addFloat** addFloat(args)**} else {**addInt(args)**}
},

保存所有更改。使用go install my-calc重建二进制文件。

运行my-calc add 1.2 2.5 -fmy-calc add 1.2 2.5 --float

add float flag

你可以用旗子做很多事情。您甚至可以将值传递给标志,如一片 int、float、string 等。

操作实现的基本添加完成。

让我们通过向addCmd添加子命令来扩展它。

添加偶数

在项目目录中打开终端,创建一个新的**even**命令。

cobra add even

even命令作为even.go添加到cmd文件夹中。

在编辑器中打开even.go。将init中的**rootCmd**改为**addCmd**

// even.go
func init() {**addCmd.AddCommand(evenCmd)** ...
}

addCmd.AddCommand(evenCmd)将添加evenCmd作为addCmd的子命令或子命令。

更新evenCmd结构变量的RUN方法。

// even.go
Run: func(cmd *cobra.Command, args []string) { var evenSum intfor _, ival := range args {** itemp, _ := strconv.Atoi(ival)****if itemp%2 == 0 {**evenSum = evenSum + itemp}} fmt.Printf("The even addition of %s is %d", args, evenSum)
},

它将首先使用strconv包将string转换为int,然后只添加偶数。

保存所有更改。使用go install my-calc重建二进制文件。

运行**my-calc add even 1 2 3 4 5 6**

add even

my-calc是根命令,addrootCmd的命令,evenaddCmd的命令(子命令)。

添加奇数

这个和evenCmd一样。它不加偶数,反而会加奇数。

在项目目录中打开终端并创建一个新的 odd 命令。

cobra add odd

odd命令作为odd.go添加到cmd文件夹中。

在编辑器中打开odd.go。将init中的**rootCmd**改为**addCmd**

// odd.go
func init() {**addCmd.AddCommand(oddCmd)** ...
}

addCmd.AddCommand(oddCmd)将添加oddCmd作为addCmd的子命令或子命令。

更新oddCmd结构变量的RUN方法。

// odd.goRun: func(cmd *cobra.Command, args []string) {var oddSum intfor _, ival := range args {**itemp, _ := strconv.Atoi(ival)**** if itemp%2 != 0 {**oddSum = oddSum + itemp}} fmt.Printf("The odd addition of %s is %d", args, oddSum)
},

它将首先使用strconv包将string转换为int,然后只添加偶数。

保存所有更改。使用go install my-calc重建二进制文件。

运行**my-calc add odd 1 2 3 4 5 6**

my-calc是根命令,addrootCmd的命令,oddaddCmd的命令(子命令)。

恭喜🎉

恭喜你!您使用 cobra 在 golang 中创建了自己的 cli。

完整的代码保存在 Github 上。

cli 项目已经完成。本教程的主要目的是理解 cobra 库的基础知识。本教程涵盖了创建 cli 所需的大多数基本操作。如果需要,我会不断更新更多的基本操作。我希望我平滑了创建 cli 的学习曲线。感谢您花时间阅读教程。我希望你学到了一些东西,这是值得你花时间。

请对本教程提出宝贵的反馈意见。我会做出相应的改变。

如果你喜欢这个教程,你可以在我的博客上阅读我的最新教程。 📑

如何毫不费力地用 GitHub 页面免费创建一个网站(即使你不知道自己在做什么)

原文:https://towardsdatascience.com/how-to-create-a-free-github-pages-website-53743d7524e1?source=collection_archive---------0-----------------------

GitHub Pages 入门:创建和发布免费作品集、博客或网站的快速简便指南

GitHub Pages 必须是人们不知道他们已经拥有的最酷的工具。几乎 GitHub 上的任何存储库都可以通过点击两个按钮变成一个网站。

你需要一个你的工作的在线作品集,让潜在的雇主检查,但你不知道如何制作一个网站?你想创建一个博客或商业网站,但你不知道从哪里开始?有没有可能你只是不想处理(或支付)网站托管,域名,以及其他一切?

这是给你的!

Photo by Leonard Alcira on Unsplash

我为什么要有网站?

很难想象谁不会从拥有一个网站中受益!你可能需要向潜在客户或雇主展示你的投资组合。您可能需要以一种可以共享的方式来组织项目。你可能想创建一个关于你正在做的事情或你去过的地方的博客。你可能需要宣传你自己或你的企业或销售产品。不管你的理由是什么,很有可能你不想花太多时间就想把一些东西放在一起。更有可能的是,你不想花很多钱。

Photo by imarksm via Pixabay

网站是与世界联系的一种方式,也是一种强大的交流工具。这是分享你的工作、兴趣和激情的一种方式。这是你如何创造,建立和控制你的在线形象。另外,你越早建立你的网站,你就有越多的时间来建立你的网上形象,接触你想接触的人。它可以帮助你在众多竞争者中脱颖而出。

如果你不知道自己在做什么,这也不是一件容易的事情。

初学者有几种方法可以创建一个简单且完全免费的网站。主要的有 GitHub 和 Wordpress。

Wordpress 对于需要所有帮助的初学者来说非常棒。我爱 Wordpress!这就是我如何开始我的第一个博客!关于一个免费的 Wordpress 网站,很明显它是一个 Wordpress 网站。你有一个以 wordpress.com 结尾的地址,并且在每一页的底部有一个 Wordpress 标志。

如果你刚进入科技领域,你会发现如果你知道如何使用 GitHub,你会看起来更有吸引力。如果你现在已经在技术世界呆了一段时间,现在你很有可能已经在 GitHub 上有了一百万到一百万个仓库。

为什么不在 GitHub 上建立你的网站,并直接从你的库托管它呢?

GIF via GIPHY

现在在技术世界中,很多重要的事情都是为开源做贡献。在社区中公开分享你的作品是一件大事。GitHub 正是为此而设计的。把你的作品放在 GitHub 上,说明你参与了,也意识到了。(如果你想看的话,我把我的作品集放在 GitHub 的一个库中。它已经相当过时了,但它是一个用 Bootstrap 构建的、由 GitHub repo 托管的个人资料网站的例子。)

当你在 GitHub 上分享你的项目时,人们可以看到你的代码,你在做什么,以及你是如何做的。GitHub 就是关于思想的交流。

现在几乎所有的技术人员都在以某种方式使用 Git 和/或 GitHub。将你的个人资料放在 GitHub 上是举起你的手并参与进来的好方法。另外,您将在您的个人资料页面上获得一个存储库和一些提交!

如果你对 Git 一无所知,你可能想看看“Git 和 GitHub 入门:完全初学者指南”那篇文章将带您了解什么是 Git 和 GitHub 的基础知识,如“”等概念。我假设你已经知道了基本知识。如果你不知道,花几分钟去熟悉他们是值得的。

让我们开始派对吧!

有两种方法可以开始你的网站。你可能会完全从零开始!另一方面,你可能已经有了一个网站,但是你不知道如何使用 GitHub 把它变成一个免费的网站。

我从选项 2 开始。

GIF via GIPHY

我有文件,但我不知道该怎么处理它们!

这再简单不过了。说真的!GitHub 会为您完成剩下的工作。我假设你已经有一个 GitHub 帐户,并且你知道什么是资源库,但是如果你不知道,请查看Git 和 GitHub 入门文章。

简而言之,一个存储库就是你的项目将要存在的地方。这是您组织项目的地方。您将在存储库中保存文件夹、文件、图像、视频、电子表格、Jupyter 笔记本、数据集以及项目需要的任何其他东西。

如果您还没有,那么继续使用存储库初始化您的项目,或者创建一个新的存储库并上传您的文件。如果你有一个名为“index.html”的文件,GitHub 会知道你想做什么。

现在你将利用 GitHub 页面。进入你的 GitHub 库,点击设置

向下滚动到 GitHub 页面你会看到这个:

现在将“ Source ”下拉菜单拖放到“ master branch ”或“ master branch/docs 文件夹”事情是这样的:如果你想从你的“docs”文件夹发布,你真的需要在你的主分支中有一个“docs”文件夹,你想从那里运行你的网站!

如果你是一个初学者,你可能会选择“master branch”,这意味着你想按原样发布你的库。(有几次,我需要调整一两个文件路径,这取决于我如何组织我的文件夹。)

您将看到一个通知,告知您的站点可以发布了。

请耐心等待一两分钟,然后刷新页面或尝试链接。一旦您的站点发布,您将看到以下内容:

试着点击那个链接。

噗!你有一个免费网站!

恭喜你!!!

现在是另一个选择:

我都不知道怎么开始!

我将在另一个时间处理像引导和基本网站设计这样的事情,并在这里关注绝对的基础。不过,我确实想让你知道,这个世界是你的!唯一限制你选择的是你实现它的动力。(嗯,可能是开车,也可能是你有多少时间……)因为这个选项是针对完全初学者的,所以我将向你展示如何在 GitHub 网站上做好每一件事。

我们将首先创建一个新的存储库。

填写您的存储库名称和简短描述,选中“使用自述文件初始化此存储库”框,然后单击“创建存储库

现在转到屏幕右上方附近的“设置,然后向下滚动到“ GitHub 页面”部分。下拉显示“”的下拉菜单至“总分行

首先,你会看到这个:

等一两分钟,然后你会看到这个:

现在点击链接!

你有网站了!恭喜你!

这看起来没什么

好吧,这看起来确实很无聊,但是你可以看到这里显示的是你的自述文件。

如果您想做一些快速更改,您可以继续编辑您的自述文件,以显示您希望人们看到的内容。要做到这一点,请回到您的存储库中,单击您的自述文件上的小铅笔图标,并使它变得更好!

Edit your README file

Editing the file (you’re working with a Markdown file)

How the file looks with a few edits!

你正在使用 markdown,你可以用 Markdown 文件做很多事情。这包括添加文本、图像、链接、颜色和一些基本的格式。这是一个非常简单的开始方式!这里是基本语法的降价指南,适合以前没有用过的人。

(请记住,如果您在自述文件中添加任何图像,您需要确保将它们上传到您的资源库,否则 GitHub 不会知道您想要什么!)

现在回到你的网站,看看你有什么!

请注意,这些更改有时需要几分钟才能完成。如果您没有立即看到您的更改,请等待几分钟,然后重试。我还遇到了一个问题,即使我做了更改,我的笔记本电脑还是想回到我网站的旧版本。删除我过去 24 小时的浏览器历史记录解决了这个问题。在你被复杂的事情吓到之前,尝试简单的解决方法!

GIF via GIPHY

这是一个进步,但它可能会更有趣

如果你是一个完全的初学者,你对 CSS 一无所知,但是你想要更多的视觉吸引力,试试 Jekyll 主题!它们是预先构建的主题,你可以用它们来让你的网站看起来更好,而你自己基本上不需要做任何努力。Jekyll 和 GitHub 将为您完成这项工作!你的工作就是按一两个按钮。

回到“设置”中的“ GitHub 页面”部分,点击“选择一个主题

让我们看看,如果我们选择第一个出现的主题,我们的网站会是什么样子。你所要做的就是按下绿色的"选择主题"按钮,等待几分钟,然后再次尝试你的网站!

经过几分钟的努力,我们已经有所进展了!

就是这样!只需几分钟,您就可以为自己的企业、博客或作品集创建一个免费网站,通过 GitHub 存储库托管它,而且它已经开始运行了。你已经准备好与世界分享了!

好样的。!!

只有几个提示:

*如果你决定你根本不想使用一个主题,没有按钮可以回到原来的版本。不过,去掉你的主题其实是完全容易的!如果你回到你的存储库,你会发现你现在有一个名为“ _config.yml ”的文件,它包含了你的主题信息。如果你删除了那个文件,你就删除了主题!

*如果您想尝试您的主题和主题选项,您会发现" _config.yml "文件是您的第一站。现在你知道了,看看你拥有的无数其他 Jekyll 选项吧!如果你想要一个简单的已经设置好的博客,你甚至可以从 Jekyll Now 主题开始。你的选择是无限的!

我等不及要看你创造的东西了!一如既往,如果你用这些信息做出了什么惊人的事情,请在下面的评论中让每个人都知道。

如果你想接触或者找到更多很酷的文章,请到内容简约来和我一起吧!

你可能也想看看我在 Medium 上为初学者写的其他教程!

[## 如何撰写和发表引人注目的文章

创建内容的简单技巧,易于查找,阅读起来令人兴奋

medium.com](https://medium.com/swlh/how-to-write-and-publish-articles-that-get-noticed-60e9701daed4) [## Git 和 GitHub 入门:完全初学者指南

Git 和 GitHub 基础知识,供好奇和完全困惑的人使用(加上最简单的方法来为您的第一次公开…

towardsdatascience.com](/getting-started-with-git-and-github-6fcd0f2d4ac6) [## Google Colab 入门

沮丧和困惑的基本教程

towardsdatascience.com](/getting-started-with-google-colab-f2fff97f594c)

感谢阅读!

不写代码怎么创建热图?

原文:https://towardsdatascience.com/how-to-create-a-heat-map-without-writing-code-e1d7b10cf33f?source=collection_archive---------15-----------------------

我们如何在不编写一行代码的情况下创建热图?这听起来不可能,但实际上非常容易实现。有时候,我们需要善于利用工具和学习技巧来帮助我们节省时间,提高工作效率。今天我将向你展示如何不用写代码就能制作地震热图。而我用的工具是一个数据可视化软件,FineReport。

个人版 FineReport 完全免费。想学做热图可以下载,跟着我的教程练习。

首先给大家展示一下地震图的最终效果。图为 1999 年至 2019 年地震的分布和震级。

上面的截图只显示了东南亚的地震。我还做了一个 3D 动态热图,显示地震的全球分布。而且我在制作过程中没有使用任何代码。

现在,让我们开始学习如何可视化数据。

1。找到数据源

数据可视化的第一步是找到数据的来源。我们可以从 美国地质调查局 获得各个地区的地震热图数据。在这篇文章中,我们将 1999 年至 2019 年的世界地震数据导入 Excel,然后编辑成如下图所示的统一格式。

2.连接数据集

接下来,我们将数据导入 FineReport 设计器。 FineReport 可以连接各种数据库。

但是如果数据来自 Excel,我们需要把 Excel 文件放在安装 FineReport 的同一个
路径下。比如在我的电脑里,我把上面创建的 Excel 文件放入C:\ fine report _ 10.0 \ WEB apps \ webroot \ we b-INF \ reportlets,作为内置模板。

然后打开 FineReport 设计器,你会找到你的 Excel 文件。选择文件,设置文件类型Excel ,选择本地文件,选择刚导入的 Excel 文件,在右侧选择“首行包含列标题”,数据导入完成。

3.选择图表类型

我们创建一个新表单来设计仪表板,并在图表中选择热图,如下所示。

单击地图进行编辑。选择地图点,这里我选择模板参数,然后选择 GIS 图层选择卫星。您可以设置地图显示的中心点。这里我选择(101,0)来显示,以东南亚为中心。

然后将数据导入地图。设置如下。

4.设计热图的样式

最后,我们调整了热图的样式。

默认情况下,图例设置为渐变颜色。您可以根据需要定义最大值和最小值。选择图表属性表- >样式- >系列,可以看到系列属性分为两种设置:热点BG 区域。如果用户选择的边界/点不包含边界信息,则设置无效。热点的串联界面如下:渲染半径越大,热区显示范围越大;模糊越大,热边界的模糊程度越高。不透明度最小值和最大值,对应于图形中最小和最大值的不透明度,在此设置如下。

5.效果显示

点击预览,一个没有编码的热图就完成了。

看到这里你可能会问文章开头的 3D 动态热图是怎么做出来的?这很简单。插入图表时,只需选择结构(新)。而且我觉得后续的设置你可以自己摸索,和上面的步骤差不多。

最后

除了热图,如果想了解地图可视化,可以看看这篇文章 数据可视化中的 10 大地图类型

您可能也会对…感兴趣

2019 年你不能错过的 9 个数据可视化工具

2019 年 6 大数据分析工具

什么是大屏幕的数据可视化,如何实现?

数据分析师需要掌握的 6 项关键技能

业务仪表盘初学者指南

数据可视化中排名前 16 的图表类型

如何从零开始创建机器学习数据集?

原文:https://towardsdatascience.com/how-to-create-a-machine-learning-dataset-from-scratch-6a24a9fd1673?source=collection_archive---------19-----------------------

我祖母的烹饪书遇见机器学习第一部分

Figure 1: My grandmothers old, German cookbook: “Praktisches Kochbuch” by Henriette Davidis

我的祖母是一位杰出的厨师。因此,当我最近偶然发现她的旧烹饪书时,我试着通读了一些食谱,希望我能重现一些我小时候喜欢的菜肴。然而,这比预期的要难,因为这本书是在 1911 年左右以一种叫做frak tur的字体印刷的。不幸的是,fraktur 字体偏离现代字体在几个例子。例如,字母“A”看起来像 fraktur 中的“U”,每当我看到 fraktur 中的“Z”时,我就会读出一个“3”(见图 2)。

Figure 2: Examples of letters in fraktur and in a modern typeface (Calibri)

因此,这个想法出现了,以开发一个管道,将创建一个现代字体的 fraktur 字母的现场翻译。有了这样的工具在手,我们可以很容易地通读食谱,并专注于烹饪部分,而不是破译这本书。幸运的是,有许多优秀的开源工具可以帮助我们开发这样的管道。然而,这个项目的一些方面必须从头开始建设。主要是我们需要一个数据集来训练我们的机器学习算法。这就是我们将在本文中重点讨论的内容。但在我们开始使用数据集之前,让我们快速浏览一下摆在我们面前的所有任务:

  1. 检测图像中的单个字母
  2. 从这些字母创建一个训练数据集
  3. 训练一个算法来分类字母
  4. 使用经过训练的算法对单个字母进行分类(在线)

我们将在本文中讨论前两个主题,并在第二和第三篇文章中继续讨论主题 3 和 4。这应该给我们足够的空间来详细研究每个任务。

同样作为一个一般备注:在这些文章中,我们不会关注如何从头开始实现每个算法。相反,我们将看到如何连接不同的工具,将烹饪书翻译成现代字体。如果你对代码比对解释更感兴趣,你也可以直接去 Github 上的 Jupyter 笔记本。

检测图像中的字母

所以第一个任务是找到一种方法从烹饪书的书页中提取单个字母。这是后面一切的基础。在下一步中,我们可以从提取的字母中创建一个数据集,并最终在其上训练一个分类器。

Figure 3: Picture of one paragraph of the cook book

我们管道的输入将总是来自烹饪书的页面图片,类似于上面图 3 所示。这些输入可以是来自智能手机摄像头的单个高分辨率图像,也可以是来自网络摄像头的图像流。我们必须确保的是,每一张独立于其来源的图像,都以一种检测算法可以找到所有单个字母的方式进行处理。这里首先要记住的是,数码相机是以三个独立的通道存储图像的: R ed、 G reen 和 B lue ( RGB )。但是在我们的例子中,这三个通道包含冗余信息,因为字母可以在这三个通道的每一个中分别被识别。因此,我们将首先把所有图像转换成灰度。结果,我们只需要处理一个通道,而不是三个通道。此外,我们还将数据量减少到 1/3,这将提高性能。但我们的检测算法将面临另一个问题:不断变化的闪电条件。这使得从背景中分离字母变得复杂,因为整个图像的对比度发生了变化。为了解决这个问题,我们将使用一种称为自适应阈值的技术,该技术使用附近的像素来创建局部阈值,然后用于二值化图像。结果,处理后的图像将仅由黑白像素组成;不再是灰色了。然后,我们可以通过使用中值模糊滤波器对图像进行去噪来进一步优化字母检测。下面的代码概述了一个 Python 函数,它在 openCV 库的帮助下将图像从 RGB 转换为黑白。该处理步骤的结果在图 4 中进一步举例说明。

# Define a function that converts an image to thresholded image
def convert_image(img, blur=3):# Convert to grayscaleconv_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # Adaptive thresholding to binarize the imageconv_img = cv2.adaptiveThreshold(conv_img, 255,   cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 4) # Blur the image to reduce noiseconv_img = cv2.medianBlur(conv_img, blur) return conv_img

Figure 4: The left image shows the original picture, middle image shows the gray scaled version and the right image shows the thresholded and blurred result.

好了,现在我们处理了图像,是时候检测字母了。为此,我们可以使用 openCV 库的 findContours 方法。代码归结为一行,由下面的函数调用。然后,我们可以将该函数找到的轮廓的边界框映射回原始 RGB 图像,以查看实际检测到了什么(图 5)。

# Define a function that detects contours in the converted image
def extract_char(conv_img):# Find contours_, ctrs, _ = cv2.findContours(conv_img, cv2.RETR_TREE,  cv2.CHAIN_APPROX_SIMPLE) return ctrs

Figure 5: Result of detected contours mapped back onto the original image.

从图 5 中我们可以看到检测工作得相当好。但是,在某些情况下,没有检测到字母,例如,第 1 行末尾的一些“I”。而在另外一些情况下,一个字母被拆分成两个字母,例如【b】在最后一行的末尾。另一件要注意的事情是,一些字母组合实质上变成了单个字母,并被算法相应地检测到,图 5 中的两个例子是“ch”“CK”。我们将在后面看到如何处理这些问题。但是现在我们可以继续目前的结果。因此,由于我们有了每个字母的边框,我们可以将它们剪切下来,保存为单独的图像。png)放在我们硬盘上的一个文件夹里。如果你对如何做到这一点感兴趣,可以看看 Jupyter 的笔记本。

创建数据集

拥有一组提取的字母是好的,但是我们需要以一种数据集对我们有用的方式来组织它们。为此,我们必须做两件事:

  1. 删除不包含字母的图像。这可能是各种各样的伪像,例如,我们在图 5 中看到的一页上的污点或一封信的一部分。
  2. 将所有剩余图像分组。这意味着所有字母“A”进入一个文件夹,所有字母“B”进入另一个文件夹,依此类推。

原则上,以上两点都很容易解决。然而,由于我们从这本书的许多页中提取了几千封潜在的信件,它们构成了一个漫长而乏味的任务。从好的方面来看,我们可以自动化第一轮分组,这样我们以后“只”需要纠正这个预分组步骤的结果。但是在我们开始这个聚类步骤之前,还有一件事要做:我们必须使提取的字母的所有图像具有相同的大小。

Figure 6: Scatter plot of the first 3 PCA scores. Color represents the cluster.

其原因是,我们将用于聚类和分类的算法预期输入图像的大小是固定的。但是正如我们从图 5 的边界框中看到的,每个图像目前都有不同的形状。为了克服图像尺寸的多样性,我们将使用 openCV 库的 resize 方法,并将所有图像调整到相同的尺寸。然后,我们将图像存储在一个 Numpy 数组中,并通过计算它们的 z 值来归一化它们。归一化对于下一步很重要,下一步是用主成分分析(PCA)降低每幅图像的维数。然后,第一主成分的分数将作为 K-Means 聚类算法的输入,该算法将为我们进行字母的预聚类。如果你对这个过程和 K-Means 算法的细节感兴趣,你可以查看这篇文章的 Jupyter 笔记本,或者在这里了解一个不同的用例。K-Means 聚类的结果如图 6 所示,其中每个点的颜色表示它所属的聚类。查看图 6 看起来一些数据点形成的组也通过 K-Means 算法被分配到同一个聚类。然而,仅仅从图 6 中很难判断集群工作得有多好。评估结果的一个更好的方法是将一个簇中的所有图像移动到一个单独的文件夹中,然后查看每个簇的内容。图 7 显示了一个示例文件夹中的图像,在该文件夹中,集群工作得非常好。下一步是将该文件夹重命名为“a”。

在其他情况下,聚类效果并不好。图 8 显示了一个包含不同类型字母的集群示例。虽然大多数字母是“n ”,但在字母串中也有一些“K”和“u”。然而,我们可以通过搜索“K”和“u”集群并将图像移动到那里来轻松解决这个问题。之后,该文件夹可以重命名为“n”。

Figure 8: Example folder with clustered data that contains different letters

我们将继续这样做,直到所有的集群都被清理和重命名,如上所述。结果应该类似于图 9,其中大写字母用“_”标记。

Figure 9: Example of how the data should be organized after clustering and manual adjustments.

因此,显然需要一些手工工作来整理数据。然而,我们能够通过使用 PCA 和 K-Means 对数据进行预聚类来自动化大部分工作。数据集现在已经清理和组织好了,但是为了让我们更有效地工作,我们需要以一种比硬盘上的文件夹更方便的方式保存它。

将数据集转换为 IDX 格式

因此,最后一步是将数据集转换为 IDX 数据格式。你可能已经熟悉了这种格式,因为著名的 MNIST 数据集也是以同样的方式保存的。只是在这里,我们必须写数据,而不是从 IDX 文件中读取数据。
我们将通过使用一个 idx_converter 来实现,它采用我们上面设置的文件结构,并直接以 idx 格式保存。输出将是两个文件:一个文件包含图像,另一个文件包含标签。
由于我们希望稍后在数据上训练一个分类器,我们应该已经将图像分成训练和测试数据集。为此,我们将 30%的字母移动到测试文件夹,而剩余的字母留在培训文件夹中。您可以查看 Jupyter 笔记本中的代码,了解有关该程序实现的详细信息。

既然我们已经从头开始创建了 fraktur 数据集,我们可以继续下一篇文章,在这篇文章中,我们将比较几个分类器算法的性能,以便选择一个用于烹饪书的实时翻译。

同时,你可以在这里查看这篇文章的完整代码,在 Twitter 上关注我或者通过 LinkedIn 联系我。

如何创建一个 Plotly 可视化,并将其嵌入网站

原文:https://towardsdatascience.com/how-to-create-a-plotly-visualization-and-embed-it-on-websites-517c1a78568b?source=collection_archive---------3-----------------------

Examples from Plot.ly

Plotly 是一个开源的、易于使用的 python 图表库。Plotly.express 是作为 Plotly.py 的包装器构建的,使创建交互式可视化像编写一行 python ✨一样简单

plotly.express之于plotly就像seaborn之于matplotlib

有很多很酷的交互式可视化可以用 Plotly Express 创建——就像这个使用 Airbnb 数据集的可视化:

使用 Plotly express 创建的交互式可视化可以在大多数笔记本和 IDE 上渲染和显示。将它们嵌入其他地方则是另一回事。如果你在嵌入你的交互式可视化图形时遇到了麻烦,那你就来对地方了!

在本文中,我将介绍如何使用 plotly express 创建一个基本的交互式可视化,并生成 iframe 嵌入代码以在任何网站上显示它。

步骤如下:

  • 创建情节可视化
  • 主机可视化(在 plotly 或 github 页面上)
  • 获取 iframe 嵌入代码

创建一个情节可视化

如果您还没有,使用!pip install plotly将 plotly 安装到您的环境中,并使用import plotly.express as px导入 plotly。

运行以下代码创建一个基本的可视化:

gapminder = px.data.gapminder()
fig = px.scatter(gapminder.query("year==2007"), x="gdpPercap", y="lifeExp", size="pop", color="continent",hover_name="country", log_x=True, size_max=60)fig.show()

下图应该会出现在您的笔记本中:

现在你有了一个交互式可视化工具…让我们把它放在某个地方吧!

上传可视化到 Plotly

如果你的数据集足够小,你就可以免费将你的可视化上传到 plotly,如果不够小,当你尝试下面的部分时,它会给你一个错误。我将在下一节解释如果遇到错误如何解决。

要将可视化上传到您的 plotly 帐户,请使用!pip install chart_studio安装 chart studio,然后使用import chart_studio将其导入。

您将需要您的用户名和 api 密钥从您的 plotly 帐户连接到它从您的笔记本电脑。要获取您的 api 密钥,只需点击您的个人资料右上角的用户名,然后点击设置,然后重新生成一个新的 api 密钥。现在,您可以设置您的凭据:

username = '' # your username
api_key = '' # your api key - go to profile > settings > regenerate keychart_studio.tools.set_credentials_file(username=username, api_key=api_key)

使用以下代码行将您的可视化应用到您的帐户中:

import chart_studio.plotly as py
py.plot(fig, filename = 'gdp_per_cap', auto_open=True)

如果操作正确,这段代码应该会在你的帐户上打开一个新的可视化窗口,并返回你的笔记本中的链接。您可以使用相同的链接,然后在支持 embed.ly 嵌入的网站上嵌入,如 Medium。注意:当你在 Medium 上写文章的时候,你的可视化效果不会是交互式的,但是一旦你发布了它,它就会起作用。

这是我们创建的交互式可视化,我只需粘贴链接就可以嵌入到 Medium 中…很简单。

如果把你的可视化上传到 plotly 对你有用,那太好了。您可以跳到下一节,我将向您展示如何生成 iframe 嵌入代码。

为绘图可视化生成 HTML

当您正在处理的数据集太大时,您将从 plotly 获得一个错误,即您无法上传可视化,除非您升级您的帐户。因此,为了解决这个问题,我们将把我们的可视化图形写成 HTML。

首先,让我们创建一个大型数据集的可视化。我将使用 Airbnb 的数据,这些数据可以在这个 github repo 中找到。如果您想继续学习,可以下载 csv。

下面是创建我将使用的数据帧的代码:

下面是创建可视化的代码:

fig = px.scatter(df, x='Neighborhood', y='Price (US Dollars)',size='Accommodates', hover_data=['Bedrooms', 'Wifi', 'Cable TV', 'Kitchen', 'Washer', 'Number of Reviews'],color= 'Room Type')fig.update_layout(template='plotly_white')
fig.update_layout(title='How much should you charge in a Berlin neighborhood?')fig.show()

输出将如下所示:

现在,如果您尝试使用py.plot(fig, filename='airbnb', auto_open=True)将它上传到您的 plotly 帐户,您将会看到以下错误:

PlotlyRequestError: This file is too big! Your current subscription is limited to 524.288 KB uploads. For more information, please visit: [https://go.plot.ly/get-pricing.](https://go.plot.ly/get-pricing.)

因此,我们将把我们的可视化结果写成 HTML,并放在 github 页面上。

创建 HTML

要为 plotly 可视化生成 HTML 文件,请使用:

import plotly.io as pio
pio.write_html(fig, file=’index.html’, auto_open=True)

如果操作正确,这段代码将在您的浏览器中打开本地 HTML 文件,您应该会看到可视化效果。

GitHub 页面的宿主

发布到 github 页面非常简单。你可以按照 github 这里的说明或者按照我的简要概述来做。

创建一个新的 github repo 并用 README.md 初始化。上传我们刚刚创建的 index.html 文件,并将其提交到主分支。现在,点击设置,向下滚动到 github 页面部分,在“源”下选择“主分支”。

现在你应该可以使用这个链接结构来查看你的可视化效果了

我刚刚做的那个可以在这里找到https://elizabethts.github.io/publish-plotly-website/。

用 iframe 嵌入 Plotly 可视化

现在我们有了到我们的 plotly 可视化的链接(托管在 plotly 或 github 页面上),我们可以为可视化生成 iframe 代码。如果您能够将可视化上传到 plotly,则可以使用以下代码行生成 iframe 嵌入代码:

*import chart_studio.tools as tls
tls.get_embed('[https://plot.ly/~elizabethts/9/'](https://plot.ly/~elizabethts/9/')) #change to your url*

这将为您提供输出:

*<iframe id="igraph" scrolling="no" style="border:none;" seamless="seamless" src="https://plot.ly/~elizabethts/9.embed" height="525" width="100%"></iframe>*

如果您走的是 github pages 路线,您需要自己修改上面的 iframe 代码。把 plotly 网址换成 github 网址就行了!

最后,您可以将这个 iframe 嵌入代码放到您的站点中,您的可视化效果将会出现!注意:如果使用 github 链接,可能需要修改高度和宽度。

讽刺的是,据我所知,如果你的数据集太大,你不能在媒体上嵌入你的交互式可视化,你必须把它放在 github 上。为了解决这个问题,我强烈推荐使用 CloudApp 来筛选记录 gif,你可以轻松地将其拖放到你的中型文章中,这就是我在这篇文章中所做的。

现在,您可以创建一个交互式的 plotly 可视化,并生成 iframe 嵌入代码以在任何网站上显示它!

在推特上找到我@伊丽莎白!

来源:

* [## plotly

Plotly 的 Python 图形库制作出交互式的、出版物质量的图形。如何制作线图的示例…

plot.ly](https://plot.ly/python/) [## Python 的 Plotly 入门

情节可以设置为三种不同类型隐私:公开、私人或秘密。公共:任何人都可以查看此图表。它…

plot.ly](https://plot.ly/python/getting-started-with-chart-studio/) [## ✨推出 Plotly 快递✨

Plotly Express 是一个新的高级 Python 可视化库:它是 Plotly.py 的包装器,公开了一个简单的…

medium.com](https://medium.com/plotly/introducing-plotly-express-808df010143d) [## 在 HTML 中嵌入图形

Plotly 图形可以嵌入任何 HTML 页面。这包括 IPython 笔记本、Wordpress 网站、仪表盘、博客…

plot.ly](https://plot.ly/python/embedding-plotly-graphs-in-HTML/) [## GitHub 页面

使用你最喜欢的文本编辑器,在你的项目中添加一个 index.html 文件:Hello World I hosted with GitHub Pages…

pages.github.com](https://pages.github.com)*

如何创建一个生产就绪的推荐系统

原文:https://towardsdatascience.com/how-to-create-a-production-ready-recommender-system-3c932752f8ea?source=collection_archive---------2-----------------------

我们每天在网上看到很多东西。但是你知道有多少其他的东西我们还没有看到吗?

Photo by Susan Yin on Unsplash

你可能每天都会看到电子商务网站。或者阅读大量博客、新闻和媒体出版物上的文章。

从你作为用户或读者的角度来看,看所有这些东西时,常见的痛点是什么?

一个简单的答案:

有很多东西可以看,当你试图发现一些东西的时候,你经常会迷失方向。

是的,这些网站上有大量的东西或文章,用户需要一个解决方案来简化他们的发现之旅。

如果你是运营电商网站或者博客的,也许你想问。何必呢?

嗯,你听说过漏斗吗?

用户在尝试做某件事的时候漏斗越少,转化就越大。这是用户体验的基本规则。那么,如果减少步骤数量可以增加你的网站页面浏览量甚至收入,为什么不呢?

如果你想阅读更多关于推荐系统或深度学习的一般内容,可以在这里 下载免费书籍

推荐系统能有什么帮助?

简单来说,推荐系统就是一个发现系统。系统从数据中学习并向用户提供建议。无需用户专门搜索该项目,该项目由系统自动带来。

听起来很神奇。

亚马逊和网飞从几十年前就开始使用这种魔法。

当你打开 Spotify 时,它已经给了你一个听歌曲的列表(发现周刊,我惊讶于它如何能挑选我从未听过的歌曲,我喜欢它)。

Photo by Samuel Zeller on Unsplash

关于推荐系统的深入探讨

一般来说,有两种推荐系统被我们人类所知。嗯,不全是人类。

1.基于内容的过滤

这种推荐系统很容易被我们的大脑所消化。没有短路或爆炸的迹象。

例如,你是一个狂热的小说读者。你喜欢阿加莎·克里斯蒂的《然后就没有了》。你从网上书店买的。

如果下次你打开网站,书店会给你看“美国广播公司谋杀案”,这是有道理的。

为什么?

因为它们都是阿加莎·克里斯蒂写的。

因此,基于内容的过滤模型会向您推荐该标题。

哇,这么容易!让我们利用这一点!

等等…

虽然基于内容的过滤很容易被我们的大脑消化,而且看起来很简单,但它无法猜测用户的真实行为。

例如,我不喜欢赫丘里·波罗,但我喜欢她小说中的其他侦探。在这种情况下,“ABC 谋杀案”不应该推荐给我。

2.协同过滤

这种类型将克服前面的问题。本质上,该系统记录了用户在网站上的所有先前的交互。并在此基础上提供建议。

它是如何工作的?

看一下这个场景。

有两个用户 A 和 b。

购买的项目 1

购买的项目 2

购买的项目 3

b 购买的项目 1

b 购买的项目 3

协同过滤将推荐 B 项目 2 ,因为有另一个购买了项目 1 和 3 的用户也购买了项目 2。

你可能会说,哇,它们可能是偶然凑巧一起买的。

但是,如果,有 100 个用户和用户 A 有同样的行为呢?

这就是所谓的,群体的力量

那么,为什么要等呢?让我们开始在您的生产环境中创建协作过滤系统吧!

别冲动,伙计!

虽然它的性能非常好。它有几个严重的问题。更重要的是,当您试图创建一个生产就绪的系统时。

协同过滤的缺点

  1. 它不知道上下文。与推荐相似项目的基于内容的过滤相比,协同过滤不会基于相似性进行推荐。如果这是您关心的问题,那么解决方案就是混合动力。结合两种方法。
  2. 它需要大量的硬件资源,因为你需要存储一个用户条目矩阵。想象一下,如果你打开你的电子商务网站,它有 10 万用户。同时,你提供 10K 产品。在这种情况下,您将需要 10K x 100K 矩阵,其中每个元素包含 4 个字节的整数。是的,你需要 4GB 的内存来存储矩阵。甚至不做其他事情。
  3. 冷启动。一个新用户不会从系统中得到任何好处,因为你不了解他。
  4. 不可改变的。如果你没有在网站上做任何事情,推荐系统的结果将保持不变。用户会认为网站上没有什么新东西。他们会离开。

虽然第一个问题很容易通过混合动力解决,但其他问题仍然令人头疼。

嗯,解决数字 2,3,4 是这篇文章的原因。

我们开始吧。

让您的推荐系统投入生产的明确指南

我可能和你在同一个地方。我真的不知道如何让这件事成为可能。由于机器的限制,当然还有常识,我不能仅仅为了这个微小的需求就部署一个庞大的服务。

幸运的是,我偶然发现了这本书

Practical Machine Learning by Ted Dunning & Ellen Friedman

他们告诉我,对于一个生产就绪的系统,您可能不希望它的性能达到最佳精度。

一个有些不准确但可接受的在现实世界中最常见的用例。

关于如何做到这一点,最有趣的部分是,

  1. 一般推荐指标的批量计算。
  2. 实时查询,不使用用户-项目矩阵,而是取用户最近的几次交互,查询到系统。

当我们建立系统的时候让我解释。

基于 Python 的推荐系统

为什么是 python?嗯,python 是最容易学的语言之一。你只需要花几个小时就能理解语法。

for item in the_bag:print(item)

你可以打印包里的所有东西。

这么简单。

去 Python 网站根据你的操作系统下载安装。

对于本教程,您需要几个包

pip install numpy
pip install scipy
pip install pandas
pip install jupyter
pip install requests

Numpy 和 Scipy 是处理数学计算的 python 包,你将需要它们用于矩阵。熊猫是用于你的数据。请求用于 http 调用。Jupyter 是一个交互式运行 python 代码的 web 应用程序。

键入 jupyter 笔记本,你会看到这样的内容

Jupyter Notebook

在提供的单元格上编写代码,代码将交互式运行。

在我们开始之前,你需要几个工具。

  1. 弹性搜索。这是一个开源搜索引擎,可以让你快速搜索你的文档。您将需要这个工具来保存您计算的指标,以便您可以实时查询。
  2. 邮递员。一个 API 开发工具。您将需要它来模拟对 elasticsearch 的查询。因为 elasticsearch 可以通过 http 访问。

下载并安装这两个软件,你就可以开始了。

数据

对于本教程,我们来看看 Kaggle 中的一个数据集。 Retailrocket 推荐系统数据集。下载并提取 Jupyter 笔记本目录中的数据。

应该是那样的。

在这些文件中,对于本教程,您只需要 events.csv。

该文件由用户对电子商务网站上的商品的数百万次操作组成。

让我们来探索数据!

import pandas as pd
import numpy as np

在 Jupyter 笔记本上写下那些进口货。你已经准备好了。

df = pd.read_csv('events.csv')
df.shape

它会打印你(2756101,5)。这意味着你有 270 万行 5 列。

我们去看看。

df.head()

它有五列。

  1. 时间戳,事件的时间戳。
  2. Visitorid,用户的 id
  3. Itemid,项目的 id
  4. 事件,事件
  5. Transactionid,如果事件是事务,则为事务的 id

让我们查一下,有什么样的活动

df.event.unique()

您将得到三个事件,视图添加到图表事务

为了简单起见,您可能不想玩所有的事件。对于本教程,您将只玩事务。

因此,让我们只过滤事务。

trans = df[df['event'] == 'transaction']
trans.shape

它将返回(22457,5)

你将有 22K 的交易可以玩。我认为对于我们这样的新手来说已经足够好了。

让我们进一步看看这些数据

visitors = trans['visitorid'].unique()
items = trans['itemid'].unique()print(visitors.shape)
print(items.shape)

您将获得 11,719 个独特的访问者和 12,025 个独特的项目。

创建简单而有效的推荐系统的经验法则是在不损失质量的情况下对数据进行下采样。这意味着,你可以为每个用户只取 50 个最新的交易,你仍然可以得到你想要的质量,因为行为会随着时间的推移而改变。

trans2 = trans.groupby(['visitorid']).head(50)
trans2.shape

现在你只有 19939 笔交易。意味着大约有 2K 个事务被废弃。

因为访问者 id 和项目 id 是巨大的数字,你将很难记住每一个 id。

trans2['visitors'] = trans2['visitorid'].apply(lambda x : np.argwhere(visitors == x)[0][0])
trans2['items'] = trans2['itemid'].apply(lambda x : np.argwhere(items == x)[0][0])trans2

您需要其他基于 0 的索引列。你会看到这样的东西。

更干净。现在,在接下来的所有步骤中,您可以只使用访问者和项目列。

Photo by Andrei Lazarev on Unsplash

下一步:创建用户-项目矩阵

噩梦来了…

你有 11,719 个独立访问者和 12,025 个条目,所以你需要大约 500MB 的内存来存储这个矩阵。

稀疏矩阵来拯救。

稀疏矩阵是大部分元素为零的矩阵。这是有意义的,因为不是所有的用户都购买所有的商品。连接的批次将为零。

from scipy.sparse import csr_matrix

西皮有这个东西。

occurences = csr_matrix((visitors.shape[0], items.shape[0]), dtype='int8')def set_occurences(visitor, item):occurences[visitor, item] += 1trans2.apply(lambda row: set_occurences(row['visitors'], row['items']), axis=1)occurences

对数据中的每一行应用 set _ occurences 函数。

它会打印出这样的内容

<11719x12025 sparse matrix of type '<class 'numpy.int8'>'with 18905 stored elements in Compressed Sparse Row format>

在矩阵中的 1.4 亿个单元中,只有 18905 个填充了非零值。

所以基本上你只需要把这 18,905 个值存储到内存中。效率提高了 99.99%。

稀疏矩阵的缺点是,当试图实时检索数据时,它的计算量较高。所以,你不应该在这一步结束。

同现是一个更好的现象

让我们构建一个商品-商品矩阵,其中每个元素表示用户一起购买这两种商品的次数。称之为共生矩阵。

要创建一个共生矩阵,你需要将共生矩阵的转置矩阵和它本身进行点积。

我试过没有稀疏矩阵,我的电脑突然停止工作。所以,我们不要这样做。

cooc = occurences.transpose().dot(occurences)
cooc.setdiag(0)

它立即完成了一个稀疏矩阵。我很开心。

setdiag 函数将对角线设置为 0,这意味着您不想计算项目 1 的值,因为项目 1 是同一个项目,所以它们会放在一起。

反常行为更好

同现矩阵将由两个项目一起购买的次数组成。

但是有可能有一件物品。不管用户的行为如何,该商品都会被购买。可能是闪购之类的。

实际上,你可能想要真正捕捉用户的行为,从类似闪购的东西中清理出来。因为这不是你所期望的行为。

为了去除那些受影响的东西,你需要在同现矩阵上扣分。

泰德·邓宁斯在之前的书里有一个算法叫做,对数似然比或 LLR。

def xLogX(x):return x * np.log(x) if x != 0 else 0.0def entropy(x1, x2=0, x3=0, x4=0):return xLogX(x1 + x2 + x3 + x4) - xLogX(x1) - xLogX(x2) - xLogX(x3) - xLogX(x4)def LLR(k11, k12, k21, k22):rowEntropy = entropy(k11 + k12, k21 + k22)columnEntropy = entropy(k11 + k21, k12 + k22)matrixEntropy = entropy(k11, k12, k21, k22)if rowEntropy + columnEntropy < matrixEntropy:return 0.0return 2.0 * (rowEntropy + columnEntropy - matrixEntropy)def rootLLR(k11, k12, k21, k22):llr = LLR(k11, k12, k21, k22)sqrt = np.sqrt(llr)if k11 * 1.0 / (k11 + k12) < k21 * 1.0 / (k21 + k22):sqrt = -sqrtreturn sqrt

LLR 函数计算两个事件 A 和 B 同时出现的可能性。

这些参数是,

  1. k11,两个事件同时出现的次数
  2. k12,数 B 出现而无 A
  3. k21,A 出现的次数没有 B 多
  4. k22,其他一些东西出现的时候没有他们两个

现在计算 LLR 函数并保存到 pp_score 矩阵中。

row_sum = np.sum(cooc, axis=0).A.flatten()
column_sum = np.sum(cooc, axis=1).A.flatten()
total = np.sum(row_sum, axis=0)pp_score = csr_matrix((cooc.shape[0], cooc.shape[1]), dtype='double')
cx = cooc.tocoo()
for i,j,v in zip(cx.row, cx.col, cx.data):if v != 0:k11 = vk12 = row_sum[i] - k11k21 = column_sum[j] - k11k22 = total - k11 - k12 - k21pp_score[i,j] = rootLLR(k11, k12, k21, k22)

对结果进行排序,使每个项目的最高 LLR 分数出现在每行的第一列。

result = np.flip(np.sort(pp_score.A, axis=1), axis=1)
result_indices = np.flip(np.argsort(pp_score.A, axis=1), axis=1)

指标,如何推荐

结果矩阵上的第一个项目,如果足够高,可以被认为是该项目的指示器。

让我们来看看其中的一个结果

result[8456]

你会得到

array([15.33511076, 14.60017668,  3.62091635, ...,  0\.        ,0\.        ,  0\.        ])

看看这些指数

result_indices[8456]

会抓到你

array([8682,  380, 8501, ..., 8010, 8009,    0], dtype=int64)

您可以有把握地回答,对于高数量 LLR 分数,项目 8682 和 380 可以是项目 8456 的指示符。而项目 8501 由于分数没有那么大,可能不是项目 8456 的指示符。

意思是,如果有人买了 8682 和 380,你可以推荐他 8456。

容易。

但是,根据经验法则,您可能希望对 LLR 分数进行一些限制,这样无关紧要的指标将被删除。

minLLR = 5
indicators = result[:, :50]
indicators[indicators < minLLR] = 0.0indicators_indices = result_indices[:, :50]max_indicator_indices = (indicators==0).argmax(axis=1)
max = max_indicator_indices.max()indicators = indicators[:, :max+1]
indicators_indices = indicators_indices[:, :max+1]

现在你已经准备好把它们放在一起进行 elasticsearch 了。所以可以实时查询推荐。

import requests
import json

好了,现在你准备好把东西放进你之前准备好的 elasticsearch 里面了。

但是,要小心。如果你试图使用/_create/ API 一个一个地添加数据,那将花费你很长时间。当然,你可以,但是你可能需要半个小时到一个小时才能将我们的 12,025 个项目移动到 elasticsearch 中。

我做过一次,所以请不要重复我的错误。

那么解决办法是什么呢?

批量更新

幸运的是,elasticsearch 有 bulk API,可以很容易地一次发送多个文档。

因此,创建一个新的索引(items2,我在前面的错误中使用了 items ),让我们尝试一下

actions = []
for i in range(indicators.shape[0]):length = indicators[i].nonzero()[0].shape[0]real_indicators = items[indicators_indices[i, :length]].astype("int").tolist()id = items[i]action = { "index" : { "_index" : "items2", "_id" : str(id) } }data = {"id": int(id),"indicators": real_indicators}actions.append(json.dumps(action))actions.append(json.dumps(data))if len(actions) == 200:actions_string = "\n".join(actions) + "\n"actions = []url = "[http://127.0.0.1:9200/_bulk/](http://127.0.0.1:9200/_bulk/)"headers = {"Content-Type" : "application/x-ndjson"}requests.post(url, headers=headers, data=actions_string)if len(actions) > 0:actions_string = "\n".join(actions) + "\n"actions = [] url = "[http://127.0.0.1:9200/_bulk/](http://127.0.0.1:9200/_bulk/)"headers = {"Content-Type" : "application/x-ndjson"}requests.post(url, headers=headers, data=actions_string)

瞧,它将在几秒钟内完成。

在邮递员中点击这个 API

127.0.0.1:9200/items2/_count

您已经存储了您的数据

{"count": 12025,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0}
}

让我们用/items2/240708 检查你的项目数据

{"id": 240708,"indicators": [305675,346067,312728]
}

Id 是项目的 id。而指标是成为推荐该项目的指标的其他项目。

实时查询

我们创造的最好的部分是实时查询,

{"query": {"bool": {"should": [{ "terms": {"indicators" : [240708], "boost": 2}}]}}
}

将请求发送到127 . 0 . 0 . 1:9200/items 2/_ search

你会得到三个结果。312728、305675 和 346067。与 240708 号物品一起购买的三件物品。

太好了!所以,需要大量资源的问题现在已经不是问题了。那么,另外两个问题呢?

在那之前,让你的眼睛休息一会儿。

Photo by Sean O. on Unsplash

冷启动问题:我不认识你

构建推荐系统时最常见的问题是冷启动问题。每个新用户都不会在系统中记录他们的任何行为。

那么,系统应该给他们推荐什么呢?

让我们来看看我们最近建立的推荐系统。你认为结果有什么奇怪的吗?

是的,结果只返回 3 个推荐的项目。就三个。您计划如何向客户展示?

让我们在列表末尾显示另一个不推荐的项目。只是为了用户体验好。

{"query": {"bool": {"should": [{ "terms": {"indicators" : [240708]}},{ "constant_score": {"filter" : {"match_all": {}}, "boost" : 0.000001}}]}}
}

您可以使用常数分数来返回所有其他项目。

但是,对于所有不推荐的项目,您需要对它们进行排序,以便用户可能会喜欢的东西,即使没有在他们的行为中捕捉到。

很多情况下,热门单品确实很好用。

你如何计算一个受欢迎的项目?

popular = np.zeros(items.shape[0])def inc_popular(index):popular[index] += 1trans2.apply(lambda row: inc_popular(row['items']), axis=1)

简单,一件一件数物品外观。所以人气值最高的就是最受欢迎的。

让我们创建另一个名为 items3 的索引。和批量插入

actions = []
for i in range(indicators.shape[0]):length = indicators[i].nonzero()[0].shape[0]real_indicators = items[indicators_indices[i, :length]].astype("int").tolist()id = items[i]action = { "index" : { "_index" : "items3", "_id" : str(id) } }#     url = "[http://127.0.0.1:9200/items/_create/](http://127.0.0.1:9200/items/_create/)" + str(id)data = {"id": int(id),"indicators": real_indicators,"popular": popular[i]}actions.append(json.dumps(action))actions.append(json.dumps(data))if len(actions) == 200:actions_string = "\n".join(actions) + "\n"actions = []url = "[http://127.0.0.1:9200/_bulk/](http://127.0.0.1:9200/_bulk/)"headers = {"Content-Type" : "application/x-ndjson"}requests.post(url, headers=headers, data=actions_string)if len(actions) > 0:actions_string = "\n".join(actions) + "\n"actions = []url = "[http://127.0.0.1:9200/_bulk/](http://127.0.0.1:9200/_bulk/)"headers = {"Content-Type" : "application/x-ndjson"}requests.post(url, headers=headers, data=actions_string)

在这个索引阶段,您包括热门领域。所以,你的数据会像这样

{"id": 240708,"indicators": [305675,346067,312728],"popular": 3.0
}

您将有三个字段。Id 和指标像上一个,热门领域。用户购买商品的数量。

让我们将 popular 添加到前面的查询中。

函数分数,组合分数的方式

那么,你现在有多个分数来源,即指标匹配和热门,如何组合分数?

Elasticsearch 具有与此相关的功能评分。

{"query": {"function_score":{"query": {"bool": {"should": [{ "terms": {"indicators" : [240708], "boost": 2}},{ "constant_score": {"filter" : {"match_all": {}}, "boost" : 0.000001}}]}},"functions":[{"filter": {"range": {"popular": {"gt": 0}}},"script_score" : {"script" : {"source": "doc['popular'].value * 0.1"}}}],"score_mode": "sum","min_score" : 0}}
}

重做您的查询,并添加一个函数分数,将上面的常量分数稍微增加 0.1 倍。您不必坚持使用 0.1,您可以使用其他函数,甚至是自然对数。像这样,

Math.log(doc['popular'].value)

现在,您将看到您最受欢迎的项目 461686 位于第四位,就在推荐项目的下方。

下面还有其他受欢迎的项目。

不变的静态推荐

如您所见,每次运行实时查询时,我们的结果都保持不变。这可能是好的,因为我们的技术是可重复的,但同时,用户可能会不高兴。

书中的泰德·邓宁斯说,推荐的点击率,在第 20 个结果之后会下降得很低。这意味着我们在此之后推荐的任何项目都不会被用户知道。

这个怎么解决?

有一种技术叫做抖动。当查询显示最不推荐的项目,但仍然将强烈推荐的项目放在顶部时,这是在制造随机噪音。

{"query": {"function_score":{"query": {"bool": {"should": [{ "terms": {"indicators" : [240708], "boost": 2}},{ "constant_score": {"filter" : {"match_all": {}}, "boost" : 0.000001}}]}},"functions":[{"filter": {"range": {"popular": {"gt": 1}}},"script_score" : {"script" : {"source": "0.1 * Math.log(doc['popular'].value)"}}},{"filter": {"match_all": {}},"random_score": {}}],"score_mode": "sum","min_score" : 0}}
}

随机评分,它会给你所有的物品均匀分布随机噪音。分数会很小,所以最高推荐不会下降。

点击查询,并查看结果。你可以看到

积极的一面是。您的用户将不必滚动到第二或第三页。他或她只需要点击浏览器上的刷新按钮,就会有新的内容提供给他或她。

就像魔法一样。

Photo by Marvin Meyer on Unsplash

结论

构建一个生产就绪的推荐系统并不难。目前的技术允许我们这样做。

使用您的数据创建系统,并准备将其部署到生产环境中。

当然,你可以从这个人工智能的最佳课程中学习人工智能

干杯!

如何用 EDA 创建癌症生存预测模型

原文:https://towardsdatascience.com/how-to-create-a-simple-cancer-survival-prediction-model-with-eda-629dfa45d98b?source=collection_archive---------23-----------------------

利用 Haberman 的癌症生存数据集,使用 Python 创建一个简单的预测性癌症生存模型,对探索性数据分析技术进行全面的演练

Illustration by John Flores

这个博客和由此产生的癌症生存预测模型的动力是让人们一窥医疗保健行业的潜力。医疗保健继续从当前机器学习在其他行业的成功中学习宝贵的经验,以推动预测分析(也称为“健康预测”)的应用,并改善患者诊断、护理、慢性病管理、医院管理和供应链效率。[1]

这个分类项目是对 Haberman 数据集的探索性数据分析(EDA)的介绍,以确定开发一个简单的预测性癌症生存模型所必需的属性。该模型的预测将决定,手术后患者存活超过 5 年的可能性有多大?该记录最终基于三个属性自动进行患者的预后;年龄、手术年份和手术期间从患者身上切除的阳性腋窝淋巴结数目。

1.什么是探索性数据分析?

在机器学习领域,探索性数据分析(EDA)是一种哲学,或者说是一种用于分析数据集的方法。这是一种总结、可视化和熟悉数据集重要特征的技术。EDA 对于最大化洞察力、揭示底层结构、提取重要变量、检测异常值和异常值以及测试无意识/无意的假设非常有用。

虽然这个过程可能有点乏味,人们不会简单地,【插入经典的 LOTR 迷因】,跳过 EDA 过程,冲进机器学习阶段。事实上,EDA 技术是机器学习的前身,因为它用于回答以下问题:

如何定义潜在可用于机器学习的特征变量?如何选择最适合自己数据集的算法?

本质上,EDA 是为了挖掘数据能够告诉我们的超出正式建模或一般假设测试的内容,以创建适用的业务洞察力、模型和过程增强,这些对于业务利益相关者来说可能不明显或不值得调查。怎么会?通过在数据中寻找模式,从而洞察一些值得研究的有趣事物。

2.了解数据集

哈伯曼的生存数据集包含了 1958 年至 1970 年间在芝加哥大学比林斯医院进行的一项关于乳腺癌手术患者生存的研究。

您可以从下面的 Kaggle 链接轻松下载数据集:

[## 哈伯曼生存数据集

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/gilsousa/habermans-survival-data-set)

属性信息:

  1. 年龄:手术时患者的年龄(数值)。
  2. :患者手术切除淋巴结的年份(年份— 1900,数字)
  3. 淋巴结:检出阳性腋窝淋巴结数(数值)
  4. 状态:生存状态(职业属性)
  • 1 =患者存活了 5 年或更长时间
  • 2 =患者在 5 年内死亡

注意:只是提醒一下!在深入研究 EDA 之前,对数据集和手头的问题做一些背景研究总是一个好主意。我用“节点”做到了这一点,以下是我的发现。

背景:阳性腋窝淋巴结是位于腋窝(腋窝)的豆状小器官,沿淋巴液通道起过滤器的作用。当淋巴液离开乳房并最终回到血液中时,淋巴结在癌细胞到达身体其他部位之前捕捉并捕获癌细胞。因此,腋下淋巴结中有癌细胞表明癌症扩散的风险增加。

当淋巴结没有癌症时,测试结果是阴性的。然而,如果在腋窝淋巴结中检测到癌细胞,它们被认为是阳性的。

3.环境配置:导入库和加载数据文件

下面,您将了解如何设置您的环境以重复此 EDA 过程和癌症存活模型的详细信息。导入分析所需库的目的是:

  • Pandas 用于操作数据集
  • NumPy 用于对数据集进行数学计算和统计
  • Matplotlib 和 Seaborn 用于可视化
# Import the necessary packages 
**import** pandas **as** pd
**import** matplotlib.pyplot **as** plt
**import** seaborn **as** sns
**import** numpy **as** np# Load the dataset
haberman = pd.read_csv("haberman.csv")

4.数据细节

# Print first 5 lines of dataset
haberman.head()

输出:

# Personal preference: convert year format from 'YY' to 'YYYY'
haberman['year'] = haberman['year'] + 1900# Again, personal preference: convert survival status 1 and 2 to #'yes' and 'no', respectively
haberman['status'] = haberman['status'].map({1:'yes', 2: 'no'})# Print first 5 lines of altered dataset
haberman.head()

输出:

# Print the number of rows and columns for the dataset
haberman.shape

输出:

(306, 4)

观察:

  1. 的。csv 文件包含来自 306 名患者的数据,存储在描述数据集特征的行和 4 列中。
# Print the column names in dataset and the data type
haberman.columns

输出:

索引(['年龄','年份','节点','状态'],类型= '对象')

# Details about the dataset
haberman.info()

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 306 entries, 0 to 305
Data columns (total 4 columns):
age       306 non-null int64
year      306 non-null int64
nodes     306 non-null int64
status    306 non-null int64
dtypes: int64(4)
memory usage: 9.6 KB

观察:

  1. 该数据集中没有缺失值。
  2. 这 3 个属性是 int 数据类型,最后一个属性被转换为分类数据类型。
  3. 在“状态”栏中,最初的 int-type 被映射为“是”,这意味着患者存活超过 5 年。值“2”被映射为“否”,这意味着患者在 5 年内去世。
# Statistically describe the dataset
haberman.describe()

输出:

观察:

  1. 计数:每个相应列中存在的数据点总数为 306。
  2. Mean:关于年龄、年份和节点的每一列的平均值。
  3. Std(标准偏差):衡量一组数值与平均值或期望值相差多远。
  4. Min(最小值):每列中出现的最小值。
  5. 25%四分位数:1/4 的数据点低于规定值。
  6. 50%四分位数:1/2 的数据点低于提供的值。
  7. 75%四分位数:3/4 的数据点低于规定值。
  8. Max (Maximum):每列的最大值。
# Count each type of status in the dataset
haberman["status"].value_counts()

输出:

Yes 225
No 81
Name: status, dtype: int64

观察:

  1. value_counts 函数详细说明每个类有多少个数据点。这段代码描述了 5 年后有多少患者存活,有多少患者死亡。
  2. 在 306 名患者中,225 名存活,81 名未超过 5 年。
# Create a 'yes status' dataset to store 'yes' values for the patients that survived
status_yes = haberman[haberman["status"] == 'yes']
status_yes.describe()

输出:

# Create a 'no status' dataset to store values for the patients that did not survive
status_no = haberman[haberman["status"] == 'no']
status_no.describe()

输出:

观察结果:

  1. 关于年龄:否和是数据集的平均年龄和年份之间的差异没有统计学意义。注意:然而,有一种趋势描述了手术后 5 年未存活患者的年龄普遍增加。这种增加可以在非存活患者的最小年龄、四分位数百分比和最大年龄中看到。
  2. 年份:平均年份和否与是数据集之间的差异在统计学上并不显著。
  3. 在节点上:“是数据集”和“否数据集”的平均节点数都有显著增加。“无数据集”中的最大节点数也有所增加。无数据集的四分位数百分比也高于有数据集。注意:例如,对于 75%在手术后 5 年内死亡的患者,发现他们有 11 个或更多的淋巴结,相比之下,存活的患者只有 3 个淋巴结。

模型洞察:

  1. 平均而言,存活下来的人比没有存活下来的人少大约 2.5 倍的节点。存活的患者平均有 2.79 个淋巴结,而未存活的患者平均有 7.46 个淋巴结。

5.单变量分析

单变量分析是分析数据的最简单形式。这个过程不处理原因或关系,因为只涉及一个变量。相反,它的主要动机是描述;它获取数据,汇总数据,并找出单个特征中存在的模式。

5.1 概率密度函数

概率密度函数(PDF)是一种统计方法,用于衡量离散值的可能结果。PDF 绘制在一个典型的类似钟形曲线的图表上,结果的概率位于曲线之下。

这里,柱的高度表示相应组下的数据点的百分比。

PDF 背后的直觉是什么?

# Create a function for PDF analysis
def histoPDF(featureVar, classVar):sns.FacetGrid(data = haberman, hue = classVar, height = 5) \.map(sns.distplot, featureVar) \.add_legend(); plt.title("Histogram for " + featureVar)plt.ylabel("density")plt.plot('histogram_2.png')# PDF histogram for age v. status
histoPDF('age', 'status')

输出:

观察结果:

  1. 观察到大量的重叠,这表明年龄不是决定患者存活率的主要因素。
  2. 给定 PDF 中的重叠量,“是”数据集和“否”数据集之间的年龄差异几乎不可见。也许另一种统计方法可以揭示年龄和生存状态之间的模式。

模型洞察:

  1. 30-40 岁的人有更高的存活率,而 40-60 岁的人则没有。对于 60 岁以上的人来说,存活的机会大约是 50/50。
# PDF histogram for year v. status 
histoPDF('year', 'status')

输出:

观察结果:

  1. 主要的重叠继续再次表明,患者手术的年份并不影响他们 5 年后的生存率/结果。
  2. 1965 年手术的病人死亡率有一个高峰,而 1960 年手术的病人死亡率有所下降。
  3. 在 1960-1962 年间,病人存活的可能性增加了。
# PDF histogram for nodes v. status
histoPDF('nodes', 'status')

输出:

观察结果:

  1. 完全分离将是理想的,以区分存活患者的确切淋巴结数量。
  2. 有 0 个淋巴结或 1 个淋巴结的患者更有可能存活。如果有 25 个或更多的节点,存活的机会很小。
  3. 该图显示,淋巴结数目似乎比年龄和手术年份更能影响患者的存活率。

模型洞察:

  1. 5 个淋巴结后,患者越来越有可能无法存活。

6.累积分布函数

CDF 创建了一个经验累积分布函数图。使用 CDF 图确定 x 轴上等于或低于给定值的数据百分比。

# CDF analysis 
count1, bin_edges1 = np.histogram(status_yes['nodes'], bins = 10, density = True)
pdf1 = count1/(sum(count1))
print(pdf1, bin_edges1);
cdf1 = np.cumsum(pdf1)
plt.plot(bin_edges1[1:], pdf1)
plt.plot(bin_edges1[1:], cdf1, label = 'Yes')
plt.xlabel('nodes')print("---------------------------------------------------------")count2, bin_edges2 = np.histogram(status_no['nodes'], bins = 10, density = True)
pdf2 = count2/(sum(count2))
print(pdf2, bin_edges2);
cdf2 = np.cumsum(pdf2)
plt.plot(bin_edges2[1:], pdf2)
plt.plot(bin_edges2[1:], cdf2, label = 'No')
plt.xlabel('nodes')
plt.legend()plt.show()

输出:

观察结果:

  1. 根据 CDF 汇总统计,大约 83.55%存活的患者的淋巴结在 0 至 4.6 范围内。

7.盒须图和小提琴图

盒须图也称为盒状图,显示一组数据的五个数字汇总。五位数汇总是最小值、第一个四分位数、中值、第三个四分位数和最大值。该方框从数据的下四分位数延伸到上四分位数,中间有一条线。触须从框中延伸出来,以显示数据的范围。离群点是那些超过胡须末端的点。

小提琴图是箱线图和概率密度函数(CDF)的组合。Violin 图允许可视化一个或几个组的数字变量的分布。这是箱线图的近似形式,但可以更深入地理解密度。

# Create box and whisker plot for each feature
plt.figure(1)
plt.figure(figsize = (15, 5))
plt.subplot(131)
sns.boxplot(x = 'status', y = 'age', data = haberman)
plt.subplot(132)
sns.boxplot(x = 'status', y = 'year', data = haberman)
plt.subplot(133)
sns.boxplot(x = 'status', y = 'nodes', data = haberman)
plt.show()

输出:

# Create violin plots for each feature
plt.figure(1)
plt.figure(figsize = (15, 5))
plt.subplot(131)
sns.violinplot(x = "status",y = "age",data = haberman,height = 10)
plt.subplot(132)
sns.violinplot(x = "status",y = "year",data = haberman,height = 10)
plt.subplot(133)
sns.violinplot(x = "status",y = "nodes",data = haberman,height = 10)
plt.show()

输出:

观察:

  1. 相对而言,45 至 65 岁年龄组中有更多的人没有活下来。然而,患者年龄本身并不是决定其存活率的重要参数。
  2. 在 1965 年接受手术的人中,有更多的人活不过 5 年。
  3. 超过 1 个淋巴结的患者存活的可能性更小。一般来说,越多的淋巴结意味着存活率越低。
  4. 大部分存活的患者没有淋巴结。然而,有一小部分腋窝淋巴结为 0 的患者在术后 5 年内死亡,因此没有腋窝淋巴结阳性不能保证存活。
  5. 年龄和年份参数的箱线图和小提琴图给出了相似的结果,数据点有很大的重叠。与其他特征相比,节点的箱线图和小提琴图中的重叠较少,但是重叠仍然存在,因此很难设置阈值来对两类患者进行分类。

8.双变量分析

双变量分析是定量分析的另一种简单形式。双变量分析是对两个变量(属性)的同时分析。它探讨了两个变量之间关系的概念,是否存在关联以及这种关联的强度,或者两个变量之间是否存在差异以及这些差异的意义。

8.1 散点图

散点图揭示了两个变量之间的关系或关联。这种关系通过图中的任何非随机结构表现出来。
“关系”是指存在某种结构化关联(线性、二次等。)在 X 和 y 之间。

散点图是确定相关性的有用诊断工具,但如果存在这种相关性,该图可能会也可能不会提示潜在的因果机制。散点图永远无法“证明”因果关系——最终只有研究人员(依靠基础科学/工程)才能得出因果关系确实存在的结论。记住这句话:“相关性并不意味着因果关系”。

# Create scatter plot of age v nodes
sns.set_style("whitegrid")
sns.FacetGrid(haberman, hue = "status", height = 6)\
.map(plt.scatter, "age", "nodes")\
.add_legend()
plt.show()

输出:

观察结果:

  1. 年龄在 30 至 40 岁之间的 0 至 15 个淋巴结的患者更有可能存活。
  2. 不考虑年龄,具有 0 至 1 个淋巴结的患者更有可能存活。
  3. 50 岁以上有 5 个以上淋巴结的患者更有可能没有存活。

8.2 对图

配对图用于理解最佳特征集,以解释两个变量/维度之间的关系或形成最大程度分离的聚类。在我们的数据集中画一些简单的线或者做线性分离,也有助于形成一些简单的分类模型。

# Create pair-plot to determine a possible relationship between the columns / attributes
sns.set_style("whitegrid")
sns.pairplot(haberman, hue = "status", height = 5)
plt.show()

输出:

观察:

  1. 在年龄与节点之间的配对图中,可以用两条重叠的钟形曲线来区分类别变量。
  2. 为了进一步分析,年龄和节点属性可以考虑用于模式发现,因为您可以确定关系,无论多么模糊。
  3. 然而,所有其他属性在它们的 PDF 中没有显示出太大的差异。

9.多变量分析

多元分析是一次对许多变量的统计调查。在生命科学中,大多数问题本质上都是多元的。多元分析是一组用于分析包含多个变量的数据集的技术,这些技术在处理相关变量时尤其有价值。这些技术为信息提取、回归或分类提供了一种经验方法;这些技术中的一些是最近开发的,因为它们需要现代计算机的计算能力。

9.1 等高线图

等值线图是一种图形技术,通过以 2D 格式绘制常量 z 切片(称为等值线)来表示 3D 表面。也就是说,给定一个 z 值,在 z 值出现的地方画出连接(x,y)坐标的线。

# Create contour plot for the cross section of 3D graph
sns.jointplot(x = "year", y = "age", data = haberman, kind = "kde")
plt.show()

# Create contour plot for the cross section of 3D graph
sns.jointplot(x = "nodes", y = "age", data = haberman, kind = "kde")
plt.show()

观察:

  1. 大约从 1960 年到 1964 年,在 45 岁到 55 岁之间的病人身上完成了更多的外科手术。
  2. 大多数 0 至 1 个淋巴结的患者年龄在 45 至 65 岁之间。

结论

  1. 患者的年龄和手术年份本身并不是他们生存的唯一决定因素。然而,年龄小于 35 岁的人有更大的生存机会。
  2. 存活的可能性似乎与每位患者发现的阳性腋窝淋巴结数成反比。然而,数据显示没有阳性腋窝淋巴结并不总是保证存活。
  3. 对新患者的生存状态进行分类的目标是困难的,并且可能产生不可靠的结果,因为数据集需要额外的特征和属性。

10.简单哈伯曼生存模型

在数据分析和一点 EDA 之后,我们可以从上面的统计分析和图表中提取这些见解,以勾勒出一个预测患者存活率的简单模型。这是从哈伯曼数据集确定一个介绍性生存模型的许多方法之一。根据我观察到的数据,淋巴结的数量和年龄是决定病人生死的最大因素。您可以向该模型添加额外的功能来提高其准确性。

总的想法是,你允许你从 EDA 的观察来通知你的假设。

10.1 数据洞察

模型的计算方式:

  1. 年龄分组在~10 年内,从 30 岁开始,到 83 岁结束
  2. 按年龄组计算总人数。
  3. 计算在该年龄范围内存活的总人数。
  4. 计算在该年龄范围内死亡的总人数。
  5. 计算每组的总节点数和存活状态。
  6. 节点范围由从数据细节部分获取的幸存者和未幸存者的平均值决定。
  7. 最后,计算存活节点的平均数量。
  8. 并计算存活率。

模型洞察概要

Case 1: 10% Chance of not surviving when: Age 30–40 Nodes <= 7Case 2: 31% Chance of not surviving when: Age 40–50 Nodes >= 8Case 3: 28% Chance of not surviving when: Age 50–60 Nodes >= 9Case 4: 29% Chance of not surviving when: Age 61–70 Nodes >= 6Case 5: 29% Chance of not surviving when: Age 71–83 Nodes <= 2

10.2 创建模型

在 EDA 过程和收集生存模型的见解中,我得出了一个假设。我的理论或对这个模型的期望包括一个总体趋势,而如果节点数量和年龄增加,患者存活率实际上会下降。

# Create a simple Survival Prediction Model with if/else statements **def** survivalModel(age, nodes):**if** nodes **in** range(0, 4):            **if** age **in** range(30, 41): print('Survival rate is approximately 90%')**else**:print('Survival rate is approximately 74%')**elif** nodes **in** range(4, 7):              **if** age **in** range(30, 51):print('Survival rate is approximately 75%') **else**:print('Survival rate approximately 47%') **elif** nodes >= 7:              **if** age **in** range(30, 51):print('Survival rate is approximately 54%')**else**:print('Survival rate is approximately 40%')

10.3 测试结果

survivalModel(32,2)

输出:存活率约 90%

survivalModel(47,5)

输出:存活率约 75%

survivalModel(55,6)

产量:存活率约 47%

survivalModel(38,21)

输出:存活率约 54%

survivalModel(60,8)

输出:存活率约 40%

10.4 生存预测模型考虑因素

如果你对医学领域或普通生命科学感兴趣,我相信你很快就会意识到,有许多其他因素导致患者被诊断患有癌症,他们的治疗选择以及癌症存活的结果。其他因素,不包括在这个数据集,有助于癌症的生存,包括病人的饮食,一般身体健康,遗传素质等。因此,为了开发一个更加精确、可靠和全面的癌症生存预测模型,我们的数据集需要包括所有这些因素,以及其他无形(抽象)的因素,如手术过程中的人为错误、药物对身体的影响、手术后护理等。

然而,作为 EDA 的初学者指南,正如您已经发现的那样,Haberman 数据集是有限的,因此我们的预测模型实际上在范围和准确性方面都是有限的,即使是在使用当今具有相同癌症诊断的患者数据时也是如此。但是对于我们所需要的来说,它非常好,并且在实现模型时没有可怕的暗示,所以不用担心。我只想提几个警告。该模型的范围有限,不应用于任何关键决策。

总之,在创建模型时,您可以使用任何分类算法,如逻辑回归和支持向量机,如果您有足够的数据,您可以尝试神经网络。这只是一个介绍,您需要识别或创建更多的功能,执行功能缩放,最重要的是识别相关性和因果关系之间的差异。

参考资料:

[1] E. Just,L. Thatcher,T. Lawry,医疗保健中的机器学习:首席执行官必须知道哪些才能在他们的组织中有效地使用它(执行报告) (2018),Health Catalyst AI 知识中心

从头开始创建一个简单的统计学习模型:在回归中强调预测

原文:https://towardsdatascience.com/how-to-create-a-simple-statistical-learning-model-from-scratch-emphasizing-prediction-in-620d6fd8b94b?source=collection_archive---------20-----------------------

在 lm 的引擎盖下发生了什么?线性回归的估计、预测和验证教程

学习统计/机器学习可能会令人生畏,尤其是如果你像我一样来自另一个领域(例如,社会科学、生命科学、商业等)。有数百种复杂的模型可供选择,并且有大量的方案来验证您的数据。在这里,我们将仔细研究一个简单的预测模型,如果你完成了统计学课程,你可能会遇到回归。为什么这么简单?回归可能不像其他一些方法那样吸引人,但对基础知识有更深的理解对于转向更复杂的模型无疑是重要的。

当学习回归时,重点可能不是在预测(或预测值来自哪里),而是跳到输出,检查系数,并祈祷与所述系数相关的 p 值低于. 05。回归不一定只是推断统计的工具。正如我提到的,如果你已经运行了一个回归分析,你就已经完成了一个包括计算预测值的计算。

下面,我们将解开预测如何在两种不同的背景下展开。在第一种情况下,我们将处理存在 y 值的数据,这是一种常见的情况,分析师正在对结果和预测变量之间的关系进行推断。在第二种情况下,我们将预测遗漏数据的新 y 值。我们将在没有函数或库的帮助下完成所有这些,以说明如何使用线性回归作为经典 iris 数据集的基本预测工具。

首先要做的是加载虹膜数据集:

在我们开始自己的计算之前,让我们先来看看如何拟合一个线性模型,并使用该模型通过“lm”函数来预测基数 R 中的一些新数据。我们将尝试从 iris 数据集中的其他 3 个数值变量来预测萼片长度。首先,我们将获取一些训练数据(70/30 分割)并拟合我们的模型。

现在,我们将创建一些测试数据,并将其与来自训练数据的模型相结合,以创建一些预测。

预测看起来很棒!如果有人不小心删除了花卉数据库中有关鸢尾属植物萼片长度的信息,我们可以有把握地说,我们会很好地恢复这些信息。

当然,我们在这里关心的是确定“predict”正在做什么来产生这些值。我们一会儿就来看看。但是首先,我们将在更一般的意义上检查线性回归模型的预测。

我们将从检查如何在一组数据上预测新值开始,其中y 值和预测变量都存在(使用我们创建的 iris 训练数据作为例子)。首先,我们需要把 x 值和 y 值分开。我们将用一列 1 填充 x 矩阵来表示截距。

现在,我们需要转置 X,并将其乘以自身( X'X) 。这导致平方和/叉积矩阵, SSCP 。事实证明,通过一些操作,这个矩阵可以描述一组变量之间的方差/协方差、相关性或余弦关联。如果你有兴趣听到更多关于这方面的信息,请点击这里查看我的帖子。

我们的计算与实际叉积函数的输出相匹配。

接下来,我们将计算一个投影矩阵或帽子矩阵(在它的对角线上是观察杠杆)。

这将允许我们将 y 映射成预测的 y 值。

因此,如果我们可以访问 y 值,我们可以将它们与投影矩阵结合起来获得预测。这很好,但是我们如何使用训练数据来预测测试数据中 y 的新值呢?为此,我们需要为包含 y 值和 x 值之间关系信息的训练数据计算β系数。

通过与“lm”产生的值进行比较,我们可以确保计算出的β值确实是正确的。

我们可以将模型截距加到我们的测试数据中,然后乘以β系数(截距除外),得出我们的预测值。

到目前为止,我们所学的可以很容易地扩展到 kfold 交叉验证方案。下面的函数将创建折叠并返回一个包含原始数据集的列表,其中折叠作为一个新列。此外,还将返回包含折叠索引本身的列表。

让我们创建折叠,并确保他们有意义。

并使用 5 重交叉验证来拟合我们的模型:

我们可以提取和检查预测汇总统计数据。

最后,我们可以将我们的折叠指数传递给流行的预测建模包 caret,并确认我们的计算。

通过对折叠进行平均,我们的统计数据与 caret 的输出相匹配。

总之,我们仔细研究了预测在回归环境中的作用。我们最终能够应用我们所涵盖的计算对遗漏的数据进行预测。希望本教程能让你明白,当你在一行包含“lm”函数的代码上按下 ctrl+enter 时会发生什么。

如何创建成功的数据策略

原文:https://towardsdatascience.com/how-to-create-a-successful-data-strategy-1293bacf463c?source=collection_archive---------5-----------------------

Image from Pixabay CC0

随着人工智能和数据科学的快速发展,数据已经成为每个企业的重要资产。因此,建立数据策略已经成为每个企业的使命,尤其是在高管层和管理层。什么是数据策略,我们如何创建正确的数据策略?我想用这篇文章来回答这两个问题。

在讨论数据策略之前,我们需要了解什么是策略。用一个简单的定义来说,战略是一个深思熟虑的计划,专注于改变当前的状态,以实现未来的愿景。换句话说,正确的战略需要从愿景开始,战略是一种做出一系列改变的方式,通常需要创新和开箱即用的思维来实现愿景。在制定数据战略之前,每个企业都必须制定好业务愿景和业务战略。数据策略应该与业务策略携手并进,并服务于实现业务愿景。另一方面,数据与技术共存,同时为企业和客户提供价值。因此,数据战略也是数据和技术的战略。

给定了什么是数据策略的定义,我们也应该能够说什么是数据策略而不是。比如上云,采用 AI,聘请数据科学家,都不是数据战略;它们是我看到的经常与愿景或战略混淆的手段和工具。这种混乱要么导致“煮沸海洋”的昂贵努力,要么因为缺乏明确的方向和目标而注定失败。技术正以前所未有的速度发展,尤其是在数据和人工智能领域。只有当新技术能够帮助实现原有技术无法实现的业务愿景时,成功采用新技术才是重要和有意义的。因此,相对于现有系统而言,新技术能够带来的最终商业价值是探索新技术并使其成为战略的一部分的正当理由。另一方面,新技术可以推动新产品的新想法或新的创收机会。在这种情况下,新产品或收入机会需要成为业务愿景和业务战略的一部分,而技术则成为数据战略中的一项投资。换句话说,新技术的探索和采用应该与业务目标和业务愿景相一致。

要创建成功的数据策略,我们应该关注 6 个方面:一致性、架构、流程、组织、人员和长期规划。

与业务战略保持一致

这大概是数据策略最重要的方面。虽然数据策略的重要性已被广泛接受,但对于许多组织来说,它的实施仍然是一个大问题。这主要是因为通常情况下,业务人员对技术和数据没有信心,科学家或技术专家过于专注于技术,而没有将技术工具融入到业务挑战中。因此,只有当双方都关注业务成果时,才能实现协调:

  1. 在业务环境中定义业务目标和战略

业务目标和策略应该围绕需要为顾客和客户实现的结果,而不是限制潜在的技术解决方案。例如,当一个商业策略说“向公司的客户交付 API”时,它立即缩小了技术人员为最终客户构建 API 解决方案的范围。虽然这可能是可能的解决方案之一,但它并没有真正反映出客户在寻找什么。更恰当的说法是“客户需要一种方便的方式,以最少的人力从任何地方检索数据。”有了这个目标,解决方案将会非常不同,事实上,将会导致一个完全不同的策略,更加强调用户体验而不仅仅是 API。我们学到的教训是,业务人员应该通过关注期望的业务结果来陈述业务问题,并且避免从一开始就定义使用哪种技术。

2。设计和实施技术解决方案,从广阔的角度真正理解业务问题

技术专家总是在寻找新的工具、新的库,甚至新的编程语言。从一项新技术实现的那一刻起,它可能会逐渐失去它的荣耀,并由于其与更新的技术相比的局限性而招致批评。因此,我多年来看到的一个严重缺陷是,实现或更新只是为了技术进步,而不是解决业务问题。有时候,这是必要的,也是不可避免的。另一方面,我们应该尽量避免跟随技术世界中的宣传,而是将技术进步集中在业务用例上,并根据业务需求做出明智的决策。

在更高的层面上,数据策略的业务需求来自 3 个方面:产品、运营/流程改进和法规遵从性。这些领域的数据策略可能会有很大的不同。产品相关战略需要快速发现和集成新数据源的能力,以及交付新用户体验的能力。运营/流程改进主要应用于内部,关注效率、成本降低和质量改进。法规遵从性侧重于数据安全性。因此,有效的数据策略应该涵盖所有这些领域。

在有很多机会的人工智能和分析领域,数据战略应该与业务战略保持一致,以便设置优先级,并确定从哪些领域开始以及接下来计划什么用例。明确定义人工智能和机器学习(ML)的优先级并不是一件容易的事情,这首先需要对方法论、机会和大胆的愿景有深刻的理解。在这种情况下,业务和产品人员应该与技术和数据科学领导者密切合作,共同创造愿景和战略。

架构:数据量至关重要

在处理数据架构时,理解现有和未来的数据资产是关键。需要提出一些重要的问题,例如,解决业务问题需要什么类型的数据,典型的使用案例是什么,3 到 5 年内的数据量增长是多少。正如我在另一篇文章(大数据性能原则)中所述,处理小数据量更简单,这保证了更快的周期和更少的投资。但是,当处理大量数据时,体系结构将变得更加复杂,因此,成本将会更高,实施时间将会更长,风险也更大。如果不同来源和应用程序的数据大小确实不同,那么应该有不同的策略来处理每种情况,从一开始就有不同的思考和规划方式。鉴于技术的不断发展和数据量的不断增加推动了大数据架构的复杂性,大数据架构的战略也应该是深远的,其愿景可能不仅局限于 3-5 年,还应着眼于更长期的发展。

大数据的典型架构包括 3 个方面:1)数据源及其暂存区;2)数据湖和数据处理平台;3)交付解决方案。针对大数据的成功数据战略应该针对这三个领域进行不同的规划,并相应地将每个领域与业务目标保持一致。特别是,为大数据重建数据湖和数据处理平台的成本非常高,可能需要很长时间和大量资源。另一方面,添加数据源或开发新的交付解决方案可以相对快速和容易地完成,从而增加收入。构建可扩展、可集成、可持续的数据处理管道和平台是实现企业长期发展的核心策略。

组织:集权与分权

新的想法和创新往往来自业务部门,因为他们更接近客户和客户,而 It 或集中式数据技术团队拥有变更管理、可扩展生产系统、流程自动化和企业级解决方案方面的专业知识。将 IT“分散”到业务部门也称为“影子 IT”。其存在的原因显而易见:它拥有集中的资源,这些资源通常无法满足快速、灵活地满足客户需求的业务需求。另一方面,业务部门既没有大型生产环境的能力,也没有企业级软件解决方案的预算。当需要重新设计解决方案并进行迁移时,这种限制最终会导致“成长的烦恼”和资源浪费。

这种冲突在数据科学和人工智能领域变得更加明显。虽然业务部门的小型数据科学团队可以快速试验人工智能和机器学习算法,但他们也应该计划好如何同时扩展和生产他们的模型。整个生命周期,从新算法的实验开始,到集成和生产化,需要在数据策略中明确地讨论和执行,包括组织结构和业务与技术部门之间的合作关系。这项工作可以提高企业级效率,同时加快创新速度。例如,数据科学家可以专注于新想法,但不需要担心支持生产,而 IT/集中化技术团队则专注于构建和支持具有最佳性能的可扩展集成生产平台。换句话说,一个好的策略允许我们将数据生命周期视为一个整体,从最初的创新到最终的生产化和业务增长。它还促使技术和业务部门以相同的目标紧密合作,以实现双赢的结果。

流程:数据治理

任何数据策略的主题都是公司的数据资产。成功的数据战略应该有一个清晰的计划,说明如何释放数据资产的价值来服务于业务目的。数据治理是根据所有权、完整性、合规性、质量、内容以及与其他数据集的关系来管理这些数据集的过程。如果没有既定的治理,企业将缺乏对其数据集的清晰性和洞察力,这可能导致不一致或重叠的数据策略。正如 mime 的前一篇文章(主数据管理:数据策略的重要部分)中所述,为了确保主数据管理成为数据策略的一部分,数据治理流程对于策略的成功至关重要。数据治理是一个过程,其有效性通过交付的结果来衡量。其目的是提供透明度和效率,而不是混乱和官僚主义。考虑到数据治理在管理数据资产中的重要作用,数据治理应该是数据战略的一部分,应该有一个关于如何建立、实施和持续改进企业数据治理流程的更具体的计划。

人:人才与文化

人也应该是任何企业战略的一部分,数据战略也不例外。数据战略的不同之处在于,技术人才很难找到,而数据也需要机构知识才能产生成效。对现有人才的评估以及在培训或建立新人才管道之前的计划对于成功的数据战略来说至关重要。在这个领域,留住人才和发现新人才同等重要。建立具有多样化、互补的技能组合和多层次经验的团队应该是成功的数据战略的一个重要方面。

另一个方面是在组织中建立数据能力和数据文化。这并不是说任何访问数据的人都应该能够进行 SQL、Python 编程或运行机器学习算法。一个例子是,大多数人能够处理 Excel 电子表格中的数据。应该为人们建立相同级别的范围和能力,以便使用组织内的标准化工具轻松访问数据,这样人们就可以提取、分析和使用数据来改进决策和工作效率,而无需技术人员的帮助。这当然取决于公司内部的几项能力:轻松的数据访问、清晰的数据编目、带有访问和分析数据插件的自助服务工具的可用性,以及大量的培训。建立数据能力和强大的数据文化需要长期的努力,但对于一个组织来说,充分发现和实现其数据集对业务增长的价值是数据战略的重要组成部分。

长期能力和竞争力

数据是公司的资产,因此,处理数据是一项长期的工作,数据战略需要长远的眼光。事实上,一个成功的数据战略应该有一个超越业务战略的总体规划,以便为未来的业务战略和增长奠定长期基础。这是因为建立数据平台、基础设施、人才、文化需要时间,结果随着数据一起成为公司的资产。使用数据资产与构建程序或界面非常不同。它需要精心管理、长期投资和坚持不懈的努力。具有坚实基础和能力的稳定性对于一个公司在最少干扰和挫折的情况下高效快速地发展是至关重要的。虽然我们并不确切知道技术前景将会如何,但成功的数据战略将有助于企业做好准备并接受它,而不是以磕磕绊绊的方式应对它。在这方面,有效数据战略的优势在于强调数据资产和人员提供的价值,而不是新技术,新技术只是提取和实现数据价值的工具和方法。

总结

虽然数据战略与业务战略具有相同的组成部分,但它在战略领域仍相对较新。建立正确的数据策略首先需要业务愿景,并与业务策略保持一致。数据战略还应被视为长期愿景的促成因素,为未来的业务战略奠定基础。最后,防止数据策略纯粹是技术性的或以 IT 为中心是其成功的关键。换句话说,组织应该采取全面的方法来采用长期的数据战略,优化技术投资、人员和流程,以实现持续的业务增长。毕竟,正如吉米·罗恩所说:“成功是 20%的技能和 80%的策略。你可能知道如何成功,但更重要的是,你的成功计划是什么?”。

如何在 Excel 中创建显示覆盖在样本指标上的正常范围的可视化?

原文:https://towardsdatascience.com/how-to-create-a-visualization-showing-normal-range-overlaid-on-sample-metrics-in-excel-c73fc08c05b5?source=collection_archive---------3-----------------------

本文简介:创建图表的分步指南,该图表显示覆盖在多个数据系列的平均值、最小值和最大值上的正常范围。换句话说,实际与目标图表。本教程结束时,您将能够在 MS-Excel 中生成如下内容:

上面的图像来自我在 T2 发表的一篇研究论文,研究儿童接种疫苗的及时性。我们展示了自出生以来,儿童接受某种疫苗的天数范围。在此基础上,我们还在同一图表中显示了该疫苗的理想时间窗口。这有助于比较各种疫苗接种时机的好坏。

将定量变量的正常或理想范围覆盖在实际结果之上是可视化这种比较的常用方法。为了在 Excel 图表中实现这一点,我们依赖于为正常范围窗口和实际结果创建单独的数据系列。然而,为了获得不错的结果,我们需要滥用【Excel 提供的工具;我们用散点图而不是条形图来表示数据。如果你想自己练习,完整的教程文件在这里可以找到。

第一步:整理数据

创建图表需要三组数据:你想要显示的实际结果,代表要覆盖的正常范围的数值,第三组是在 y 轴上放置标签的数据。让我逐一解释。

系列 1:实际结果需要显示

这个系列有 6 个栏目。前三个是:

  • 样本中的儿童在出生后接受某种疫苗接种的最小中位数最大天数。例如,对于我收集的数据中的卡介苗,这些值分别为 0、13 和 304 天。稍后,中位数将在散点图中绘制为 x 值。

下一个是 y 值列:

  • y 值:包含每个 x 值的 y 值。这些是手动创建的,不是来自数据。当我们创建散点图时,您会看到这些值只是用来在 y 轴上垂直分布 x 值。

除此之外,还需要两列:

  • err_neg =中值—最小值
  • err_pos =最大值—中值

上面两列计算的数字将用于在中间值的两侧创建适当长度的误差线。您的数据表现在应该看起来像这样:

您可能会发现上表中列的位置有点奇怪。我这样做只是为了以后创建散点图更容易一些,只要正负误差的公式正确工作,列的顺序真的不重要。

系列 2:您需要显示的正常范围窗口

塑造这个系列的过程与第一个系列完全相同,有两个不同之处:

  1. 该系列中的最小值和最大值代表给定类别的任何正常范围的最小和最大极限。例如,儿童出生后应接种卡介苗的正常/适当天数的最小值和最大值分别为 0 天和 40 天。
  2. 这种情况下正常范围的‘中位数’是一个计算值,我们可以通过这个公式得到: =MEDIAN(min,max)

该系列的数据表应该如下所示:

系列 3:放置在 y 轴上的分类标签

我们可以简单地使用图表本身提供的 y 轴,但是我发现要将标签正确地放置在正确的距离上,并且没有显示 y 轴本身,这是非常烦人和困难的。因此,我使用了另一个数据系列来绘制标签,就像数据点一样。这给了我们更多的控制标签出现的地方。在本系列中,我为每个类别创建了 x 和 y 值列。下面的截图可以帮助你准备这个系列:

步骤 2:创建散点图

要创建第一个散点图,作为以后添加的所有内容的基础,首先选择前面创建的第一个系列(结果)的中间值和 y 值列。然后在功能区菜单中找到“插入”选项卡,选择第一种类型的“散点图”。

这应该给出下面的基本散点图。在这里,将轴调整正确是很重要的。如果你做得对,数据点应该对下面显示的 x 轴值有意义。

提示:如果您不确定散点图中的哪一列是 x 或 y 值,您可以通过右键单击图表,选择“选择数据”,然后单击相关系列的“编辑”按钮进行检查。这将显示哪个范围被选择为 x 值,哪个范围被选择为 y 值。

现在让我们清理一些图表垃圾,给我们一些喘息的空间。单击 y 轴以及垂直和水平网格线,然后按“Delete”键将其删除。

现在,我们将数据点标记从圆形转换为向上的三角形。双击任何数据点以选择整个系列。如果格式工具栏还没有打开,这应该会打开它。找到线条和标记设置,并从标记选项的内置选项中选择三角形。将“深红色”填充颜色(或您喜欢的任何颜色)应用于同一工具栏中的标记,并将相同的颜色应用于标记的边框。

现在你应该有这样漂亮的尖角标记:

现在,为了在中间值周围添加代表最小值和最大值的条,我们将使用误差线。单击图表顶部附近的“添加图表元素”按钮(或从功能区菜单中),然后单击“误差线”将水平和垂直误差线添加到数据点。然后点击垂直误差线,按“删除”键,只留下水平误差线。

现在单击水平误差线,在属性工具栏中,为误差量选择“自定义”选项。然后单击“指定值”按钮。这将打开一个对话框,询问正负误差量的数据范围。对于正误差,单击并拖动系列 1 的 err_pos 值,然后使用如下所示的 err_neg 值对负误差进行同样的操作。现在点击确定。

现在,您应该可以看到适当长度的误差线:

步骤 3:将第二个系列添加到散点图中

现在是时候添加代表正常窗口的第二个系列了。选中图表后,单击图表工具菜单中的“选择数据”。然后在“数据源”对话框中单击“添加”,添加新的一系列数据。在出现的下一个对话框中,通过单击并拖动第二个系列的 win_midy 值列下的值范围,添加这个新系列的 x 和 y 值(见下文)。您也可以从单元格 A8 中添加一个系列名称,但它以后不会显示在任何地方。现在单击确定,然后再次单击确定。

新系列应显示为代表正常范围窗口中点的点:

最终,我们将不再需要这些数据点,但为了便于选择,我们会暂时保留它们。对于这个系列,我们将再次使用误差线来创建一个正常的范围窗口。添加误差线的过程与我们在之前的系列中所做的完全相同。首先选择新系列的数据点,然后点击“添加图表元素”按钮,点击“误差线”选项添加误差线。然后选择垂直的并删除它们。

现在选择水平误差线,并在属性工具栏中为误差量选择“自定义”选项。然后点击“指定值”打开数值范围输入框。对于正误差,拖动第二系列数据中 err_pos 的值,对于负误差,使用 err_neg 下的值。然后单击确定。

在误差线仍处于选中状态的情况下,在误差线选项中选择“无帽”端样式。在填充和线条选项卡中,选择“实线”选项,并应用所示的绿色。然后改变透明度为 50%,宽度为 14 磅。

最后,要使中间的数据点消失,请单击任意数据点将其选中。然后在系列选项中选择“无填充”和“无线条”选项。

现在你应该有这样的东西:

步骤 4:创建标签系列

现在,我们将添加第三个也是最后一个系列,以显示图表中每个类别的标签。一般来说,这个过程与第二个系列相同,只是这里我们不使用任何误差线,而是从数据中添加标签。

选中图表后,单击图表工具菜单中的“选择数据”打开系列对话框。在这里,单击“添加”添加一个新系列。在接下来打开的范围输入框中,通过单击并拖动电子表格中第三个系列的 label_xlabel_y 列下的值,添加适当的范围(见下图)。然后单击确定,再单击确定。

沿着图表的左边界,你会看到新的系列只是点状的小点。右键单击这些点,然后从菜单中单击“添加数据标签”来添加标签。

标签还没有显示任何有意义的东西,所以让我们来解决这个问题。单击任意数据标签以选择所有数据标签。然后在属性工具栏中找到“标签选项”,点击“单元格中的值”。这将打开一个范围输入框。现在单击并拖动电子表格中第三个系列的标签列下所有类别的名称,添加这个范围。单击确定。

要清理它,取消选中标签选项中的“Y 值”和“显示引线”选项,并选择“左”作为标签位置。要为标签留出空间,请单击中央图表区,然后向右拖动此矩形的左边界(见下图)。

最后,要删除点标记,请单击标签系列的任何数据点,然后为系列中的标记选项选择“无填充”和“无线条”选项。

至此,该图表在技术上已经完成,除了一些调整:

第五步:简化和美化

在这最后一步,我们将做一些最后的润色,使图表看起来更加专业和完善。

  • 去掉 x 轴上的十进制数字:

  • 添加有意义的图表标题:

  • 使最小/最大条变粗并减少黑色:

  • 添加横轴标题,并将其命名为“Days”。
  • 最后,让字体稍微大一点,让文字更易读。

恭喜你!现在您已经准备好了最终的图表:

我个人喜欢做灰度图表,这里有一个灰度版本,可以获得更多灵感:

在此下载完整的教程文件。

如何在 5 分钟内创建一个天气机器人

原文:https://towardsdatascience.com/how-to-create-a-weather-bot-in-5-minutes-7d83b1052269?source=collection_archive---------12-----------------------

创建天气机器人来获取 Hala.ai 聊天中的天气信息。在本教程中,我们将使用服务https://weatherstack.com来获取当前天气的信息。

第一步。去https://weatherstack.com注册一个免费账户

第二步。注册后,转到https://weatherstack.com/quickstart并复制为您的帐户生成的 API 访问密钥和基本 URL

第三步。转到 Hala 平台上的Integration部分,添加新的 integration REST API,并传递您在上一步中复制的值。保存您的结果。

第四步。转到哈拉平台上的Actions段,新建一个action。提供操作的名称并选择集成。

第五步。对你的 API 服务进行配置。您可以在 API 提供者的文档中找到关于构建 API 的更多信息。在我们的例子中,你可以在这里阅读这个服务的 API 文档。完成后,保存您的更改。

第六步。您已经设置了整合和行动。现在,您需要创建一个意图来识别关于获取天气的用户输入。转到哈拉平台上的Intents部分,按下New Utterance

步骤 7。要更改意向的默认名称,点击默认值旁边的铅笔图标,或者您可以点击默认值,然后您将能够修改它。

步骤 8。指定意图的名称并回车

步骤九。现在你需要提供最终用户如何撰写天气预报的例子。你需要提供至少五个例子。

第十步。 Save你的变化和train model

第 11 步。现在,您需要创建一个实体来识别我们需要提供天气的城市。转到平台上的Entities部分,按下New Entity

Save你的变化和train model

第十二步。进入哈拉平台的Skill Kit部分,按下Create skill按钮创建技能

第十三步。提供技能的名称、描述和标签(最后两个是可选的)。按“下一步”创建对话流。

第十四步。你将进入创建对话流程界面。按下按钮Add new创建第一个根节点

第十五步。打开已创建的对话框节点并填充。

  • 字段名称—您可以输入任何值,例如“用户询问天气预报”
  • 条件——这里需要指定创建意图intent.get_weather

  • 操作—跳过此部分
  • 上下文—跳过此部分
  • 输出—这里我们需要询问用户我们需要为哪个城市提供天气预报

第十六步。现在您需要创建一个子节点来识别用户关于城市的输入。

第十七步。打开子节点,填充。

  • 字段名称—您可以输入任何值,例如“表单成功”
  • 条件—这里需要指定实体entity.city

  • 动作——当我们获得关于城市的信息时,我们可以向气象服务发送 API 请求。我们需要添加之前创建的操作。

查找并添加操作

当您添加操作时,您需要指定存储天气服务响应的上下文变量,例如context.weatherResponse

  • 上下文—这里我们需要将城市名保存到上下文变量中,该变量将被发送到天气服务。

  • Output —在 Output 中,您可以这样写“请稍候,我正在检查信息。”

第十八步。创建一个新的子节点来处理来自天气服务的 API 响应。

打开创建的节点并填充它:

  • 字段名称—您可以输入任何值,例如“提供结果”
  • 条件—指定在先前步骤中为动作响应创建的上下文变量:context.weatherResponse

  • 操作—跳过此部分
  • 上下文—跳过此部分
  • 输出—在输出中,我们需要提供关于天气的信息。要从 API 响应中访问数据,您需要使用下一个前缀context.weatherResponse.,然后指定所需数据的路径。所有的 API 提供者都有关于使用他们的 API 的信息。您可以阅读这些信息来创建正确的数据提取路径。

你可以使用下一段文字:

Weather forecast for {{context.weatherResponse.request.query}}Local time: {{context.weatherResponse.location.localtime}}Temprature: {{context.weatherResponse.current.temperature}}Wind speed: {{context.weatherResponse.current.wind_speed}}

第 19 步。按下“保存更改”按钮保存更改。现在,您已经创建了具有一个对话框节点的简单技能。

请记住保存您的更改。

第二十步。检验结果。使用下一个链接https://chat.hala.ai/进入哈拉网络聊天,并在聊天中键入第一条消息。您可以键入一个经过训练的短语,也可以使用未在意向训练中指定的新短语。

恭喜你!您已经创建了技能(机器人)并测试了它。

如何创建令人惊叹的数据科学产品组合

原文:https://towardsdatascience.com/how-to-create-an-amazing-data-science-portfolio-1ea4bc74ceee?source=collection_archive---------4-----------------------

Photo by Skye Studios on Unsplash

最近,我写了一篇文章,提出了进入数据科学领域的建议。如果你感兴趣,你可以在这里找到这篇文章:

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

进入数据科学领域的建议

towardsdatascience.com](/standing-out-in-a-sea-of-data-scientists-c82e42a1e62b)

其中一条建议是“获得定义和解决端到端机器学习问题的经验。”我对如何有效地做到这一点有一些疑问,所以我想更深入地了解一下我将如何开始构建数据科学投资组合。

热情

你不太可能有充足的空闲时间,因此致力于构建你的数据科学投资组合肯定需要投入和牺牲。根据我的经验,只有当你追求一个你充满激情的项目时,你才会成功。激情也不一定要很明显。就我个人而言,我对写作一点也不热衷,但我热衷于分享想法。写作是一个很好的媒介,通过它我可以追寻我对想法的热情。也许你真的想做一个深度学习的项目,但缺乏动力。但也许你对音乐充满热情。你可以通过使用深度学习创作音乐来开始你的作品集。当你很想放弃的时候,将你的努力集中在你的激情上可以极大地帮助你坚持下去。

定义你自己的问题

在 Kaggle 等平台上围绕预定义的问题构建辅助项目是非常诱人的。虽然这无疑使过程更容易,但它有效地消除了数据科学过程中最重要的部分之一:定义问题。在行业中,通常最大的挑战之一是将业务问题转化为数据科学问题。在编写任何代码之前,请仔细考虑以下事项:

  • 我想解决什么问题?
  • 我认为我可以如何使用数据科学来解决这个问题?
  • 如果我能解决这个问题,会创造什么价值?

你的答案可能很简单,我想创作听起来像我最喜欢的乐队的音乐;我做了一些研究,看起来深度学习在解决这个问题上取得了一些成功;如果我能解决它,我将拥有无限的听起来像我最喜欢的艺术家的音乐!

这一步是必不可少的,因为它为你的项目故事搭建了舞台。这将帮助你更好地向他人解释你为什么选择这个项目,并展示你解决问题时的战略思维。

收集你自己的数据

如果您定义了自己的问题,这一步几乎肯定是强制性的。你的问题可能是独特的,因此你需要花一些时间收集数据。这太棒了!根据我的经验,我发现我花了大量的时间来思考收集数据来帮助解决我的问题的最佳方式。现在,您可以在您的项目中展示该技能。对于我们的音乐示例,它可能包括检查包含高质量合法音频下载的免费音乐档案库。我保证,通过探索如何获取和收集您自己的数据,您将学到数据科学过程中至关重要的一步,也是学校不常教授的一步。

Photo by Craig Whitehead on Unsplash

展示数据探索

正如安德烈·卡帕西所说:

与数据融为一体

任何机器学习项目的第一步都是花时间检查和分析你的数据。不要跳过这一步。它不仅重要,而且还允许你创建一些非常棒的可视化效果。深入挖掘您的数据,查看以下内容:

  • 有没有异常值?
  • 你的特性分布是怎样的?
  • 绘制特征和目标之间的相关性
  • 看看你的数据的实际例子

在这一步中,您还可以做更多的事情,但是这些都是一个很好的起点。使用 seaborn 让你的情节更漂亮,或者如果你有野心,试着让可视化与类似 Plotly 的东西互动。此处的目标是向他人展示您如何分析数据以发现他人可能忽略的智慧,这将使您的模型变得更好。

构建多个模型

太多时候,我看到项目只展示最好的模型。一个伟大的作品集项目可以让人了解你的思维过程,所以请给我们看看!为了有效地做到这一点,我推荐以下过程:

  • 首先,创建一个非机器学习基线。这个基线应该是合理的,比如历史平均值。这是评估你的第一个基于机器学习的模型的关键一步。
  • 其次,创建你的第一个机器学习模型。描述你为什么选择从这个模型开始,并与你的基线进行比较。
  • 第三,建立你的第二个机器学习模型。这一步的关键部分是清楚地解释为什么这是下一个最好的步骤。您的模型是否过拟合,因此您需要使用不太复杂的模型或添加正则化?也许您使用了相同的模型,但是基于错误分析开发了额外的特性。
  • 第四,重复第三步,直到你对结果感到满意。

最后,你不仅应该在你的项目中有多个模型,而且你将有一个逻辑故事来解释你如何考虑开发一个伟大的机器学习模型。

讲故事

在这一点上,你已经有了很多关键的组件,你可能会觉得你就要完成了。没那么快!你现在需要回去,把你所有的工作联系起来,讲一个伟大的故事。

伟大的数据科学家是伟大的故事讲述者

这是为你的作品集创造一个令人惊叹的项目的最重要的一步。如果你跳过这一步,你可能只是 GitHub 上的一堆代码。那不是投资组合。使用博客平台,如 Medium,或者你甚至可以创建自己的博客,并解释你的旅程。写下项目的目标,突出关键的探索性分析,包括你的建模结果和思考过程,告诉我们你的项目是如何创造价值的。

把这想象成你如何向主管们展示你的项目。你不需要包含任何代码(但是一定要链接到你在 GitHub 上的代码)。

Photo by JOSHUA COLEMAN on Unsplash

重复

现在你的投资组合中有了一个漂亮的项目。你现在要做的就是重复这个过程。:)这确实需要大量的工作和时间,但通过持续、专注的努力,你会发现自己有一些利用机器学习在你感兴趣的领域创造价值的故事(确保你在 LinkedIn 和简历上突出了你的投资组合)。这是一个惊人的数据科学产品组合,肯定会帮助您脱颖而出。寻找一些灵感?查看蒂姆·德特默斯的数据科学作品集。

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

获取免费指南来帮助你学习部署你自己的项目的步骤。

如何在 R 中创建一个带有自动 Amazon 附属链接的交互式书单

原文:https://towardsdatascience.com/how-to-create-an-interactive-booklist-with-automatic-amazon-affiliate-links-in-r-7c1304dec43?source=collection_archive---------24-----------------------

Photo by Piotr Cichosz

介绍

B 书目是分享你读过的书籍、推荐给其他读者和/或推广你所写的书籍的有用方式。它可以简单到在你的个人网站或博客上显示的一系列书名。然而,你可能希望以一种更复杂的方式来呈现这份书单,比如在一个表格中列出书名、作者和购买链接。

在这篇博文中,我将向你展示如何在 r 中创建一个带有自动 Amazon 附属链接的交互式书单。此外,我所说的自动亚马逊联盟链接指的是直接重定向到亚马逊网上商店中有问题的书的 URL(当然是你的联盟链接),而不是手动为每本书创建一个链接。

这种技术对那些列表中有数百本书的人特别有用,因为你只需要创建一次 URL,它就会自动适应所有的书。如果这还不清楚,请看这里的一个实例。

要求

为了用你的会员链接建立这个扩充的书单,你需要:

  • 一个亚马逊协会的账户。如果您还没有帐户,请在此注册
  • 书单(你推荐和/或你写的)

创建书单

你有两个选择:

  1. 在 Excel 中创建它,然后导入到 R
  2. 直接在 R 中创建它

在 Excel 中创建它,然后导入它

最简单的方法是遵循以下步骤:

  1. 打开一个 Excel 文件,用两列填写:(I)一列是标题,(ii)第二列是作者(见下图)
  2. 以. csv 格式保存(在 Excel 中,文件>另存为…>选择 CSV 文件格式并保存)
  3. 将其导入到 R 中(如果您在导入过程中遇到困难,请参见如何导入. csv 文件)
  4. (如果您以后需要编辑该列表,请直接在。csv 文件而不是 Excel 文件)

下面是你在 Excel 中创建的书单的样子(你的书单里应该有更多的书):

Step 1: Booklist created in Excel

我们现在将它导入 RStudio,并将数据集重命名为dat(参见这里的为什么我总是使用通用名称而不是更具体的名称):

dat <- read.csv("booklist.csv", # name of your file with .csv extensionheader = TRUE, # names of variables are presentsep = ","
) # values are separated by a comma

您可以通过运行head(name_of_dataset)View(name_of_dataset)来检查您的书目是否被正确导入。

直接在 R 中创建它

您可以使用命令data.frame()直接在 R 中创建您的图书列表:

# Create the data frame named dat
dat <- data.frame("Title" = c("A Random Walk Down Wall Street","Naked Statistics","Freakonomics"),"Author" = c("Burton G. Malkiel","Charles Wheelan","Steven D. Levitt and Stephen J. Dubner"),stringsAsFactors = FALSE
)
# Print the data frame
dat##                            Title                                 Author
## 1 A Random Walk Down Wall Street                      Burton G. Malkiel
## 2               Naked Statistics                        Charles Wheelan
## 3                   Freakonomics Steven D. Levitt and Stephen J. Dubner

让它互动

为了能够按作者或书名搜索书籍,我们使用 DT 包中的datatable()命令。下面的代码为带有默认选项的表格:

library(DT)
datatable(dat)

Example of interactive table with the {DT} package

让我们通过以下方式改进此表:

  • 删除行号
  • 在“标题”和“作者”列上添加过滤器
  • 增加了复制或下载表格的可能性
  • 仅显示前 5 个条目,而不是 10 个
  • 按书名升序排列书籍
datatable(dat,rownames = FALSE, # remove row numbersfilter = "top", # add filter on top of columnsextensions = "Buttons", # add download buttonsoptions = list(autoWidth = TRUE,dom = "Blfrtip", # location of the download buttonsbuttons = c("copy", "csv", "excel", "pdf", "print"), # download buttonspageLength = 5, # show first 5 entries, default is 10order = list(0, "asc") # order the title column by ascending order)
)

Improved interactive table

将带有代销商链接的 URL 添加到表格中

我们现在要在上面的互动表格中添加取决于书名和作者的网址(包括你的会员链接)。为此,我们首先需要提取作为 URL 基础的附属链接,然后在 URL 末尾添加书名和作者。事实上,我们在 URL 的末尾添加了书名和作者,这使得它是自动的。事实上,最终的 URL 将重定向到该书的搜索页面(由于书名和作者作为关键字),并包括您的附属链接(因为我们使用附属链接作为基本 URL)。

提取附属链接

要提取代销商链接,请遵循以下步骤(参见下图获取帮助):

  1. 转到您的亚马逊协会帐户
  2. 点击产品链接>链接到任何页面
  3. 点击“搜索结果链接”选项卡
  4. 为产品系列选择“书籍和教科书”
  5. 输入你想要的任何关键字和你的链接的名称(这两个将在以后改变,所以你输入什么并不重要)
  6. 点击“获取 HTML”按钮
  7. 将预览(右窗格)中显示的代码复制到剪贴板中(Windows 上为 CTRL+c,Mac 上为 cmd+c)

Step 2: Link to Any Page on Amazon associates account

Step 3 to 7: Create Amazon affiliate link for a search page

您刚才复制的代码应该是这样的(虽然不完全相同,因为它包括您的个人会员链接):

<a target="_blank" href="https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=BOOK TITLE">BOOK TITLE</a><img src="//ir-na.amazon-adsystem.com/e/ir?t=antoinesoetew-20&l=ur2&o=1" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

从这段长代码中,删除所有跟在keywords=后面的内容,但保留keywords=(这就是为什么你在上面的步骤 5 中键入的内容并不重要)。按照我们的示例,我们只剩下这段代码:

<a target="_blank" href="https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=

复制这个缩短的代码。

追加书名和作者使其自动化

我们现在将连接(即,将几个字符串附加在一起)Amazon affiliate 链接(我们刚刚复制的代码)、书名和作者,然后是一个带有paste0()命令的结束 HTML 标记。结果将是一个 URL,它以附属链接为基础,以书名和作者为关键词,使它自动适应你书单上的每本书。为此,在 R 中运行以下命令:

# Do not mix " and ', they are different in this case!
link <- paste0('<a target="_blank" href="https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=', # affiliate linkdat$Title, " + ", dat$Author, # book title and author'">Amazon</a>' # closing HTML tag
)

你的链接应该看起来像这样,所有的书都有相同的附属链接和结束标签,但有不同的关键字,对应于书名和作者:

head(link)## [1] "<a target=\"_blank\" href=\"https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=A Random Walk Down Wall Street + Burton G. Malkiel\">Amazon</a>"   
## [2] "<a target=\"_blank\" href=\"https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=Naked Statistics + Charles Wheelan\">Amazon</a>"                   
## [3] "<a target=\"_blank\" href=\"https://www.amazon.com/gp/search?ie=UTF8&tag=antoinesoetew-20&linkCode=ur2&linkId=a587bdd780cbbfb6d3f4569f7fb358fc&camp=1789&creative=9325&index=books&keywords=Freakonomics + Steven D. Levitt and Stephen J. Dubner\">Amazon</a>"

向交互式表格添加链接

既然 URL 是特定于每本书的,我们可以将它们添加到前面构建的交互式表格中:

dat$Link <- link

最后,我们可以显示带有标题、作者及其 URL 的交互式表格:

datatable(dat,rownames = FALSE, # remove row numbersfilter = "top", # add filter on top of columnsextensions = "Buttons", # add download buttonsoptions = list(autoWidth = TRUE,dom = "Blfrtip", # location of the download buttonsbuttons = c("copy", "csv", "excel", "pdf", "print"), # download buttonspageLength = 5, # show first 5 entries, default is 10order = list(0, "asc") # order the title column by ascending order),escape = FALSE # to make URLs clickable
)

这与之前的代码完全相同,只是我们需要添加escape = FALSE来使 URL 可点击。

决赛成绩

Final result of the interactive booklist with affiliate links

通过点击不同的链接来检查一切是否正常。如果您没有错过任何步骤,它会将您重定向到亚马逊商店,在搜索栏中显示书名和作者,从而在搜索结果中显示有问题的书。

感谢阅读。我希望这篇文章能帮助你建立一个交互式书单,并自动链接到你书单上的每本书。如果你想看一个活生生的例子,请看我的个人书单。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

相关文章:

  • 一种安装和加载 R 包的有效方法
  • 我的数据符合正态分布吗?关于最广泛使用的分布以及如何检验 R 中的正态性的注释
  • R 中的 Fisher 精确检验:小样本的独立性检验
  • R 中独立性的卡方检验
  • 如何在简历中创建简历时间线

原载于 2019 年 12 月 26 日【https://statsandr.com】

如何创建交互式 Dash Web 应用程序

原文:https://towardsdatascience.com/how-to-create-an-interactive-dash-web-application-11ea210aa6d9?source=collection_archive---------22-----------------------

使用 Dash、Heroku、XGBoost 和 Pickling 创建预测性 Web 应用程序

您已经完成了数据科学,现在您需要向全世界展示结果! Dash 是一个用于构建 web 应用的 python 框架。Dash 基于 Flask、Plotly.js 和 React.js 编写,非常适合快速构建定制的 web 应用程序。一旦构建完成,网络应用程序可以很容易地部署在云平台上,如 Heroku 。

先说最终产品。下面这个简单的 web 应用程序使用户能够确定一个面临竞价大战的房屋的预计价格。预测价格基于 2015 年至 2019 年在加利福尼亚州马林县出售的所有单户住宅的历史数据,收到两个或更多报价。用户可以选择面积,卧室数量,浴室数量,预期报价和上市价格的数量,应用程序将提供预测的销售价格。

要使用 web 应用程序,只需选择预测选项卡,选择标准,应用程序将返回预测的报价。有关目标、数据、评估协议和模型选择的说明,请使用解释选项卡。“评估”选项卡提供了用于评估预测相对于实际中标报价的准确性的指标。

预测竞价战中标价格的互动网络应用

如果您想了解如何开发自己的交互式 web 应用程序,请跟随我一步一步地指导您完成这个过程。

关于代码的一句话

该项目的所有代码、数据和相关文件都可以在 my GitHub 访问。安装 Dash 后,从代码所在的目录运行本地计算机上的代码,并从您的终端运行 python app.py 。这将在您的本地主机(127.0.0.1:8050)上运行应用程序。

数据科学

由于本文的重点是交互式 web 应用程序的创建,我将简要描述用于预测最佳投标价格的数据科学。详情请看 colab 笔记本这里。

原始数据是 2015 年至 2019 年在加利福尼亚州马林县出售的所有收到两个或更多报价的单户住宅的历史数据。导入原始数据并将区域映射到城市名称后,数据如下所示:

All Multiple Offer Sales in Marin County, CA 2015–2019

数据分为培训(2015 年至 2017 年)和验证(2018 年)以及测试(2019 年),培训和验证分别涉及 2,973 次销售和 991 次销售,测试涉及 776 次销售。该测试集包含 2019 年约 11 个月的数据。

# Split into train and test - 2015-2018 in train, 2019 in test
low_cutoff = 2015
high_cutoff = 2019
train = df[(df['Year'] >= low_cutoff) & (df['Year'] < high_cutoff)]
test  = df[df['Year'] >= high_cutoff]# Split train into train and validation - 2015-2017 in train and 2018 in validation
cutoff = 2018
temp=train.copy()
train = temp[temp['Year'] < cutoff]
val  = temp[temp['Year'] >= cutoff]

最初进行了简单的线性回归,结果非常好。然后运行一个 XGBoost 模型,它有稍微好一点的指标,因此被选为模型。

XGBoost Metrics

腌制

Pickling 用于序列化和反序列化 Python 对象(也称为编组或扁平化)。当您想要保存过程以便在以后进行预测而不必重新训练您的模型时,Pickling 在使用机器学习算法时非常有用。在我们的例子中,我们将清理管道,并在我们的 web 应用程序中使用它来进行预测。

首先,我们从 joblib 导入 dump:

from joblib import dump

接下来,我们运行 XGBoost 模型并转储管道。这实际上是将管道保存到本地磁盘上一个名为 pipeline.joblib 的文件中。然后,这个文件被加载到 GitHub 中,并在 web 应用程序的 predict.py 代码中使用。

# Encode and fit a XGBoost model
target = 'Selling Price'features = train.columns.drop(target)
X_train = train[features]
y_train = train[target]
X_val = val[features]
y_val = val[target]
X_test = test[features]
y_test = test[target]pipeline = make_pipeline(ce.OneHotEncoder(use_cat_names=True), XGBRegressor(n_estimators=200, n_jobs=-1)
)pipeline.fit(X_train, y_train)
dump(pipeline, 'pipeline.joblib')
y_pred = pipeline.predict(X_val)

Dash App

Dash 应用由定义应用外观的“布局”和创建交互性的“回调”组成。我们的基本 Dash 应用程序由 app.py 和 index.py 文件组成。如果你用过烧瓶,那么这段代码看起来会很熟悉!

app.py

import dashexternal_stylesheets = ['[https://codepen.io/chriddyp/pen/bWLwgP.css'](https://codepen.io/chriddyp/pen/bWLwgP.css')]app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = True
server = app.server

app.py 文件只是初始化和实例化 Dash 应用程序。

index.py

from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as htmlfrom app import app, server
from tabs import intro, predict, explain, evaluatestyle = {'maxWidth': '960px', 'margin': 'auto'}app.layout = html.Div([dcc.Markdown('# Multiple Offer Calculator'),dcc.Tabs(id='tabs', value='tab-intro', children=[dcc.Tab(label='Intro', value='tab-intro'),dcc.Tab(label='Predict', value='tab-predict'),dcc.Tab(label='Explain', value='tab-explain'),dcc.Tab(label='Evaluate', value='tab-evaluate'),]),html.Div(id='tabs-content'),
], style=style)[@app](http://twitter.com/app).callback(Output('tabs-content', 'children'),[Input('tabs', 'value')])
def render_content(tab):if tab == 'tab-intro': return intro.layoutelif tab == 'tab-predict': return predict.layoutelif tab == 'tab-explain': return explain.layoutelif tab == 'tab-evaluate': return evaluate.layoutif __name__ == '__main__':app.run_server(debug=True)

index.py 文件是应用程序的主要可执行文件。它分为两个主要部分:布局和回调。我们先来看一下布局。

布局

Dash 提供了两套可视化组件: dash_html_componentsdash_core_components 。dash_hml_components 库为每个 HTML 标签提供了一个组件。dash_core_components 库是更高级别的组件,如选项卡、下拉列表、降价模块、图表等。

对于我们的应用程序的布局,我们将使用 html 保持简单。dcc 部门。app.layout 定义了我们在 html 中的布局。Div(在 HTML 文档中定义一个部分)dcc。Markdown 使用 Markdown 和 dcc 创建标题。Tab 创建四个标签,标签在标签中可见,一个值用于编码。就这样——我们基本上已经创建了主页!

回调

Dash 使用 @app.callback decorator 告诉应用程序如何处理输入和输出。在我们的应用程序中,输入是布局 dcc 中定义的 id='tabs 。有四个子项的选项卡—介绍、预测、解释和评估。输出是在 html.Div 中定义的 id='tabs-content '。当用户单击一个选项卡时,输入识别该选项卡,调用 render_content(tab) 构造函数(函数)将选项卡更改为被单击的选项卡,然后结果输出到 html.Div。就这样——一个非常简单的回调!

预测选项卡

了解了基础知识之后,让我们用预测选项卡来看看一个更复杂的例子。在 predict.py 代码中,我们将使用一个下拉菜单和四个滑动标签来获取我们的预测输入。然后,输入将用于运行我们的 pickled 预测并输出结果。

style = {'padding': '1.5em'}layout = html.Div([dcc.Markdown("""### PredictUse the controls below to update your predicted offer, based on city,beds, baths, number of offers, and list price."""),html.Div(id='prediction-content', style={'fontWeight': 'bold'}),html.Div([dcc.Markdown('###### Area'),dcc.Dropdown(id='area',options=[{'label': city, 'value': city} for city in cities],value=cities[10]),], style=style),html.Div([dcc.Markdown('###### Bedrooms'),dcc.Slider(id='bedrooms',min=1,max=7,step=1,value=3,marks={n: str(n) for n in range(1, 7, 1)}),], style=style),html.Div([dcc.Markdown('###### Baths'),dcc.Slider(id='baths',min=1,max=9,step=1,value=2,marks={n: str(n) for n in range(1, 9, 1)}),], style=style),html.Div([dcc.Markdown('###### Number of Offers'),dcc.Slider(id='offers',min=2,max=15,step=1,value=3,marks={n: str(n) for n in range(2, 15, 1)}),], style=style),html.Div([dcc.Markdown('###### Listing Price'),dcc.Slider(id='list_price',min=1000000,max=3000000,step=100000,value=1500000,marks={n: f'{n/1000:.0f}k' for n in range(1000000, 3000000, 100000)}),], style=style),])[@app](http://twitter.com/app).callback(Output('prediction-content', 'children'),[Input('area', 'value'),Input('bedrooms', 'value'),Input('baths', 'value'),Input('offers', 'value'),Input('list_price', 'value')])
def predict(area, bedrooms, baths, offers, list_price):year = 2019df = pd.DataFrame(columns=['Year', 'Area', 'Total Bathrooms', 'Bedrooms', 'Curr List Price', 'Number of Offers'],data=[[year, area, baths, bedrooms, list_price, offers]])pipeline = load('model/pipeline.joblib')y_pred_log = pipeline.predict(df)y_pred = y_pred_log[0]percent_over = ((y_pred - list_price) / list_price) * 100per_offer = percent_over / offersresults = f'The predicted winning bid is ${y_pred:,.0f} which is {percent_over:.2f}% over the asking price or \{per_offer:.2f}% per offer.'return results

虽然这看起来可能有很多代码,但实际上非常简单。该布局仅由四个组件组成——html。dcc 部门。降价,dcc。我们的布局由六个 html 组成。Div (sections ),预测在第一节,组件在接下来的五节。五个组件提供输入。

每当任何单个输入发生变化时,都会调用回调函数,调用预测函数并将结果输出到第一部分。

注意在预测函数中:

pipeline = load(' model/pipeline . joblib ')
这将加载转储的管道,允许使用很少的代码非常快速地进行预测。

这是对 Dash 的一个非常简单的介绍。如需了解更多详情,请查看 Dash 文档此处。

Heroku 部署

一旦你让交互式网络应用在本地运行,你就可以让其他人通过使用公共托管服务(比如 Heroku)来访问它。Heroku 将托管该应用程序,允许您链接到它或使用 iframe。

在 Heroku 上托管的基本步骤是:

1.创建一个 Procfile 和 requirements.txt 文件。在我的[GitHub][4]里看到我的。

2.创建一个 Heroku 应用程序并连接到您的 GitHub 存储库。

3.运行应用程序!

我欢迎建设性的批评和反馈,请随时给我发私信。

有关 web 应用程序的更多背景信息,请参见配套文章“如何赢得房地产投标战”。

这篇文章最初出现在我的 GitHub Pages 网站上。

在推特上关注我

马林房地产数据来源:马林 MLS (BAREIS),2015–2019 数据

如何使用 Python 和 Bokeh 创建交互式地理地图

原文:https://towardsdatascience.com/how-to-create-an-interactive-geographic-map-using-python-and-bokeh-12981ca0b567?source=collection_archive---------4-----------------------

使用 Choropleth 地图进行交互式数据可视化

如果你正在寻找一种强大的方法来可视化地理数据,那么你应该学会使用交互式 Choropleth 地图。Choropleth 地图通过预定地理区域(例如国家、州或县)上的各种阴影图案或符号来表示统计数据。静态 Choropleth 图对于显示数据的一个视图很有用,但是交互式 Choropleth 图更强大,并且允许用户选择他们更喜欢查看的数据。

下面的互动图表提供了旧金山独栋房屋销售的细节。该图表按中位数销售价格、最低收入要求、平均销售价格、每平方英尺平均销售价格、平均平方英尺和销售数量(10 年的数据)对单户家庭房屋销售进行了细分。

2009-2018 年旧金山独栋住宅销售互动图

如果您想了解如何开发自己的交互式地图,请跟随我一步一步地指导您完成这个过程。

关于代码的一句话

该项目的所有代码、数据和相关文件都可以在 my GitHub 访问。在 Bokeh 服务器上运行的最终 Colab 代码可以在这里找到。跳过数据清理和争论步骤的 Colab 代码的测试版本可以在这里找到。

使用 Python 和散景

在探索了几种不同的方法之后,我发现 Python 和 Bokeh 的结合是创建交互式地图的最直接、最有据可查的方法。

让我们从图表所需的安装和导入开始。Pandas、numpy 和 math 是用于清理和争论数据的标准 Python 库。geopandas、json 和 bokeh 导入是映射所需的库。

我在 Colab 工作,需要安装 fiona 和 geopandas。

!pip install fiona
!pip install geopandas

进口

*# Import libraries*
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**import** **math****import** **geopandas**
**import** **json****from** **bokeh.io** **import** output_notebook, show, output_file
**from** **bokeh.plotting** **import** figure
**from** **bokeh.models** **import** GeoJSONDataSource, LinearColorMapper, ColorBar, NumeralTickFormatter
**from** **bokeh.palettes** **import** brewer**from** **bokeh.io.doc** **import** curdoc
**from** **bokeh.models** **import** Slider, HoverTool, Select
**from** **bokeh.layouts** **import** widgetbox, row, column

数据加载、清理和争论

因为本文的重点是交互式地图的创建,所以我将简要描述用于加载、清理和争论数据的步骤。有兴趣可以在这里查看完整的清洗和角力。

由于我有房地产许可证,我可以访问旧金山 MLS,我过去常常将 10 年(2009 年至 2018 年)的单户住宅销售数据下载到 sf_data 数据框架中。

一个重要的数据,房屋面积,大约 16%的数据为零。填充数据的一个合理方法是使用旧金山所有单户家庭卧室的平均房屋面积。例如,所有价值为零的一居室房屋都用旧金山所有一居室房屋销售的平均平方英尺来填充。

数据的关键列是邻居代码,它需要匹配邻居的映射代码。这将允许我们将数据与地图合并。字典用于更改数据中的邻域代码以匹配地图中的邻域代码。

最后,将年份和每平方英尺价格列添加到 sf_data 中,并使用 groupby 和聚合函数对 sf_data 进行汇总,以创建最终的 neighborhood_data 数据帧,其中所有数值字段都转换为整数值,以便于显示数据:

neighborhood_data DataFrame

neighborhood_data 数据框显示了按街区汇总的单户住宅销售情况。现在我们需要将这些数据映射到旧金山的社区地图上。

以下是已清理数据的快捷方式:

neighborhood_data = pd.read_csv('https://raw.githubusercontent.com/JimKing100/SF_Real_Estate_Live/master/data/neighborhood_data.csv')

准备测绘数据和地理数据框架

Bokeh 提供了几种处理地理数据的方法,包括切片提供商地图、Google 地图和 GeoJSON 数据。我们将使用 GeoJSON,这是一个流行的开放标准,用于用 JSON 表示地理特征。JSON (JavaScript Object Notation)是一种最小的、可读的数据结构化格式。散景使用 JSON 在散景服务器和 web 应用程序之间传输数据。

在典型的散景交互式图形中,数据源需要是 ColumnDataSource。这是散景中的一个关键概念。但是,在使用地图时,您可以使用 GeoJSONDataSource。

为了使我们在 Python 中处理地理空间数据更容易,我们使用了 GeoPandas。它结合了 pandas 和 shapely 的功能,在 pandas 中提供地理空间操作,并为 shapely 提供多种几何图形的高级接口。我们将使用 GeoPandas 创建地理数据框架,这是创建 GeoJSONDataSource 的前奏。

最后,我们需要一张 geojson 格式的地图。旧金山,通过他们的 DataSF 网站,有一个 geojson 格式的可导出的邻居地图。

让我们通过以下代码展示如何创建地理数据框架。

*# Read the geojson map file for Realtor Neighborhoods into a GeoDataframe object*
sf = geopandas.read_file('https://raw.githubusercontent.com/JimKing100/SF_Real_Estate_Live/master/data/Realtor%20Neighborhoods.geojson')*# Set the Coordinate Referance System (crs) for projections*
*# ESPG code 4326 is also referred to as WGS84 lat-long projection*
sf.crs = {'init': 'epsg:4326'}*# Rename columns in geojson map file*
sf = sf.rename(columns={'geometry': 'geometry','nbrhood':'neighborhood_name', 'nid': 'subdist_no'}).set_geometry('geometry')*# Change neighborhood id (subdist_no) for correct code for Mount Davidson Manor and for parks*
sf.loc[sf['neighborhood_name'] == 'Mount Davidson Manor', 'subdist_no'] = '4n'
sf.loc[sf['neighborhood_name'] == 'Golden Gate Park', 'subdist_no'] = '12a'
sf.loc[sf['neighborhood_name'] == 'Presidio', 'subdist_no'] = '12b'
sf.loc[sf['neighborhood_name'] == 'Lincoln Park', 'subdist_no'] = '12c'sf.sort_values(by=['subdist_no'])

我们使用 geopandas 将 geojson 地图读入地理数据框架 sf 。然后,我们将坐标参考系统设置为经纬度投影。接下来,我们重命名几个列,并使用 set_geometry 将地理数据框设置为包含活动几何(要绘制的形状的描述)的“几何”列。最后,我们清理一些邻居 id 来匹配邻居数据

sf GeoDataFrame

我们现在在 neighborhood_data 中有我们的邻居数据,在 sf 中有我们的映射数据。请注意,它们都有共同的列 subdist_no(邻域标识符)。

为 GeoJSONDataSource 创建 JSON 数据

我们现在需要创建一个函数,将我们的邻居数据与我们的地图数据合并,并将其转换为 Bokeh 服务器的 JSON 格式。

*# Create a function the returns json_data for the year selected by the user*
**def** json_data(selectedYear):yr = selectedYear*# Pull selected year from neighborhood summary data*df_yr = neighborhood_data[neighborhood_data['year'] == yr]*# Merge the GeoDataframe object (sf) with the neighborhood summary data (neighborhood)*merged = pd.merge(sf, df_yr, on='subdist_no', how='left')*# Fill the null values*values = {'year': yr, 'sale_price_count': 0, 'sale_price_mean': 0, 'sale_price_median': 0,'sf_mean': 0, 'price_sf_mean': 0, 'min_income': 0}merged = merged.fillna(value=values)*# Bokeh uses geojson formatting, representing geographical features, with json**# Convert to json*merged_json = json.loads(merged.to_json())*# Convert to json preferred string-like object* json_data = json.dumps(merged_json)**return** json_data

我们向 json_data 函数传递我们希望加载的数据年份(例如 2018 年)。然后,我们从 neighborhood_data 中提取所选年份的数据,并将其与 sf 中的映射数据合并。在用零填充空值(没有销售的街区,比如金门公园)之后,我们使用 json.loads 和 json.dumps 将合并的文件转换成 json 格式,在 json_data 中返回 JSON 格式的数据。

互动地图主要代码

我们仍然需要几段代码来制作交互式地图,包括彩条、散景小部件和工具、绘图功能和更新功能,但在我们详细讨论这些部分之前,让我们先看看主要代码。

*# Input geojson source that contains features for plotting for:*
*# initial year 2018 and initial criteria sale_price_median*
geosource = GeoJSONDataSource(geojson = json_data(2018))
input_field = 'sale_price_median'*# Define a sequential multi-hue color palette.*
palette = brewer['Blues'][8]*# Reverse color order so that dark blue is highest obesity.*
palette = palette[::-1]*# Add hover tool*
hover = HoverTool(tooltips = [ ('Neighborhood','@neighborhood_name'),('# Sales', '@sale_price_count'),('Average Price', '$@sale_price_mean{,}'),('Median Price', '$@sale_price_median{,}'),('Average SF', '@sf_mean{,}'),('Price/SF ', '$@price_sf_mean{,}'),('Income Needed', '$@min_income{,}')])*# Call the plotting function*
p = make_plot(input_field)*# Make a slider object: slider* 
slider = Slider(title = 'Year',start = 2009, end = 2018, step = 1, value = 2018)
slider.on_change('value', update_plot)*# Make a selection object: select*
select = Select(title='Select Criteria:', value='Median Sales Price', options=['Median Sales Price', 'Minimum Income Required','Average Sales Price', 'Average Price Per Square Foot','Average Square Footage', 'Number of Sales'])
select.on_change('value', update_plot)*# Make a column layout of widgetbox(slider) and plot, and add it to the current document*
*# Display the current document*
layout = column(p, widgetbox(select), widgetbox(slider))
curdoc().add_root(layout)

让我们来分解代码:

  1. 用我们 2018 年的初始数据创建我们的 GeoJSONDataSource 对象。
  2. 定义用于颜色条和邻域映射值的调色板。
  3. 添加一个 Bokeh HoverTool,当鼠标悬停在某个邻域上时显示数据。
  4. 调用绘图函数,使用 sale_price_median 作为 initial_data(中间销售价格)来创建地图绘图。
  5. 添加一个 Bokeh Slider 小部件,使用户能够根据年份更改数据。
  6. 添加一个 Bokeh Select 小部件,使用户能够根据标准(例如,中等销售价格或最低收入要求)选择数据。
  7. 在列中布局地图地块和微件,并将结果输出到由散景服务器显示的文档中。

彩条

彩条比我想象的要更有挑战性。原来,彩条是“附加”在绘图上的,当要求更改标准时,整个绘图都需要刷新。每个标准都有自己独特的最小和最大范围、显示格式和描述。例如,“销售额”的范围为 0-100,格式为整数,名称“销售额”需要在图的标题中更改。所以我创建了一个 format_df ,它详细描述了颜色栏和标题中需要的数据。

# This dictionary contains the formatting for the data in the plots
format_data = [('sale_price_count', 0, 100,'0,0', 'Number of Sales'),('sale_price_mean', 500000, 4000000,'$0,0', 'Average Sales Price'),('sale_price_median', 500000, 4000000, '$0,0', 'Median Sales Price'),('sf_mean', 500, 5000,'0,0', 'Average Square Footage'),('price_sf_mean', 0, 2000,'$0,0', 'Average Price Per Square Foot'),('min_income', 50000, 600000,'$0,0', 'Minimum Income Required')]#Create a DataFrame object from the dictionary 
format_df = pd.DataFrame(format_data, columns = ['field' , 'min_range', 'max_range' , 'format', 'verbage'])

format_df DataFrame

悬浮工具

HoverTool 是一个相当简单的散景工具,允许用户将鼠标悬停在某个项目上并显示值。在主代码中,我们插入 HoverTool 代码,告诉它使用基于 neighborhood_name 的数据,并显示六个标准,使用“@”来表示列值。

*# Add hover tool*
hover = HoverTool(tooltips = [ ('Neighborhood','@neighborhood_name'),('# Sales', '@sale_price_count'),('Average Price', '$@sale_price_mean{,}'),('Median Price', '$@sale_price_median{,}'),('Average SF', '@sf_mean{,}'),('Price/SF ', '$@price_sf_mean{,}'),('Income Needed', '$@min_income{,}')])

Widgets 和回调函数

我们使用两个散景部件,滑块对象和选择对象。在我们的示例中,Slider 对象允许用户选择要显示的年份(或行), select 对象允许用户选择标准(或列)。

这两个小部件的工作原理相同——回调。在下面的代码中,小部件传递一个“值”并调用一个名为 update_plot 的函数。调用 on_change 方法(当使用小部件(事件处理程序)进行更改时)。

*# Make a slider object: slider* 
slider = Slider(title = 'Year',start = 2009, end = 2018, step = 1, value = 2018)
slider.on_change('value', update_plot)*# Make a selection object: select*
select = Select(title='Select Criteria:', value='Median Sales Price', options=['Median Sales Price', 'Minimum Income Required','Average Sales Price', 'Average Price Per Square Foot','Average Square Footage', 'Number of Sales'])
select.on_change('value', update_plot)

回调函数 update_plot 有三个参数。attr 参数只是您传递的“值”(例如 slider.value 或 select.value),新旧参数是散景使用的内部参数,您不需要处理它们。

根据所使用的小部件,我们或者基于年份(yr)选择 new_data (Slider ),或者基于条件(cr)重新设置 input_field (Select)。然后,我们根据当前的 input_field 重新设置绘图。

最后,我们布局图和小部件,清除旧文档并输出包含新数据的新文档。

*# Define the callback function: update_plot*
**def** update_plot(attr, old, new):*# The input yr is the year selected from the slider*yr = slider.valuenew_data = json_data(yr)*# The input cr is the criteria selected from the select box*cr = select.valueinput_field = format_df.loc[format_df['verbage'] == cr, 'field'].iloc[0]*# Update the plot based on the changed inputs*p = make_plot(input_field)*# Update the layout, clear the old document and display the new document*layout = column(p, widgetbox(select), widgetbox(slider))curdoc().clear()curdoc().add_root(layout)*# Update the data*geosource.geojson = new_data

创建绘图功能

地图的最后一部分是 make_plot,绘图函数。让我们来分解一下:

  1. 我们将 field_name 传递给它,以指示我们要绘制哪一列数据(例如,销售价格中值)。
  2. 使用 format_df,我们为颜色条提取最小范围、最大范围和格式。
  3. 我们调用 Bokeh 的 LinearColorMapper 来设置调色板和颜色条的范围。
  4. 我们使用 Bokeh 的 NumeralTickFormatter 和 ColorBar 创建了 ColorBar。
  5. 我们创建具有适当标题的绘图图形。
  6. 我们使用 Bokeh 的 p.patches 字形和 geosource 中的数据创建“面片”,在我们的例子中是邻域多边形。
  7. 我们将 colorbar 和 HoverTool 添加到绘图中,并返回绘图 p。
*# Create a plotting function*
**def** make_plot(field_name):    *# Set the format of the colorbar*min_range = format_df.loc[format_df['field'] == field_name, 'min_range'].iloc[0]max_range = format_df.loc[format_df['field'] == field_name, 'max_range'].iloc[0]field_format = format_df.loc[format_df['field'] == field_name, 'format'].iloc[0]*# Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.*color_mapper = LinearColorMapper(palette = palette, low = min_range, high = max_range)*# Create color bar.*format_tick = NumeralTickFormatter(format=field_format)color_bar = ColorBar(color_mapper=color_mapper, label_standoff=18, formatter=format_tick,border_line_color=**None**, location = (0, 0))*# Create figure object.*verbage = format_df.loc[format_df['field'] == field_name, 'verbage'].iloc[0]p = figure(title = verbage + ' by Neighborhood for Single Family Homes in SF by Year - 2009 to 2018', plot_height = 650, plot_width = 850,toolbar_location = **None**)p.xgrid.grid_line_color = **None**p.ygrid.grid_line_color = **None**p.axis.visible = **False***# Add patch renderer to figure.* p.patches('xs','ys', source = geosource, fill_color = {'field' : field_name, 'transform' : color_mapper},line_color = 'black', line_width = 0.25, fill_alpha = 1)*# Specify color bar layout.*p.add_layout(color_bar, 'right')*# Add the hover tool to the graph*p.add_tools(hover)**return** p

将所有这些放在一起

测试代码将所有这些放在一起,用 Colab 笔记本中的 ColorBar 和 HoverTool 打印出一个静态地图。为了使用滑块和选择来查看交互式组件,您需要在接下来的步骤中使用散景服务器。(您将需要 fiona 和 geopandas 导入来运行下面的代码)

带彩条和悬浮工具的静态地图

散景服务器

我使用 2018 年的数据和 Colab 中的中值销售价格开发了静态地图,以便在添加互动部分之前让大部分代码工作。为了测试和查看散景的交互式组件,您需要遵循以下步骤。

  1. 在电脑上安装散景服务器。
  2. 下载。ipynb 文件复制到计算机上的本地目录中。
  3. 从终端将目录更改为带有。ipynb 文件。
  4. 从终端运行以下命令:bokeh serve(两个破折号)show filename.ipynb
  5. 这将在您的浏览器上打开一个本地主机,并输出您的交互式图形。如果有错误,应该可以在终端中看到。

公众通过 Heroku 进入互动图表

一旦你让交互式图形在本地工作,你就可以让其他人通过使用一个公共的散景托管服务(比如 Heroku)来访问它。Heroku 将托管交互式图形,允许您链接到它(如本文中所示)或使用 iframe,如在我的 GitHub Pages 站点上。

在 Heroku 上托管的基本步骤是:

  1. 更改 Colab 笔记本,注释掉 fiona 和 geopandas 的安装。Heroku 拥有这些项目,如果它们出现在代码中,构建将会失败。
  2. 更改 Colab 笔记本,注释掉最后两行(output_notebook()和 show(p))。
  3. 将 Colab 笔记本下载为. py 文件,并上传到 GitHub 存储库。
  4. 创建一个 Heroku 应用程序并连接到包含您的。py 文件。
  5. 创建一个 Procfile 和 requirements.txt 文件。在我的 GitHub 里看到我的。
  6. 运行应用程序!

我欢迎建设性的批评和反馈,请随时给我发私信。

在推特上关注我

这篇文章最初出现在我的 GitHub Pages 网站上,交互图也可以在走向数据科学文章旧金山理工就业?先查房价!

如何创建获奖的数据可视化

原文:https://towardsdatascience.com/how-to-create-award-winning-data-visualizations-518127fc30ef?source=collection_archive---------3-----------------------

如何创建出色的数据可视化的分步指南。让您的数据脱颖而出的技巧和想法!

Chart from award-winning kernel from Kaggle competition. Let’s learn how to create it from scratch!

本周早些时候,我带着我的笔记本在 Kaggle 的机器学习和数据科学调查竞赛中获得了三等奖(6000 美元)【外面有工作吗?Kaggle vs 玻璃门。

虽然竞赛评估了我作品的几个方面,但我认为我展示信息的方式是获奖的关键。在这里,我想分享一点构建数据可视化背后的思考过程,一步一步地说明。

要绘制的数据

我的想法是衡量不同国家有多少人在不同的岗位(职称)上工作。

Data that I want to plot!

第一个情节

我选择使用 Plotly 主要是因为我已经习惯了它,也因为我喜欢它提供的开箱即用的交互性。然而,我所应用的概念,以及我将要演示的概念,可以用于任何其他图形库或软件,与语言无关。

First attempt to plot data

First attempt to plot data by country

选择更好的绘图类型

我对这个可视化的条形图不满意。我想显示相同的信息,但允许比较不同的国家。为各个国家添加多个条形图看起来一点也不好。然后我试了一个折线图,因为添加多条线比多列效果更好。

Choosing a Line Plot

好多了…现在让我们尝试添加国家,而不是所有国家的总和。

Trying a line plot per country.

比栅栏看起来好多了。但还是不对。我的下一个想法是把 x 轴转换成径向。

Radial plot by country

这看起来很有趣!我想我可以继续使用这种图表类型。

将要绘制的数据从绝对数据更改为相对数据

一些国家比其他国家有更多的绝对行。这在图表中造成了失真,因此我将改变指标,绘制每个国家每个职位的相对百分比。它应该允许我们比较它们!

Plotting relative values (percentages)

确实!现在所有国家的规模都一样。按比例比较比绝对值比较好得多。

关闭线路

这有点棘手。要在 Plotly 上“关闭”雷达图,您需要将第一个数据点再次添加到末尾。

Radar chart, with all lines closed

在轴标题中创建层次结构

如果你看看轴,他们目前没有一个层次或任何特定的顺序。我想通过从最不专业到最专业的相似的职位名称来创建一个。对我来说,按照以下顺序组织是有意义的:

商业分析师< Data Analyst < Data Scientist < Data Engineer/DBA < Software Engineer < Statistician/Research Scientist

Adding a hierarchy to the axis

Decluttering

This is the most important part of any good data visualization. Remove any noise that is not directly contributing to how people are reading and interpreting data.

Turning background to white

Now that the background is white, we also need to change some other elements, such as grids, ticks and lines. Here my choices were:

  • Turn all text and chart elements to a light grey
  • Hide any chart grid and axis lines that are not essential. I only kept radial axis grid (the circles), because they are important for readers to understand the magnitude of the values displayed.

Declutter background

It looks much better now, doesn’t it?

Smoothing all lines, and making them grey and thinner

Now we will transform all lines to grey, reduce their width and also make them less sharp by applying some smoothing.

Bringing lines to background

This is 好多了!因为现在我们实际上可以“看到”每一行了!但正如他们所说,细节决定成败。让我们继续改进它吧!

删除图例,调整网格和范围

  • 现在,我认为有太多的网格线(0,10,20,…,50)塞满了图表。我不喜欢它,相反,我将只创建三行(25%和 50%)。
  • 我也不喜欢为一个传奇人物设定那么多的值,它们除了让我们的形象变得更糟之外,没有任何帮助。让我们把它藏起来!
  • 有一行几乎超过了数据科学家轴标题,我将稍微增加一点范围以避免这种情况。

Hiding legends and adjusting grid

调整悬停信息

Hover does not look good

当我们将鼠标悬停在数据点上时,我们会看到 rθ值。这对于查看图表的任何人来说都没有信息。让我们在那里调整一些事情。

  • 添加国家名称(这样无需多种颜色或图例,就可以轻松将该系列与国家联系起来)
  • 添加数据点(这样很容易将每个数据点的值与每一行相关联)
  • 将数据点格式化为不带小数点的百分比(不需要任何小数点,因为分析更加定性)

After adjusting hover information

讲故事

现在,我们将重点介绍一些我们想讲述的特定国家。在这张图表中,我选择美国对中国。我们将做什么:

  • 为突出显示的国家/地区线条增添色彩
  • 从国旗颜色中选择颜色(红色代表中国,蓝色代表美国)
  • 增加突出显示的国家线的宽度
  • 增加突出显示的国家线的不透明度
  • 仅对突出显示的国家显示图例

Highlighting data to tell a story

现在我们用这些数据来讲述一些故事!我们能够看到中国和美国之间的差异!从这张图表中我们可以很容易地得出一些结论!

添加有意义的标题

现在,我们将向图表添加一个有意义的标题和数据源。

  • 标题字体更大
  • 源的较小字体
  • 两者都是灰色的,不会引起太多注意

Adding title and source

将所有要素更紧密地联系在一起

使用 Plotly 的标准自动调整大小会导致所有元素彼此之间的间隔过大,让我们通过定义图表的高度和宽度大小来拉近它们。

另外对图例也做了一些小的调整:

  • 将颜色更改为灰色
  • 单击并双击时更改行为

Legend is now grey, all elements are more close together

为什么它是好的?

这个图表很容易让我们比较两个不同的国家。同时,它还保留了未被纳入相关报道的所有其他国家的数据,从而为报道提供了更多的背景信息。

读者的注意力会被吸引到数据本身,而不是其他图表元素。故事/比较突出显示且清晰,标题与故事相关。这个图表只讲述了一个故事。

颜色是明智的选择,也有意义(国旗颜色)。所有其他不属于故事的元素都以灰色背景。

这个消息来源被清楚地引用,并没有引起太多的关注。

关于如何进行出色的数据讲述的更多提示

保持所有图表相似

显示多个图表时,请坚持使用几种不同的图表类型。这样做的目的是让读者的生活更轻松,因为他们不需要学习如何阅读每一个新图表——在学习如何解释一个图表之后,阅读所有其他图表将是自动的。

在每个图表中坚持使用几种颜色

如果你突出显示的数据颜色没有任何意义(不像这个例子,他们对国旗的颜色进行编码),那么你就不应该使用很多不同的颜色。尽量减少。

每个图表只讲一个故事

在一张图表中突出多种事物可能很有诱惑力。相反,创建各种图表来突出不同的东西,每个图表一个独特的故事。

请参阅构建这些图表的完整代码

查看笔记本,其中包含用于创建此逐步指南的所有代码和数据。

如何使用 R 和 dygraph 创建更好的交互式预测图

原文:https://towardsdatascience.com/how-to-create-better-interactive-forecast-plots-using-r-and-dygraph-29bdd7146066?source=collection_archive---------19-----------------------

如果你对 R 和时间序列感兴趣,你一定会偶然发现罗伯·海曼的伟大的预测包。除了用于分析时间序列的各种工具和方法之外,它还扩展了 ggplot 以使用 autoplot 可视化预测对象。虽然这几乎不用代码就能产生很好的结果,但它不提供交互功能。在本文中,您将了解到…

  • 如何使用交互式功能(如缩放、平移和鼠标悬停信息)绘制预测
  • 如何在绘图中包含 80%和 95%的区间预测
  • 如何编写 JavaScript 格式化程序来调整图例

这是结果的样子…

对预测对象使用自动批次

让我们先看看预测对象的基本自动绘图功能的结果。在经典的航空公司数据集上创建一个 3 年预测,并绘制出结果,只需要三行代码。

code that forecasts and plots the air passenger time series

autoplot of a forecast object

你可以看到黑色的实际时间序列和蓝色的预测。预测区间(80%和 95%)也显示为蓝色区域。虽然这对于三行代码来说无疑是一个好结果,但是可以通过交互特性来改善这个结果。

将 dygraph 用于预测对象

JavaScript 库 dygraph 可以创建交互式绘图,R 的这个库的接口也可以通过dy graph 包获得。

将上面的例子转换成使用 dygraph 只是增加了一行来绑定来自 forecast 对象的时间序列。

simple dygraph for a forecast object

basic dygraph showing actuals and point forecast

现在,虽然我们获得了 dygraph 的交互特性,但突然之间预测区间丢失了。在 dygraph 中,可以用所谓的误差线来绘制时间序列,以解决这个问题。由于 dygraph 只支持每个时间序列一个误差线,我们只是简单地为每个时间间隔添加一个时间序列。

adding error bars for the interval forecasts

dygraph showing actuals, point and interval forecasts

那看起来相当好,但是有一点东西不见了。如果将鼠标悬停在图表上,您将只能看到图例中的点预测值(上图中的 569.93),而看不到相应的区间。

为预测间隔编写自定义格式化程序

使用dyAxis函数的valueFormatter参数,自定义 JavaScript 函数可以覆盖 dygraph 图例中值的格式。对于每个时间序列,将在鼠标悬停时调用 JavaScript 函数,该函数将接受六个参数:

  • num:当前时间序列鼠标悬停位置的值
  • opts:当前动态图的选项值
  • seriesName:当前时间序列的名称
  • g:实际的 dygraph 对象
  • row:鼠标当前所在位置的原始数据的行索引
  • col:当前时间序列的原始数据列索引

将传递给函数的值num不包括间隔值。但是,给定行和列索引的值可以从 dygraph 对象(函数getValue)中获得,并且将包含这个预测间隔。然后,我们可以根据自己的喜好对其进行格式化。重用内置的Dygraph.numberValueFormatter函数来格式化和传递选项值将保持对选项的支持,例如控制要显示的位数(参见dyOptions中的选项digitsAfterDecimal)。

请注意,dygraph 返回的值将是一个长度为 3 的向量,即使对于像实际时间序列这样只有一个值的时间序列也是如此。因此,在格式化为一个区间之前,我添加了检查上限值和下限值是否实际不同。

custom JavaScript for formatting values in the legend

此外,我对图表进行了一些额外的调整:

  • 点预测的专用时间序列,用于将间隔预测与图例中的点预测分开
  • 使用dyLegend函数中的选项labelsSeparateLines将每个标签放在一个单独的行上,这使得结果更具可读性
  • dyRangeSelector函数在图的底部放置了一个漂亮的选择器
  • 使用选项digitsAfterDecimal将位数减少到一位
  • 一个小的 CSS 保持图例半透明,以避免覆盖图形

final code using dygraph for plotting forecast objects plot

dygraph showing actuals, point and interval forecasts and custom legend

感谢您的阅读!

如何使用 jupyter 笔记本、reveal.js、github 上的主机创建数据驱动的演示文稿,并向世界展示:第一部分—制作基本的幻灯片

原文:https://towardsdatascience.com/how-to-create-data-driven-presentations-with-jupyter-notebooks-reveal-js-e7a42a1fb7d7?source=collection_archive---------12-----------------------

…其中我讨论了一个工作流程,您可以开始在 jupyter 笔记本上写内容,创建 reveal.js 幻灯片,并将其放在 github 上进行演示。这是一个非常简单的演示,你可以完全控制自己

A first simple slide deck

第一部分:基本幻灯片组
第二部分:使用备注的基本幻灯片组
第三部分:高级技术

逐步地

建立 github repo 并添加子模块

第一步 。首先创建一个 github 存储库来存放您的幻灯片。要做到这一点,请访问https://www.github.com并启动一个存储库,您还需要安装 git。我在 Vultr 上使用了一个托管实例,它附带了一个预装的 git。如果您使用 Windows、Mac 或 Linux,您可能希望安装 git,或者在您的终端中检查您已经安装了 git,方法是发出如下命令:

git --version

Click on the + sign to add a repository

第二步 。添加存储库。例如,我创建了一个名为 myJupyterSlides 的存储库,请看下面的截图:

Created an empty repository to host jupyter notebook based slides

第三步 。(仍然使用 web 界面)最好在主分支中创建一个 index.md 文件,并说明您将在此存储库中保存您的幻灯片。为此,您也可以使用“README.md”。现在让我们创建一个文件。下面您可以看到文件是这样创建的:

In step 3 create a new file labelled as index.md

第四步 。(仍然使用 web 界面),使用 web 界面,创建一个名为 gh-pages 的新“分支”(参见下面的截图,了解如何创建 gh-pages 分支)

Create gh-pages branch

一旦你创建了 gh-pages 分支,github 会自动为你创建一个网站。如果你在你的 github 储存库(“github repo”)上点击“设置”,就会显示你的站点已经发布。例如,如果下面的屏幕截图显示了我的站点在 github repo 中的发布位置:

Your site is published!

如果我点击这个链接,它会显示一个简单的网页。

您现在已经建立了一个发布幻灯片的网站。在接下来的步骤中,我们将使用 git repo 为我们的计算机(可以是本地计算机、实例或虚拟机)创建一个文件夹,我们将在其中构建幻灯片所需的文件。以下是步骤:

第五步 。现在,在您的终端上,“克隆”git repo。首先,做一个目录(或者文件夹)。比如我做了一个名为“jupyterslides”的目录。我从当前目录切换到此目录(1)。然后初始化 git 文件夹(2)。之后,将 github repo 作为子文件夹添加到这个文件夹中(3)。您将看到添加了一个文件夹,其名称与您的 github repo 名称相同。

~$ cd jupyterslides (1)
~$ git init (2)
~$ git submodule add <your github https repo address> (3)

启动 Jupyter 笔记本/Jupyter 实验室并添加内容

第六步 。现在您已经设置了 github repo,并且已经将该 repo 作为子模块添加到您的计算机或实例中,让我们开始构建幻灯片的内容。当您完成本教程时,您将从 Jupyter 笔记本中构建一个简单的演示文稿,并在 web 上显示。稍后,您将看到您可以为该演示文稿构建交互性以及更多高级功能。与 Keynote、Powerpoint 或 OpenOffice/LibreOffice Impress 不同,您将不会使用任何基于点击的系统来构建此类内容;相反,您将使用纯文本工具来构建演示文稿。因此,

  • 第一步是开发 Jupyter 笔记本中的内容。
  • 第二步是以编程方式将该笔记本转换为降价文档
  • 第三步是使用' pandoc '(一种通用文档转换器,也称为文档转换的瑞士军刀)将文档转换为一组幻灯片
  • 第四步是将内容“推送”到 github repo,以便在互联网上显示

第七步 :在 Jupyter 笔记本中创建内容。—对于本教程,让我们创建一个包含五张幻灯片的演示文稿(这是为了演示),其中包含:

  • 标题幻灯片(我们稍后将添加标题幻灯片)
  • 包含项目符号的幻灯片
  • 包含图像的幻灯片
  • 包含链接的幻灯片
  • 包含表格的幻灯片

稍后我将向您展示,您可以使用这四个元素(项目符号、图像、链接和表格)来创建不同类型的演示。我还将向您展示如何为这些元素添加交互性。你可以使用 markdown 或用 R、Python 或 Julia(实际上还有许多其他语言)编写的代码在 Jupyter 笔记本上创建图像和表格。因此,现在是讨论四个相关问题的好时机:如何在 markdown 中创作内容,什么是 reveal.js 以及我们为什么使用它(还有其他问题),以及幻灯片制作指南。

如何在 markdown 中创作内容

Markdown 是一个内容创作系统,设计用于在 web 上编写结构化文档。文档中的以下元素构成了 markdown 语法:

The following is an example of a table written in Markdown and will be rendered as a table in github flavoured markdown| Element of text    | Equivalent Markdown syntax        |
|--------------------|-----------------------------------|
| Heading levels     | Usually with ##                   |
| First level header | # Example of a first level header |
| Second level header| ## Second level header            |
| Paragraphs         | Text separated by two line spaces |
| Unnumbered list    | * this is an element              |
| Numbered list      | 1\. This is the first element      |
| Tables             | This is a markdown table          |
| Formula            | $\formula$                        |
| Images             | ![image alt](image URL)           |
| Hyperlinks         | [Link text](URL to be linked)     |
| References         | [@bibtex_entry_ID]                |
| Codes              | backticks (`code goes here`)      |
| Italic             | *text to be italicised*           |
| Bold               | **text to be in bold font**       |
| Underline          | _text to be underlined_           |
| Blockquote         | > Text to be blockquoted          |

在上面的代码块中,我已经为您提供了一个常用的降价惯例列表。关于 github 风味减价的更长列表和备忘单,参见以下链接

[## 亚当-p/markdown-这里

Google Chrome、Firefox 和 Thunderbird 扩展,可以让你用 Markdown 编写电子邮件,并在发送前呈现。…

github.com](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)

在 Jupyter 笔记本中,您可以在 markdown 中创作文档。Jupyter 笔记本使用 github flavoured markdown,这也是我们将使用的。此外,如果您想使用参考文献和引文,并且如果您想将文档转换为包含引文和参考文献列表的其他格式,我建议您使用 pandoc 将文档从 markdown 格式转换为所需格式。您可以在此了解更多关于 pandoc 以及如何使用 pandoc 传输文档的信息。以下 youtube 视频为您提供了更多关于 pandoc 的信息:

How to use pandoc, a video you can use to learn more about pandoc

我们将在本文档的单独一节中讲述如何使用 pandoc 创建幻灯片。现在,我们将使用 markdown 来编写幻灯片。我们将使用 next reveal.js 来设计我们的幻灯片。

什么是 reveal.js,为什么你会使用它

将 reveal.js 视为一个工具,您将使用它来呈现您创建的幻灯片。Revealjs 由三个元素组成:

  • CSS(呈现文档外观的级联样式表)
  • javascript 引擎(呈现幻灯片),以及
  • 您将创建的 HTML5 文档将显示为幻灯片

考虑您将展示的包含在<section> and \<section>元素中的每张“幻灯片”。所以,事情是这样的:

<html>
CSS statements
<section>
Your slide data will go here ...</section>
<javacript file>
</html>

这是基本结构。还有其他工具和框架,请查看。在本教程中,我们将介绍 revealjs,在后续教程中,我将介绍其中的几个。一些常见和流行的框架是:

  • Impress.js
  • Shower.js
  • Deck.js
  • Remarkjs (我们将在下一个教程中介绍这一点)

我将在随后的帖子中涉及这些,所以这是我们将重点关注 revealjs 的一个帖子。

要让 revealjs 正常运行,您需要做些什么

第八步 。从他们的 github repo 中获取一份 reveal.js 的副本,并在 Jupyter 笔记本的终端中使用 wget 命令,如下所示:

~$ cd myjupyterslides (1)
~$ wget [https://github.com/hakimel/reveal.js/archive/master.zip](https://github.com/hakimel/reveal.js/archive/master.zip) (2)
~$ unzip master.zip (3)
# this will create a folder named 'reveal.js-master'
# rename the folder to 'revealjs' with:
~$ mv reveal.js-master revealjs (4)

对上述代码块的解释:

  1. 光盘 myjupyterslides (1)。—您将更改目录以进入 myjupyterslides,其中 myjupyterslides 是您之前创建的 github 存储库,因此当您添加 git 子模块时,它将作为文件夹添加到您当前的目录中
  2. wget (2) wget 是一个帮助您下载 web 内容的实用程序,在这里是 revealjs 存储库的主分支
  3. unzip master.zip (3)是不言自明的,它将解压文件并在当前目录中添加一个文件夹“reveal.js-master”
  4. mv reveal.js-master revealjs 是一种“重命名”文件夹的方法,所以现在你的文件夹被重命名为 revaljs。

在这一步的最后,您将使用 revealjs 创建幻灯片的本地副本。但是在我们开始整理内容之前,让我们学习一些关于创建幻灯片和数据可视化的良好实践。这是我将在本系列的后续文章中讨论的内容的高度浓缩版本,但将服务于本教程的目的。

关于创建幻灯片和数据可视化的说明

关于创建幻灯片和数据可视化的一些事情是有序的。

首先,牢记数据墨水五定律从爱德华·塔夫特,

  1. 最重要的是,展示数据
  2. 最大化数据油墨比率(每个油墨流更多数据)
  3. 擦除非数据墨迹
  4. 擦除多余的数据墨迹
  5. 修订和编辑

有关上述概念的更详细解释,请查阅以下资料:

[## 最大化仪表板和幻灯片中的数据-墨迹比率

“最重要的是,展示数据。”

medium.com](https://medium.com/plotly/maximizing-the-data-ink-ratio-in-dashboards-and-slide-deck-7887f7c1fab)

其他一些技巧包括:

  • 编一个有开头、中间和结尾的故事
  • 使用故事板来发展你的想法(参见 Garr Reynolds 和 Cliff Atkinson 的作品)

如何使用 Jupyter 笔记本从数据中绘制图表、曲线图和表格

让我们在 jupyter 笔记本中创建一个简单的五张幻灯片演示文稿。语法很简单,我们将创建如下的东西(你可以通过访问这个链接看到它看起来像一个 jupyter 笔记本)

## This is the first slide (1)
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a tablelibrary(tidyverse) (2)mtcars1 <- mtcars %>% (3)head() 
mtcars1 # produces the first five rows in the form of a tablemtcars %>% (4)ggplot(aes(x = disp, y = mpg)) +geom_point() +geom_smooth(method = "loess", colour = "blue", se = FALSE) +geom_smooth(method = "lm", colour = "red", se = FALSE) +labs(x = "Engine size",y = "Miles per gallon",title = "Relationship between engine size and milage for cars") +theme_bw() +theme(panel.grid.major = element_blank(),panel.grid.minor = element_blank()) +ggsave("test5.png")

上述代码的解释:

(1)这是记录在降价模块中的第一张幻灯片。你可以移动这些块,这样你就可以在 Jupyter
中构建一个故事板(2)这是在代码窗口中编写的,并调用 R
中的 tidyverse 库(3) mtcars1 是从 mtcars 创建的数据子集,这是一个关于汽车的大型数据集;我们将使用它来演示以编程方式创建表格
(4)我们使用此代码以编程方式生成一个图

第九步 。在我们使用 jupyter notebook 和在 jupyter notebook 中使用 R 生成这些图形和表格之后,我们将这个 Jupyter notebook 导出到 markdown 文档中。我们可以使用 jupyter notebook 本身来创建一组 reveal.js 幻灯片,但是首先导出到 markdown 会让您对幻灯片创建元素的某些方面有更多的控制。使用以下代码将 jupyter 笔记本转换为 markdown 文档:

~$ jupyter nbconvert -t markdown mynotebook.ipynb (1)
# generates mynotebook.md (2)

解释:

(1) mynotebook.ipynb 是我要转换的 jupyter 笔记本的名称
(2)这将生成 mynotebook.md markdown 文档

现在我们的减价文件看起来如下:

## This is the first slide
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a table```R
library(tidyverse)
```── [1mAttaching packages[22m ─────────────────────────────────────── tidyverse 1.2.1 ──[32m✔[39m [34mggplot2[39m 3.1.1     [32m✔[39m [34mpurrr  [39m 0.3.2[32m✔[39m [34mtibble [39m 2.1.3     [32m✔[39m [34mdplyr  [39m 0.8.1[32m✔[39m [34mtidyr  [39m 0.8.3     [32m✔[39m [34mstringr[39m 1.4.0[32m✔[39m [34mreadr  [39m 1.3.1     [32m✔[39m [34mforcats[39m 0.4.0── [1mConflicts[22m ────────────────────────────────────────── tidyverse_conflicts() ──[31m✖[39m [34mdplyr[39m::[32mfilter()[39m masks [34mstats[39m::filter()[31m✖[39m [34mdplyr[39m::[32mlag()[39m    masks [34mstats[39m::lag()```R
mtcars1 <- mtcars %>%head() 
mtcars1 # produces the first five rows in the form of a table
```<table>
<caption>A data.frame: 6 × 11</caption>
<thead><tr><th></th><th scope=col>mpg</th><th scope=col>cyl</th><th scope=col>disp</th><th scope=col>hp</th><th scope=col>drat</th><th scope=col>wt</th><th scope=col>qsec</th><th scope=col>vs</th><th scope=col>am</th><th scope=col>gear</th><th scope=col>carb</th></tr><tr><th></th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th></tr>
</thead>
<tbody><tr><th scope=row>Mazda RX4</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.620</td><td>16.46</td><td>0</td><td>1</td><td>4</td><td>4</td></tr><tr><th scope=row>Mazda RX4 Wag</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.875</td><td>17.02</td><td>0</td><td>1</td><td>4</td><td>4</td></tr><tr><th scope=row>Datsun 710</th><td>22.8</td><td>4</td><td>108</td><td> 93</td><td>3.85</td><td>2.320</td><td>18.61</td><td>1</td><td>1</td><td>4</td><td>1</td></tr><tr><th scope=row>Hornet 4 Drive</th><td>21.4</td><td>6</td><td>258</td><td>110</td><td>3.08</td><td>3.215</td><td>19.44</td><td>1</td><td>0</td><td>3</td><td>1</td></tr><tr><th scope=row>Hornet Sportabout</th><td>18.7</td><td>8</td><td>360</td><td>175</td><td>3.15</td><td>3.440</td><td>17.02</td><td>0</td><td>0</td><td>3</td><td>2</td></tr><tr><th scope=row>Valiant</th><td>18.1</td><td>6</td><td>225</td><td>105</td><td>2.76</td><td>3.460</td><td>20.22</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
</tbody>
</table>```R
mtcars %>%ggplot(aes(x = disp, y = mpg)) +geom_point() +geom_smooth(method = "loess", colour = "blue", se = FALSE) +geom_smooth(method = "lm", colour = "red", se = FALSE) +labs(x = "Engine size",y = "Miles per gallon",title = "Relationship between engine size and milage for cars") +theme_bw() +theme(panel.grid.major = element_blank(),panel.grid.minor = element_blank()) +ggsave("test5.png")
```Saving 6.67 x 6.67 in image![png](test5_files/test5_3_1.png)```R```

第十步。 我们将使用以下两个文档中的提示和原则来编写本文档,并使其“值得滑动”:

  • Reveal.js 文档(参见 https://github.com/hakimel/reveal.js#markdown):从这个文档中,这几行对我们很有用:
It's possible to write your slides using Markdown. To enable Markdown, add the data-markdown attribute to your <section>elements and wrap the contents in a <textarea data-template> like the example below. You'll also need to add the plugin/markdown/marked.js and plugin/markdown/markdown.js scripts (in that order) to your HTML file.<section data-markdown><textarea data-template>## Page titleA paragraph with some text and a [link](http://hakim.se).</textarea>
</section>

我们会看到潘多克会为我们做到这一点。但是文件还在继续,

Special syntax (through HTML comments) is available for adding attributes to Markdown elements. This is useful for fragments, amongst other things.<section data-markdown><script type="text/template">- Item 1 <!-- .element: class="fragment" data-fragment-index="2" -->- Item 2 <!-- .element: class="fragment" data-fragment-index="1" --></script>
</section>

这部分需要解释一下。在这里,revealjs 开发人员将您的注意力引向您决定包含在幻灯片中的“降价元素”,并给出了一个列表元素的示例。还有其他元素(注意上面的列表)。你可以用这些类定义来控制每一个元素。但接下来会有一些关于幻灯片组中所有幻灯片行为的问题。这是他们谈论控制元素的地方,比如改变背景颜色,添加一个背景图片而不是一个有标题的图片,等等。以下是相关文档:

Slide AttributesSpecial syntax (through HTML comments) is available for adding attributes to the slide <section> elements generated by your Markdown.<section data-markdown><script type="text/template"><!-- .slide: data-background="#ff0000" -->Markdown content</script>
</section>

我们将在本系列的后面部分利用这些信息来生成具有交互性的漂亮幻灯片。现在,我们会让 Pandoc 产生它能产生的东西。以下是 pandoc 文档中的更多信息:

  • 关于创建幻灯片组的 Pandoc 文档(参见https://pandoc . org/manual . html # producing-slide-shows-with-pandoc)

从 pandoc 文档中,请注意:

By default, the *slide level* is the highest heading level in the hierarchy that is followed immediately by content, and not another heading, somewhere in the document. In the example above, level-1 headings are always followed by level-2 headings, which are followed by content, so the slide level is 2\. This default can be overridden using the [--slide-level](https://pandoc.org/MANUAL.html#option--slide-level) option.The document is carved up into slides according to the following rules:
* A horizontal rule always starts a new slide.
* A heading at the slide level always starts a new slide.
* Headings *below* the slide level in the hierarchy create headings *within* a slide.
* Headings *above* the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
* Headings *above* the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
* A title page is constructed automatically from the document’s title block, if present. (In the case of beamer, this can be disabled by commenting out some lines in the default template.)

遵循这些规则,就有可能构建一系列幻灯片,这些幻灯片可以根据我们的大多数需求进行修改。在本教程中,我们将创建一组简单的幻灯片,因此我们不会深入研究不同的选项。在随后的文章中,我们将探索多种方式来“调整”幻灯片的外观,并为幻灯片添加交互性。

这里,简而言之,至少:

  • 我们将添加一个标题页
  • 我们将插入一些滑动分隔器
  • 我们将删除代码块

在这些更改完成后,最终的 markdown 文档如下所示:

--- (1)
title: A first simple slide deck
author: Me Myself
date: 9th August, 2019
---## This is the first slide (2)
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a table---------- (3)
<table>
<caption>A data.frame: 6 × 11</caption>
<thead><tr><th></th><th scope=col>mpg</th><th scope=col>cyl</th><th scope=col>disp</th><th scope=col>hp</th><th scope=col>drat</th><th scope=col>wt</th><th scope=col>qsec</th><th scope=col>vs</th><th scope=col>am</th><th scope=col>gear</th><th scope=col>carb</th></tr><tr><th></th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th><th scope=col>&lt;dbl&gt;</th></tr>
</thead>
<tbody><tr><th scope=row>Mazda RX4</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.620</td><td>16.46</td><td>0</td><td>1</td><td>4</td><td>4</td></tr><tr><th scope=row>Mazda RX4 Wag</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.875</td><td>17.02</td><td>0</td><td>1</td><td>4</td><td>4</td></tr><tr><th scope=row>Datsun 710</th><td>22.8</td><td>4</td><td>108</td><td> 93</td><td>3.85</td><td>2.320</td><td>18.61</td><td>1</td><td>1</td><td>4</td><td>1</td></tr><tr><th scope=row>Hornet 4 Drive</th><td>21.4</td><td>6</td><td>258</td><td>110</td><td>3.08</td><td>3.215</td><td>19.44</td><td>1</td><td>0</td><td>3</td><td>1</td></tr><tr><th scope=row>Hornet Sportabout</th><td>18.7</td><td>8</td><td>360</td><td>175</td><td>3.15</td><td>3.440</td><td>17.02</td><td>0</td><td>0</td><td>3</td><td>2</td></tr><tr><th scope=row>Valiant</th><td>18.1</td><td>6</td><td>225</td><td>105</td><td>2.76</td><td>3.460</td><td>20.22</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
</tbody>
</table>------ (4)![Relationship between milage and engine](test5_files/test5_3_1.png)

此代码块的解释:

①这是序言。Pandoc 将首先寻找这个块,如果找不到,它将发出警告。包括至少一个标题、日期信息和作者姓名
(2)这是具有两个散列的第一幻灯片组,说明它是第二级标题,并且由于它后面是内容,因此这被认为是基础级 2
(3)将在下一张幻灯片中张贴表格的分隔符
(4)将在下一张幻灯片中张贴图表的分隔符

第十一步。 本文档保存为‘test 5 . MD’。我们现在将使用 pandoc 将这个 markdown 文档转换成 html。为此,我们键入以下代码(假设您位于正确的文件夹中):

~$ pandoc -t revealjs -s -o {output filename.html} {input markdown file name} -V revealjs-url={file or absolute URL}

所以,在我们的例子中:

  • pandoc 是程序
  • revealjs = revealjs
  • 输出文件 name.html = test5.html
  • 输入文件名= test5.md
  • revealjs-url =。/reveal js(reveal js 所在的文件夹)

因此,我们有:

~$ pandoc -t revealjs -s -o test5.html test5.md -V revealjs-url=./revealjs

如果一切顺利,这将产生 test5.html 文件。

第十二步 现在我们将文件夹连接到 git,并将文件夹提交到 github 库。为此,我们:

~$ git checkout -b gh-pages (1)
~$ git add . (2)
~$ git commit -m "added the slide deck files" (3)
~$ git push origin gh-pages (4)

解释:
(1) git checkout 是您用来切换到您之前创建的 gh-pages 分支的命令,该分支允许您托管您的幻灯片
(2) git add。是您用来添加 git 文件夹中所有内容的命令
(3) git commit -m 表示您添加了一个文本来指示您在该点做了什么:这是您的版本控制
(4) git push origin gh-pages 表示您将文件添加到了您的 gh-pages 分支,它们将从该分支发布

如果一切正常,你的网站将在一分钟后上线(有时,需要更长时间,耐心是一种美德)。假设您的用户名是“someusername ”,并且您创建了一个名为“jupyterslidedeck”的 github 存储库,您的站点将位于:

https://someusername.github.io/jupyterslidedeck/test5.html

它将如下所示:

Your first set of deck

摘要

现在,您已经创建了一个幻灯片。这还远远没有完成,因为你会看到表看起来不太好,图中显示了图像,但它可以更好地对齐,等等。你可能还想添加更多的幻灯片,和更多的互动。我们将在本系列的下一篇文章中解决这些问题。因此,至少总结一下我们所做的事情:

  1. 启动一个包含你的幻灯片的 github 库,比如“我的幻灯片”
  2. 使用终端将此 github 存储库的子模块添加到您的“实例”或机器(Mac/Linux/Windows)中;这将创建一个名为“myslides”的文件夹
  3. 将目录(cd)更改为我的幻灯片
  4. 使用 wget 命令在该文件夹中获取一个 revealjs git repo zip(master . zip)副本,然后使用 unzip 命令解压缩所有内容,然后将 reveal.js 文件夹重命名为 reveal js(可选)
  5. 在 myslides 文件夹中启动一个 jupyter 笔记本文件,并编写带有图表、表格、列表和文本的幻灯片文档
  6. 使用jupyter nbconvert --to markdown将 ipynb 文件转换为 markdown 文件格式
  7. 在 Jupyter 中打开生成的 markdown 文件,添加标题块,添加分隔符,删除(或者您可以保留)代码块等等
  8. 使用 pandoc 通过pandoc -t revealjs -s -o whatever.html whatever.md -V revealjs-url=./revealjs将降价文件转换成 html
  9. 当然,第 8 步假设 whatever.md 是您的 markdown 文件名,revealjs 是您从 revealjs git repo 下载并解压缩 master.zip 文件的文件夹
  10. 现在切换到 gh-pages 分支,将文件添加到 git repo,提交更改,并推送到您的 git repo。您的幻灯片将会实时播放

从现在起,对幻灯片的任何更改,您可以直接在 markdown 文件中进行,也可以在 jupyter 笔记本中进行,然后重新运行上面列表中的步骤 6 到 10。

如何从列值列表中创建多个工作表,并使用 R 和 VBA 自动删除任何空列

原文:https://towardsdatascience.com/how-to-create-multiple-worksheets-from-a-list-of-column-values-and-delete-any-empty-columns-4b121b659164?source=collection_archive---------22-----------------------

Photo by Zan on Unsplash

有时候,我们会面临一些我们认为非常容易解决的问题,但实际上在现实生活中并不那么容易。两个很好的例子是根据单元格值将一个大的工作表拆分成多个工作表,并为每个工作表删除大量的空列。让我更详细地解释给你听。

有哪些问题?

假设我们收到了一个这样的文件,并希望基于系列值创建多个工作表。共有 189 种不同的家庭价值观。手动执行这项任务或使用数据透视表效率不高,可能会导致一些内存问题。为此,我们将使用 R 和 VBA。

此外,在分割工作表后,我们将通过删除任何空列来清理每个工作表。该文件有 1,044 列,有些工作表有超过 100 个不连续的空列。

1。根据列值将一个大工作表拆分成多个工作表

首先,我们导入数据并安装软件包。之后,我们检查 family 列中唯一值的数量,并设置工作目录,这样我们的文件就可以保存在一个地方。

install.packages('dplyr')
library(dplyr)#importing the file
demo <- read.csv("C:/Users/kewon-de/Desktop/tbd/demo.csv.txt", sep=";")#checking the # of values in the family column
length(unique(demo[["family"]])) #189# setting the working directory
setwd("C:/Users/kewon-de/Desktop/tbd")

使用下面的 R 代码,我们可以根据列值快速创建多个工作表。该程序循环遍历列值(=族)列表,并创建多个数据框。这些数据框以后会变成工作表。

for(i in (demo$family)) {name <- paste("demo", i, sep = ".")assign(name, demo[demo$family==i,])
}

data frames with empty columns

2。删除任何空列

创建数据框后,我们现在可以检查是否有任何空列。首先,我们应该将所有数据帧放入一个列表中,这样我们就可以对列表应用一个函数(一次对所有数据帧应用函数)。下面的函数将去掉只有 na、null、无信息和 0 的列。在此之后,我们可以解压缩数据帧并验证列的数量——空列是否被正确删除。

lst<- mget(ls(pattern='^demo')) # putting 'demo' dataframes into a listoutput <- lapply(lst, function(df) Filter(function(x)!all(is.na(x) || is.null(x) || x == "" || x == 0),df))list2env(output,envir=.GlobalEnv)#unzipping the list

在清理空列之前,有 1044 列。

list of data frames before cleaning the empty columns

清理后,数据帧的数量变为 13 至 19 列。

list of data frames after cleaning the empty columns

clean data frames with no empty columns

解压缩列表时,干净的数据帧会替换旧的数据帧,如上所示。

  • 如果只想移除几个数据框的空列,可以使用此代码手动完成。
demo.acc_consoles <- Filter(function(x)!all(is.na(x) || is.null(x) || x == "" || x == 0), demo.acc_consoles)

3.将干净的数据帧导出为 CSV 格式

既然所有的数据帧都是干净的,我们可以使用下面的代码将它们导出为 CSV 文件。

install.packages("xlsx")
library(xlsx)
for(i in names(output)){write.xlsx(output[[i]], paste0(i,".xlsx"),sheetName = i)
}

下面是在 r 中曾经是数据帧的 CSV 文件。

data frames in CSV

4.将 Excel 文件合并成一个文件

文件夹里有多个 excel 文件就没那么方便了;我们不能浏览产品。让我们用 VBA 把所有的 excel 文件合并成一个,这样我们就不用一次又一次地打开文件了。

在 excel 中,进入文件,点击选项,添加开发者。

当 VBA 屏幕弹出时,右击 Sheet1 并插入模块。

当模块弹出时,在屏幕上插入以下代码,并单击绿色箭头按钮运行代码。不要忘记添加您自己的 excel 文件所在的路径。

Sub GetSheets()
Path = "insert your own path here"
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub

module

运行代码时,文件夹中的 excel 文件会自动合并成一个。

最后,我们有一个包含 189 个工作表的 excel 文件,中间没有空列。

本文分为两个部分:1)如何基于列值创建多个工作表 2)如何删除不连续的空列。您可以根据自己的需要简单地选择一个部分。

谢谢你看我的文章!如果你喜欢我所做的,不要犹豫,在 GitHub 上关注我,在 Linkedin 上与我联系。

另外,请随意查看我的其他文章:

如何获得关于货币汇率的 Twitter 通知:网络抓取和自动化

数据块:如何在本地计算机上将数据帧保存为 CSV 文件

使用 R Regex (Easy)从文本中提取关键字

如何从头开始创建 NumPy 数组?

原文:https://towardsdatascience.com/how-to-create-numpy-arrays-from-scratch-3e0341f9ffea?source=collection_archive---------13-----------------------

本教程是关于理解 NumPy python 包和从头开始创建 NumPy 数组的。

Credits: GitHub

不管数据如何,分析它们的第一步是将它们转换成一组数字。有效地进行数据科学的基本过程是存储和操作数值数组。因此 Python 有专门的工具来处理数字数组:

  1. NumPy 包
  2. 熊猫套餐

本教程只关注 NumPy 包。然而,熊猫包装文件将在晚些时候提供。教程的完整代码可以在下面我的 GitHub 库 中找到:

[## 塔努-北帕布/Python

此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…

github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/How_to_create_NumPy_arrays_from_scratch%3F.ipynb)

什么是 NumPy?

NumPy 代表 数值 Python。 NumPy 提供了一种高效的方式来存储和操作密集数据缓冲区。在 NumPy 库的帮助下,我们可以创建和操作数组来存储数据。在某些方面,NumPy 的数组就像 Python 的 list 内置函数。

如何执行 NumPy 并检查其版本?

让我们开始吧。你可以在你喜欢的 python 编辑器中执行下面的程序,比如 PyCharmSublime Text ,或者笔记本比如 JupyterGoogle Colab 。选择一个你喜欢的 IDE 基本上是你的喜好。我使用 Google Colab 来编写我的代码,因为它给了我大量的选项来提供好的文档。此外,请访问 NumPy 网站 以获得有关安装过程的更多指导。

一旦在 IDE 上安装了 NumPy,就需要导入它。检查库的版本通常是一个好习惯。所以要安装 NumPy 库,你需要使用下面的代码。

import numpy
print(numpy.__version__)**1.17.4**

只要确保你是最新的 NumPy 版本就可以使用所有的功能和选项。与其用"【numpy】"我们可以用一个别名作为"【NP"。这就是所谓的“ 走样 ”。现在使用别名的要点是我们可以使用" np "而不是" numpy ",每次使用它的方法时都需要键入很长的时间。因此,创建别名并检查版本可以如下所示:

import numpy as np
print(np.__version__)**1.17.4**

从现在起,我们每次都可以用“ np ,而不是“ numpy ”。

为什么有了 python 的固定类型数组,Numpy 数组就出现了?

Python 提供了几种不同的选项来存储高效的固定类型数据。Python 有一个内置的数组模块叫做“ array ,用来创建统一类型的数组。这是它的主要缺点。

import array# Creating an array
print(array.array('i', [1, 2, 3, 4, 5]))**array('i', [1, 2, 3, 4, 5])**

这里的“ i ”表示整数数据。我们不能尝试在数组模块中存储其他类型的数据。这通常会导致错误。

import array# Creating an array
print(array.array('i', [1, 2.0, 3, 4, 5]))**--------------------------------------------------------------------****TypeError            Traceback (most recent call last)**[**<ipython-input-25-49d63cb1f570>**](/<ipython-input-25-49d63cb1f570>) **in <module>()
----> 1 array.array('i', [1, 2.0, 3, 4, 5])****TypeError: integer argument expected, got float**

然而,Python 的数组模块提供了基于数组的数据的高效存储。但是 NumPy 数组可以对这种类型的数据执行有效的操作。有两种方法可以创建 NumPy 数组:

  1. 从 Python 列表创建 NumPy 数组
  2. 从头开始创建 NumPy 数组

从 Python 列表创建 NumPy 数组

我们可以使用NP . array方法从 python 列表中创建数组。

import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]
print(type(a))**<class 'list'>**# Creating a numpy array from the list
print(np.array(a))**[1 2 3 4 5]**print(type(np.array(a)))**<class 'numpy.ndarray'>**

NumPy 库仅限于具有相同类型的数组,如果存在类型不匹配,则可能的话会向上转换。考虑下面的例子:

import numpy as np# Creating a list named "a"
a = [1, 2.0, 3, 4, 5]
print(type(a))**<class 'list'>**# Creating a numpy array from the list
print(np.array(a))**[1\. 2\. 3\. 4\. 5.]**print(type(np.array(a)))**<class 'numpy.ndarray'>**

因此,原来的列表是具有一个浮点值的整数,但是 numpy 数组将其向上转换为所有的 浮点数 。整数被向上转换为浮点数。下面是一个小图表,给你足够的知识来理解向上转换和向下转换。

Numpy upcast and downcast

显式设置数据类型也是可能的。这可以使用关键字“ dtype ”来完成。

import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]# Creating a numpy array from the list
np.array(a, dtype='float64')print(np.array(a, dtype='float64'))**[1\. 2\. 3\. 4\. 5.]**

从上面的例子可以看出,通过使用关键字“ dtype ”将整数类型的列表数据转换为浮点类型的数据。

Numpy 数组也可以是 多维的(数组中的数组)。这是做这件事的一种方法。

import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]# Creating a numpy array from the list
np.array([range(i, i + 4) for i in a])**[[1 2 3 4]  [2 3 4 5]  [3 4 5 6]  [4 5 6 7]  [5 6 7 8]]**

提示 :只需将“I”的值递增 1 (i+1,2,3,4,…)这样做也可以增加数组的维数。上述阵列被视为 2D 阵列。

从头开始创建 NumPy 数组

Numpy 数组实际上用于创建更大的数组。使用 numpy 包库从头开始创建大型数组效率更高。下面是一些从头开始创建 numpy 数组的例子。

  1. 创建一个长度为 5 的零填充的数组

我们可以使用名为 的 numpy 内置方法来实现这一点,如下所示:

import numpy as np# Creating a numpy array of zeros of length 5
print(np.zeros(5, dtype='int'))**[0 0 0 0 0]**

有一些标准的 numpy 数据类型可用。我不能一口气讨论所有的问题。大部分都没用过。所以我将以图表的形式提供 numpy 数组的数据类型。如果你不知道如何使用数据类型,请参考显式更改其上面的数组数据类型dtypes = "数据类型的名称"****

Credits: Python Data Science Hand Book

2。创建一个用 1 填充的 3 x 4 数组

感谢 NumPy,因为我们不必将数组放在循环语句中(我讨厌这样做;)).你所要做的就是在 numpy.one 方法中提到你希望你的数组包含的行和列。

import numpy as np# Creating a numpy array of 1’s which should have 3 rows and 4 columnsprint(np.ones((3, 4)))**[[1\. 1\. 1\. 1.]  [1\. 1\. 1\. 1.]  [1\. 1\. 1\. 1.]]**

所以数字 3 →行和 4 →显然是列。

3。用特定的数字填充 numpy 数组

到目前为止,我们已经看到用 0 和 1 填充数组,但是我们还应该知道 numpy 允许我们用我们选择的任何特定数字填充数组。我们可以借助 numpy.full 方法来做到这一点。例如,让我们用数字 500 填充数组。

import numpy as np# Creating a numpy array of 500’s which should have 3 rows and 4 columnsprint(np.full((3, 4), 500))**[[500 500 500 500]  [500 500 500 500]  [500 500 500 500]]**

在 full 方法的帮助下,我们可以向数组中添加任意数量的元素。

4。创建随机数的 numpy 数组

均匀分布→ 它是所有结果发生的可能性相等的概率分布。例如,投掷硬币的概率是均匀分布的,因为结果很可能是正面或反面。两者不可能同时存在。

NumPy 包库为我们提供了一种生成随机数的均匀分布方法,名为NumPy . random . uniform

import numpy as np# Create a 3x3 array of uniformly distributed 
# random values between 0 and 1print(np.random.random((3, 3)))**[[0.89865866 0.71138067 0.85067426]  [0.53568422 0.32887081 0.97449983]  [0.48130729 0.15841703 0.57756513]]**

此外,numpy 包库有一个种子生成器和随机数生成器,在种子方法的帮助下,我们可以控制随机数生成的顺序。他们中的大多数人不知道种子方法的特殊性及其目的。要了解更多关于 seed 方法的信息,请参考下面的内容。

为什么我们需要随机数生成器内部的“种子”?

如果我们每次都使用种子,那么我们会得到相同的随机数序列。

因此,相同的种子产生相同的随机数序列。

import numpy as np# Create a random number arrays of size 5
np.random.seed(0)
print(np.random.random(5))**[0.5488135  0.71518937 0.60276338 0.54488318 0.4236548]**

不管你执行上面的代码多少次,每次你都会得到相同的随机数。要了解区别,只需对代码(#)进行注释,然后查看区别。让我们更深入地研究一下 seed 方法。

例如,如果您使用种子(1),然后生成一些随机数,它们将与您稍后生成的随机数相同,但使用相同的种子(1),如下所示。

import numpy as np# Create a random number arrays of size 5np.random.seed(1)
print(np.random.random(5))**[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01  1.46755891e-01]**print(np.random.random(5))# Different random numbers would be generated now
**[0.09233859 0.18626021 0.34556073 0.39676747 0.53881673]**np.random.seed(1)
print(np.random.random(5))# Same random numbers would be generated same as the first time - Due to seed
**[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01  1.46755891e-01]**

相同的种子相同的随机数保证“再现性”——Quora.com

同样,种子的范围是从 0 到 2 * * 32–1。 不要只使用负数作为种子值,如果你这样做你会得到如下所示的错误:

import numpy as npnp.random.seed(-1)-------------------------------------------------------------------**ValueError                      Traceback (most recent call last)**[**<ipython-input-9-bfd0c22f2d0a>**](/<ipython-input-9-bfd0c22f2d0a>) **in <module>()
----> 1 np.random.seed(-1)****mtrand.pyx in numpy.random.mtrand.RandomState.seed()****mt19937.pyx in numpy.random.mt19937.MT19937._legacy_seeding()****mt19937.pyx in numpy.random.mt19937.MT19937._legacy_seeding()****ValueError: Seed must be between 0 and 2**32 - 1**

正态分布→ 也称为高斯分布,是一个实值随机变量的连续概率分布。它也被称为一个 对称分布 其中大部分数值集中在峰值的中心。标准差决定了价差。

NumPy 包库为我们提供了一种生成随机数的均匀分布方法,名为NumPy . random . normal。语法与均匀分布几乎相同,但您需要添加两个更重要的数据,这里称为 均值标准差

import numpy as np# Create a 3x3 array of normally distributed random values
# with mean 0 and standard deviation 1print(np.random.normal(0, 1, (3, 3)))**[[-0.56651023  0.7299756   0.37299379]  [ 0.53381091 -0.0919733   1.91382039]  [ 0.33079713  1.14194252 -1.12959516]]**

5。使用 numpy 数组创建单位矩阵

单位矩阵是这样的矩阵,其中主对角元素是 1,除了主对角元素之外的其他元素是 0。numpy 包库提供了一种生成称为 眼的单位矩阵的方法。 单位矩阵是一个方阵,意思是它有相等的行和列。

import numpy as np# Create a identity matrix of 4 rows and 4 columnsprint(np.eye(4))**[[1\. 0\. 0\. 0.]  [0\. 1\. 0\. 0.]  [0\. 0\. 1\. 0.]  [0\. 0\. 0\. 1.]]**

数字 4 代表行和列,因为它是一个正方形矩阵,我们只需要指定一次该值(本例中为 4)。

本教程到此结束如何从头创建 NumPy 数组?”,这只是 NumPy 包库的入门教程。然而,更复杂的 NumPy 包库的概念将在接下来的教程中讨论。谢谢你们花时间阅读我的教程。我希望你喜欢它。如果你对 NumPy 有任何疑问,那么评论区就是你的了。直到那时再见,看到你有一个美好的一天。

如何使用 gganimate 创建动画精美的剧情?

原文:https://towardsdatascience.com/how-to-create-plots-with-beautiful-animation-using-gganimate-912f4279b073?source=collection_archive---------14-----------------------

Total suicide rates per country

引言。

可视化最重要的事情是当它迫使我们意识到一些我们不知道的事情。视觉上吸引人的图表很容易吸引我们的注意力。将数据动画化就像将生命吸入尘埃,这是一种创造的行为。你是如何创作出富有洞察力的吸引人的动画的?

在这篇文章中,我们将学习如何使用 R 包来创建漂亮的动画, gganimate 。

**#stable version of the package can be installed using** *install.packages(“gganimate”)* **#latest development version can be obtained by** *devtools::install_github(“thomasp85/gganimate”)*.

数据。

自杀率数据是从不同来源(世卫组织、联合国开发计划署、世界银行)汇编后从 Kaggle 获得的。该数据比较了 1985 年至 2016 年每个国家的社会经济信息和自杀率。灵感来自于不同国家的自杀预防策略。

数据角力。

我们将使用下面的代码来清理数据,并且只对我们将要处理的列进行子集化。

**#loading required libraries**
library(tidyverse)
library(reshape2)
library(ggthemes)
library(gganimate)
library(gifski)**#loading dataset**
suicide_data<-read.csv("./ARTICLES/suicide rates/master.csv",header = TRUE,stringsAsFactors = FALSE)**#selecting columns to work with**
suicide_sub<-suicide_data %>% select("ï..country","year" ,"sex","suicides_no")  %>% rename("country"="ï..country" )**#function to sum the total suicide per country**
n<-unique(suicide_sub$country)
country<-function(x){suicide2<-suicide_sub %>% filter(country==x)sum(suicide2$suicides_no)
}**#return a list with all total deaths per country**
country_total<-sapply(n,function(x) country(x))**#creating a dataframe with top 10 total suicides per country**
df<-do.call(rbind,Map(data.frame,Country=n,Total_Suicides=country_total))
df2<-df %>% arrange(desc(Total_Suicides))
df3<-head(df2,n=10)
write.csv(df3,"./ARTICLES/suicide rates/total_suicide.csv")**#plotting the top 10 countries leading in the total suicide rates**
ggplot(df3,aes(reorder(Country,Total_Suicides),Total_Suicides,fill=as.factor(Country)))+geom_col()+coord_flip(clip = "off", expand = FALSE)+guides( fill = FALSE) +labs(title="TOTAL SUICIDE DEATHS PER COUNTRY FROM 1985-2016", y="Total Suicides Per Country", x="Country")+scale_y_continuous(labels = scales::comma) +geom_text(aes(label = paste(Total_Suicides,"")), hjust = 1)

**#subset initial data with top 10 countries**
top_suicide<-suicide_sub%>%filter(country==c(“Russian Federation”,”United States”,”Japan”,”France”,”Ukraine”,”Germany”,”Republic of Korea”,”Brazil”,”Poland”,”United Kingdom”))**#filtering years with consistent data**
top_suicide2<-top_suicide %>% filter(year %in%c(1990:2014)) 
top_suicide2$sex<-as.factor(top_suicide2$sex)**#summing the total male & female suicides per country for each year**
sm3<-aggregate(suicides_no~country+year,top_suicide2,sum)**#* 1 ensures we have non-integer ranks while sliding**
sm4<-sm3 %>% group_by(year) %>% mutate(rank = min_rank(-suicides_no) * 1) %>%ungroup()

构建静态地块。

我们的数据现在已经可以绘图了。我们不打算深入使用 ggplot 的更多细节。使用 ggplot 的综合指南可在这里获得。

**#plotting static plot**
static_plot<-ggplot(sm4,aes(rank,group=country,fill=as.factor(country),color=as.factor(country))) +geom_tile(aes(y = suicides_no/2,height = suicides_no,width = 0.9), alpha = 0.8, color = NA) +geom_text(aes(y = 0, label = paste(country, “ “)), vjust = 0.2, hjust = 1) +geom_text(aes(y=suicides_no,label = paste(“ “,suicides_no)), hjust=0)+coord_flip(clip = “off”, expand = TRUE) +scale_y_continuous(labels = scales::comma) +scale_x_reverse() +guides(color = FALSE, fill = FALSE) +theme_minimal() +theme(plot.title=element_text(size=25, hjust=0.5, face=”bold”, colour=”grey”, vjust=-1),plot.subtitle=element_text(size=18, hjust=0.5, face=”italic”, color=”grey”),plot.caption =element_text(size=8, hjust=0.5, face=”italic”, color=”grey”),axis.ticks.y = element_blank(), axis.text.y = element_blank(), plot.margin = margin(1,1,1,4, “cm”))

动画。

gg animate 的关键特性是什么?

  1. *transition_ : 此函数定义数据应该如何分布,以及它如何随时间的推移与自身相关联。

a. transition_reveal: 这允许你让数据逐渐消失。

b.转换时间:状态之间的转换长度被设置为对应于它们之间的实际时间差。

c. transition_state: 用于通过分类变量或离散变量来激活图形。

  1. *view_ : 用于定义轴应该如何随动画变化。

a.view _ follow(fixed _ y = TRUE):这意味着当动画运行时,y 轴是固定的。

b.view _ follow(fixed _ x = TRUE):当动画运行时,x 轴是固定的。

  1. ease_aes(): 它描述了在动画制作过程中应该如何缓和不同的美感。

a. ease_aes("立方进制出")

b. ease_aes("正弦输入输出")

  1. *enter_*/exit_ : 用于确定在动画过程中,新数据如何出现,旧数据如何消失。

a.进入 _ 淡出/退出 _ 收缩

  1. State_length: 这是指状态暂停的相对长度。

6.过渡 _ 长度:这是动画的相对长度。

**#creating final animation**
plt<-static_plot + transition_states(states = year, transition_length = 4, state_length = 1) + ease_aes(‘cubic-in-out’) +#view_follow(fixed_x = TRUE) +labs(title = ‘Total Suicides per Year : {closest_state}’, subtitle = “Top 10 Countries”,caption = “Data Source: World Bank Data”,x=”Countries”,y=”Total Suicides per year”)

7.渲染。

这是一种输出最终结果的计算。使用的参数包括:

nframes: 设置要使用的帧数(默认为 100)。

每秒帧数(fps): 这是每秒每帧花费的时间(默认为 10)

渲染器:设置将每一帧合成动画的功能。(默认为 gifski_renderer())。

如果我们想结束循环,我们使用:renderer = gif ski _ renderer(loop = FALSE)为了将动画情节保存为视频,我们使用renderer = ffmpeg _ renderer()

8.持续时间这是帧制作动画所需的总时间,即持续时间=30

9.布局。

我们可以通过指定大小来改变绘图的高度和宽度

我们将动画输出保存到一个名为 final_animation 的对象中。

**#rendering the animation for gif**
final_animation<-animate(plt,100,fps = 20,duration = 30, width = 950, height = 750, renderer = gifski_renderer())**#rendering the animation for mp4** animate(plt,100,fps = 20,duration = 30, width = 950, height = 750, renderer = ffmpeg_renderer())

10。保存动画。

为了保存我们的动画,我们将使用带有参数的函数 anim_save() :

动画——这是我们动画剧情的最终输出。

路径-我们想要保存动画的地方。

**#saving the animation**
anim_save(“./ARTICLES/suicide rates/suicide_animate.gif”,animation=final_animation)

输出。

Final animation output.

结论。

我们已经能够用动画软件包来显示每个国家的自杀率。你可以调整代码,以有效地动画任何数据集,并纳入自己的演示文稿,博客或网站。要获得更多关于创建动画的见解,你可以查看这篇 StackOverflow 指南或关于数据科学的文章。随意评论,分享,点赞。更多讨论,你可以通过 Linkedln 联系我。

如何从头开始创建简单的基于关键词的电影推荐模型

原文:https://towardsdatascience.com/how-to-create-simple-keyword-based-movie-recommender-models-from-scratch-afde718636c9?source=collection_archive---------11-----------------------

介绍

你试过用电影推荐器吗?理论上,这是一些有用的东西,可以帮助确定下一步该看什么,而不是花几个小时浏览网飞,但他们的结果往往是漫无目的的。这是一个大多数人都会涉及的问题,所以我决定自己创建一个自制的推荐系统,并在这篇博文中分享。我将向您展示如何从头开始创建 3 个简单的推荐模型,接受一部电影作为输入,返回“n”部最相似的电影作为输出,其中“n”由用户提供。

一般来说,推荐系统要么基于内容,要么与用户的历史和兴趣合作。我选择创建基于内容的模型,因为它们基于特定的输入项(电影)而不是基于用户进行预测。

注意,这个博客的推荐完全基于电影关键词。正如您将看到的,使用其他文本信息,如情节大纲或情节概要,而不是电影关键字是相当简单的。

为了限制这篇文章的范围,我没有包括数字特征(例如运行时间、发布年份、评级等。)和流派进行推荐。

如果你想在 GitHub 上关注或查看这篇文章的代码,请访问:https://GitHub . com/gbl inick/Movie-Recommender-with-NLP/blob/master/Keyword % 20 Movie % 20 Recommender . ipynb

数据集创建

任何数据科学项目的第一步都是获取数据集。有时你的数据集会给你(比如 Kaggle 竞赛)。在我们的例子中,由于这个项目是“从零开始”的,我们必须自己获得数据。

寻找电影数据的第一个地方是 https://www.imdb.com/interfaces/的 IMDb 公共数据仓库:。这个存储库包含 7 个表,其中包含各种各样的优秀电影数据。不幸的是,没有一个表格包含我们可以用来推荐的电影关键词。这并不意味着我们不能使用任何表格。看看这些表格,我们注意到其中一个,【title.ratings.tsv.gz】的包含一个名为“numVotes”的列,表示“该标题获得的票数”。这对我们很有用,因为我们可以使用这个列来获得投票数最多的 10,000 部电影。当然,如果能在我们的模型中包含每一部电影就好了,但是由于计算相似性需要额外的时间,这是不实际的。此外,即使我们没有实际的计算缺陷,我也不确定大多数人是否有兴趣看排名前 10,000 以外的电影。前 10,000 部电影应该足以让绝大多数观众满意。

我们还需要第二个表,title.basics.tsv.gz,它提供列标题类型,告诉我们标题是否是电影(相对于电视节目)。因为我们只想在我们的推荐者中包含电影,所以我们使用该列来过滤电影。

综上所述,这是我们目前的工作流程:

  1. 导入必要的库(熊猫和 numpy):

2.将我们需要的两个 IMDb 表导入 pandas 的数据框架中(在图中,文件位于与我们的笔记本平行的名为“data”的文件夹中):

3.仅从 title.basics 表中选择电影,并创建一个新的数据帧“电影”:

4.为表创建一个公共索引(两个表中每个标题的 IMDb 唯一标识符在这里是一个很好的选择),然后用一个简单的内部连接来连接表:

太好了!我们现在有一个名为“movies_with_rating”的表,其中包含所有 IMDb 电影及其评级(以及我们使用的 2 个表中的所有其他信息)。让我们看看最上面一行:

我们在表格中看到一些关于第一部电影的有趣信息。然而,我们未来的模型并不需要所有这些数据。对于这个项目,我们所关心的是通过 numVotes 获得前 10,000 部电影,并使用电影关键字来查找电影之间的相似性。

我们可以很容易地用熊猫来做到这一点。sort_values 函数:

完美。现在,我们可以将注意力转向获取我们想要用于推荐模型的情节信息。我们可以使用精彩的 IMDbPY API:【https://imdbpy.readthedocs.io/en/latest/index.html】获得这样的剧情信息。您需要使用 pip 或 conda 安装 API。

在使用 API 之前,我们需要导入它并实例化一个 IMDb 电影对象。我们将这样做,并导入几个其他的库,使用 API 运行 for-loops 成为更好的体验:

从 IMDb 提取绘图关键字的语法如下:

在上面的代码中,我首先实例化了一个字典来存储我将从 IMDb(在第 1 行)获取的关键字。我将使用电影 id 作为键,使用每部电影的关键字列表作为值。

在从第 2 行开始的 for 循环中,我遍历了前 10,000 部电影的索引。在第 5 行,我使用每个电影索引来获取相应的 IMDb 电影对象。请注意,在第 5 行,我从索引 2 开始对电影索引进行了子集化,因为索引以“tt”开头,后面跟着一个数字,而我们只需要这个数字。然后,我通过“情节大纲”对电影对象进行子集划分,以获得所需的情节大纲,然后将结果关键字列表作为对应于电影索引键的值存储在我的关键字字典中。

注意我在上面的代码中使用了 tqdm 和 sleep 库。tqdm 允许你看到你在 for 循环运行中的位置。当你运行一个 for 循环 10,000 次时(就像我们一样),很高兴知道你走了多远。

睡眠图书馆让我们对 IMDb 有礼貌。假设我们请求网站给我们 10,000 次信息,最好将我们的请求分隔开,这样我们就不会让服务器不堪重负。

完成 for 循环后,我们有了一个字典,其中的键是电影 id,值是关键字列表。看起来是这样的:

我们应该把这本字典转换成熊猫数据框架,以利用熊猫的能力。但是,如果我们只是做一个简单的 pd。熊猫会抱怨我们的字典长度不一样。因此,我们需要一个解决方案来获得我们想要的东西,如下面的代码所示:

在第 1 行中,我们创建了一个新的字典,其中有相同的键,但值与之前的字典不同。这些值不再是关键字列表,而是熊猫系列。我们可以将这个字典转换成 DataFrame,然后在第 10 行用一个简单的 lambda 函数连接所有的关键字(现在是它们自己的列)。应用 lambda 函数后,我们得到一个系列,因此我们可以将这个系列转换为 DataFrame,重命名我们的列,并保存为 CSV。

我们不需要将绘图轮廓保存到 CSV 文件中,但是当您从一个耗时的过程中获取数据时,保存它是非常明智的,这样您就不必重新运行获取数据的过程。

要使用我们的绘图轮廓数据,我们可以从 keywords.csv 文件中加载它,重命名文件中存在的 2 列(即键和值)并将其连接到我们现有的表中:

就是这样!

我们现在有了一个情节文本信息的数据集,可以用来计算电影之间的相似性。

电子设计自动化(Electronic Design Automation)

在创建我们的模型之前,让我们做一些快速的 EDA。文本数据不是最容易进行探索性数据分析的数据,所以我们将保持 EDA 简短。

我们可以做的第一件事是查看每个关键字列表中字符数量的分布。我们先剔除没有关键词的电影:

我们现在可以找到每个关键字列表的长度(以字符为单位):

从分布和每列的平均字符数可以看出,分布是右尾的。

让我们看看,如果我们为每个关键字列表中的单词数绘制分布图,是否会得到类似的分布:

是的,也很右尾。

因此,我们对关键词列表进行了两种不同的测量——列表中的字符数和单词数——它们显示了相同的模式。这是有意义的,因为这些度量是直观相关的。右翼告诉我们的是,大多数电影没有很多关键词或角色,但有一小部分——大概是最成功的电影——有很多关键词和角色。

创建模型

我们现在可以创建我们的模型了。首先,我想讨论一个关于自然语言处理和使用文本的问题。通常,当使用文本时,你没有好的、易于使用的关键字列表。如果我们决定使用情节概要而不是关键词列表(如果 IMDb 不提供电影关键词,就会发生这种情况),我们就会遇到这种情况。在这种情况下,有一些标准的,简单的步骤,你可以采取,以基本上创建自己的关键字列表。它们是:

1.小写单词

2.删除标点符号

3.删除停用词

4.词汇词条化

这些都可以使用 nltk 库相对简单地完成。

回到我们的模型:我们将创建 3 个不同的模型,基于不同的相似性概念以及不同的电影文本“向量”公式。前 2 个模型将使用余弦相似度,最后一个将使用 Jaccard 相似度。在前两个模型中,第一个将使用 tf-idf 创建电影矢量,第二个将使用简单的字数统计。

我们首先选择我们需要的列。因为我们正在创建基于关键字的推荐器,所以我们需要 keywords 列。因为我们还想输入一部电影的标题并获取其他电影,所以我们需要“primaryTitle”列。因此,我们将选择这两列。我们还重置了索引,因为我们的推荐功能稍后将使用电影在数据帧中的位置,而不是其 IMDb ID 来进行推荐:

接下来,我们需要获得一个列表列表,其中内部列表是每部电影的关键字列表。目前,我们在每部电影的关键字列中有一个字符串,其中包含所有关键字,并用逗号分隔。

我们可以通过使用 nltk 库获得这样一个列表列表:

在第 2 行,我们得到了前面提到的字符串列表。在第 4 行,我们从 nltk 库中导入了 work_tokenize 模块。在第 5 行,我们有一个列表理解,我们循环遍历每个关键字串,对于每个关键字串,我们得到带有 word_tokenize 的单个单词。注意word _ token ize(keyword . lower())返回一个关键字列表,所以我们最终得到一个列表的列表。

我们在这一点上还没有完成,因为 word_tokenize 在我们的关键字列表中留下了许多逗号。我们可以通过定义一个自定义函数 no_commas ,并将其应用于我们的关键字列表列表中的每个关键字列表,来轻松摆脱它们:

很好。所以我们现在在 processed_keywords 中有了我们想要的东西。

我们现在可以创建我们的第一个模型,一个使用词向量间余弦相似度的 tf-idf 模型。我不打算在这里解释它们是如何工作的。快速的谷歌搜索应该会返回许多有用的资源。

我们首先使用 gensim 创建一个单词字典:

这里的字典只包含我们处理过的关键字列表中与 ID 匹配的每个单词。

接下来,我们创建一个 genism 语料库,这里的语料库只是指“每部电影的词汇包”:

接下来,我们可以使用 genism tf-idf 模型将这些单词包转换为 tf-idf 模型:

最后,我们为我们的电影关键字集创建一个索引,允许我们计算任何给定的关键字集与我们的数据集中每部电影的关键字之间的相似性:

我们现在可以写一个函数来接受一部电影,并返回“n”部最相似的电影。我们函数的工作方式如下:

1.接受用户的电影

2.接受来自用户的“n ”,其中“n”是用户想要返回多少部电影

3.检索电影的关键词

4.将电影的关键词转换成单词包

5.将单词袋表示转换成 tf-idf 表示

6.使用 tf-idf 表示作为查询文档来查询我们的相似性度量对象

7.获取我们集合中每部电影的相似性结果,按照相似性递减的方式对集合进行排序,并返回“n”部最相似的电影及其相似性度量。不要返回最相似的电影,因为每部电影都是最相似的

在代码中:

现在让我们来测试一下。因为复仇者联盟最近很受欢迎,所以让我们将原始电影交给我们的功能:

看起来都很般配。

请注意,这种推荐系统不仅限于根据其他电影推荐电影。我们可以使用任何给定的关键字集来查询我们的相似性度量对象。碰巧的是,大多数人会想使用他们已经知道的电影来查询它,但它不限于此。

以下是基于提供的关键词进行推荐的更通用的函数:

我们可以继续我们的第二个推荐器,它也使用余弦相似度来计算单词向量之间的相似度。它与第一个模型的不同之处在于使用更简单的字数,而不是创建 tf-idf 字向量。这个替代实现是用 scikit-learn 中的 CountVectorizer 类来执行的,它将一组文本文档(在本例中是关键字列表)转换成一个令牌计数矩阵。

为了简单起见,我们还将计算余弦相似度。我们将使用 scikit-learnmetrics . pairwise子模块中的余弦相似度函数,而不是使用矩阵相似度

我们用下面的代码计算每部电影的字数:

然后,当给定一部电影时,我们需要做的就是计算该电影的词向量和其他词向量之间的余弦相似度,并返回最相似的匹配。这是通过我们的余弦推荐器功能实现的:

让我们在《复仇者联盟》中也尝试一下:

有用!与第一个模型相似。

对于我们的第三个模型,我们使用 Jaccard 相似度代替余弦相似度。因此,我们根本不需要单词向量。我们简单地将相似性计算为关键字集的交集除以关键字集的并集。

计算任意两个关键字列表之间的 Jaccard 相似性的代码很简单:

由此创建推荐器模型相对简单。我们找到给定的输入电影的关键字列表,计算该列表和每个其他电影关键字列表之间的 Jaccard 相似性,然后根据它们的相似性对电影进行排序,并返回前“n”个结果。

在代码中:

用我们最喜欢的电影进行测试,我们得到了很好的结果:

后续步骤

我们有很多方法可以改进现有的模型。

首先是用 Flask 部署模型,这样人们就可以使用它们了。可用性非常重要。

下一步将是找到一些方法来衡量我们的模型的性能。这很棘手,因为推荐系统通常没有明显的评估标准。尽管如此,我们还是可以想出一些方法(例如,使用用户反馈对模型进行排名),而且有很好的资源可以这样做。

第三个要考虑的改进是在带有嵌入的情节概要上使用深度学习方法:https://tfhub.dev/google/universal-sentence-encoder/2。这些方法应该允许我们将上下文结合到我们的推荐中,而不是像我们的模型目前使用的简单的单个单词。

最后,可以通过合并其他非文本特征(如体裁或数字特征)来改进模型。

几周后再来这里看看。我可能会写另一篇博文来实现这些改进。

请让我知道你对这个项目的看法,如果你有任何改进的建议。非常感谢所有建设性的意见。

参考

为了获得使用 Gensim MatrixSimilarity 类比较文档的灵感,我使用了奥瑞利的精彩教程“我如何使用 Python 比较文档相似度”:https://www . oreilly . com/learning/How-do-I-compare-document-similarity-using-Python

关于 Jaccard 和余弦相似度推荐器的使用,我非常感谢 Sanket Gupta 的教程“Python 中文本相似度度量概述”:https://towards data science . com/Overview-of-Text-Similarity-Metrics-3397 c 4601 f50

如何在 Azure 中创建自己的深度学习项目

原文:https://towardsdatascience.com/how-to-create-your-own-deep-learning-project-in-azure-509660d8297?source=collection_archive---------10-----------------------

使用 Azure 存储、带有 Keras 的数据块和 Azure ML 服务

1.介绍

深度学习对公司来说有很多实际应用,例如图像识别、视频索引和语音到文本转录。然而,对于公司来说,从深度学习项目开始可能会令人望而生畏。常见的问题是所用数据的敏感性和深度学习的复杂性,深度学习可以被视为机器学习的最高级。

2.目标

在本教程中,创建了一个样本深度学习项目,它能够使用 CIFAR-10 数据集(飞机、青蛙、船)识别图片类别。在这种情况下,执行以下步骤:

  • Azure 存储用于安全地存储图片
  • Azure Databricks 用于使用 Keras 和 TensorFlow 训练模型
  • Azure ML 服务用于将模型版本化和部署为 HTTP 端点

这可以在下面的体系结构概述中描述:

2. High level overview

这个解决方案的关键是 Azure Databricks,这是一个针对 Azure 优化的基于 Apache Spark 的分析平台。它本机集成了其他 Azure 服务,如 Azure Active Directory 和 Azure Storage。在本博客的剩余部分,将执行以下步骤:

  • 3.先决条件
  • 4.创建深度学习项目
  • 5.部署深度学习模型
  • 6.结论

这是一个独立的教程,重点是在 Azure 中建立自己的深度学习项目,以“弄脏你的手”,从而更加熟悉这个主题。重点是深度学习的内部工作,最新的算法或计算机视觉 API。如果你对 AI 的 devops 更感兴趣,请参考我以前的博客,这里和关注安全,见这里。

3.先决条件

需要在同一资源组和同一位置创建以下资源。

  • Azure 存储帐户
  • Azure Databricks 工作区。
  • Azure 机器学习服务

4.创建深度学习项目

这一部分将执行以下步骤。

  • 4a。将图片添加到存储帐户
  • 4b。创建深度学习集群
  • 4c。装载存储帐户
  • 4d。单节点训练深度学习模型
  • 4e。终止深度学习集群

4a。将图片添加到存储帐户

在本教程中, CIFAR-10 数据用于训练深度学习模型。在第一个模型中,将使用 2000 个图片的子集。随后,将创建第二个模型,该模型使用 60000 张图片的完整 CIFAR-10 数据集。

为了说明如何将 Azure Storage 与 Azure Databricks 结合使用,将在 Storage 帐户中存储 2000 张图片的子集。因此,请访问以下 URL,下载 2000 张图片的压缩文件。

[https://github.com/rebremer/devopsai_databricks/raw/master/sampledata/2000pics_cifar10.zip](https://github.com/rebremer/devopsai_databricks/raw/master/sampledata/2000pics_cifar10.zip)

随后,转到 Azure 门户并选择您的存储帐户。然后选择 blobs 并创建一个名为“2000picscifar10”的新容器。随后,将之前下载的 zip 文件上传到您的容器中。

4a1. Add zipfile to new container

最后,转到访问密钥,复制密钥或您的存储帐户。

4a3. Copy access keys

4b。创建深度学习集群

转到您的 Azure Databricks 工作区并转到群集。由于模型将在不使用 Spark 作业的情况下在驱动程序节点上训练,因此不需要创建(并支付)工人节点。因此,使用以下设置创建一个新的 GPU 集群:

4b1. Create GPU cluster without worker nodes

4c。装载存储帐户

转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:

[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/0_mountStorage.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/0_mountStorage.py)

另请参见下图:

4c1. Import notebook to mount storage

打开您的节点簿并更改以下设置

storageaccount="<<your_storage_account>>"
account_key="<<your_key_in_step4a>>"
containername="2000picscifar10" # change if you used another name

请注意,在生产环境中,不得将密钥存储在笔记本中。相反,秘密范围将被使用,参见我的博客如何在数据科学项目中嵌入安全性。然后将笔记本连接到您创建的集群,然后单击 SHIFT+ENTER 来逐个单元地运行。

4c2. Attach notebook to cluster

在本笔记本中,将执行以下步骤:

  • 将存储帐户装载到 Azure Databricks 工作区
  • 解压缩存储帐户中的图片
  • 列出并显示图片

4d。单节点训练深度学习模型

再次转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:

[https://github.com/rebremer/devopsai_databricks/blob/master/project/modelling/1_DeepLearningCifar10NotebookExploration.py](https://github.com/rebremer/devopsai_databricks/blob/master/project/modelling/1_DeepLearningCifar10NotebookExploration.py)

在本笔记本中,将执行以下步骤:

  • 从存储帐户导入和处理数据
  • 根据存储帐户中的 2000 张图片建立模型
  • 在完整 CIFAR-10 数据集的 60000 张图片的数据集上建立模型
  • 将模型保存到磁盘(dbfs)

当您成功运行笔记本时,您可以看到预测的概述(红色是错误的预测)。

4d1. Overview of predictions

4e。终止深度学习集群

运行 GPU 集群的成本可能很高。由于我们在本教程的剩余部分不需要 GPU 集群,我们可以停止它。因此,转到您的集群并选择终止。

4e1. Terminate cluster

5.部署深度学习项目

这一部分将执行以下步骤。

  • 5a。在数据块中创建新簇
  • 5b。将库添加到集群
  • 5c。注册模型和日志指标
  • 5d。创建模型的 HTTP 端点
  • 5e。测试模型的 HTTP 端点

5a。在数据块中创建新簇

在这一步中,将创建一个新的集群,用于部署我们的模型。既然模型已经训练好了,我们就不再需要 GPU 了。选择具有以下设置的群集

5a1. Non GPU cluster

5b。将库添加到集群

为了部署我们的模型,我们需要几个库。转到您的共享文件夹,右键单击共享并选择“创建库”。

4b1. Add Libraries

随后,选择 Pypi 并将以下库添加到共享文件夹中:

azureml-sdk[databricks]
keras
tensorflow

5c。注册模型和日志指标

在这一步中,模型及其指标将被添加到您的 Azure ML 服务工作区。在 Azure Databricks 工作区中导入以下笔记本。

[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2a_Cifar10KerasNotebookLogModel.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2a_Cifar10KerasNotebookLogModel.py)

打开您的节点簿并更改您的 Azure ML 服务工作区的以下设置(订阅 id 可在您的 Azure ML 服务工作区实例的概述选项卡中找到)。

workspace="<<your_name_of_azure_ml_service_workspace>>"
resource_grp="<<your_resource_group_amlservice>>"
subscription_id="<<your_subscriptionid_amlservice>>"

然后运行笔记本,再次使用 Shift+Enter 逐个单元格地浏览。在本笔记本中,将执行以下步骤:

  • 在 2000 张图片上训练的模型的对数度量
  • 在所有 60000 张图片上训练的模型的日志度量
  • 在步骤 5d 中注册要部署的最佳模型

要查看指标,请转到门户,选择 Azure 机器学习工作区,然后选择 Expirement,见下文

5c1. Log metrics of model with 2000 pictures and all CIFAR-10 pictures

5d。创建模型的 HTTP 端点

将以下笔记本导入您的工作区

[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2b_Cifar10KerasNotebookDeployModel.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2b_Cifar10KerasNotebookDeployModel.py)

再次更改参数,类似于步骤 5c。在这个笔记本中,为在所有图片上训练的模型创建一个端点。当你去门户网站,选择 Azure 容器实例,你会发现端点的 IP 地址。

5d1. Azure Container Instance with IP addresss

5e。测试模型的 HTTP 端点

要测试端点,需要完成以下步骤:

  • 从互联网上获得一个 CIFAR-10 类别的随机 png
  • 使用此网站将 png 转换为 base64 编码
  • 使用类似邮递员的工具发送 base64 有效载荷来创建预测。

下图是一艘船的图片,转换为 base64 格式,用 Postman 发送,使用 endpoint 创建预测。

5e1. Picture of ship converted to base64 using https://onlinepngtools.com/convert-png-to-base64

5e2. Prediction of ship using HTTP endpoint

6.结论

在本教程中,创建了一个深度学习项目,其中使用了以下服务:

  • Azure 存储帐户可以安全地存储图片
  • Azure Databricks 与 Tensorflow 和 Keras 一起构建模型
  • Azure ML 服务跟踪模型并创建 HTTP 端点

深度学习对企业有很多实际应用。然而,对于企业来说,从深度学习项目开始可能会令人望而生畏。创建您自己的示例项目并“亲自动手”是学习和熟悉该主题的好方法。

6. Sample project overview

最后,非常感谢我的同事 Ilona Stuhler,她非常友好地向我提供了这个课题的重要内幕,并把她的项目捐赠给了我。

如何创建自己的深度学习平台:完整的硬件指南。

原文:https://towardsdatascience.com/how-to-create-your-own-deep-learning-rig-a-complete-hardware-guide-2bba792b001b?source=collection_archive---------2-----------------------

以及从长远来看,它如何比云解决方案更快、更便宜。

这篇博客是关于建立一个 GPU 工作站,像 Lambda 的预建 GPU 深度学习平台一样,并作为一个指南,指导你应该看什么是绝对的东西,以确保你准备创建自己的深度学习机器,而不是意外地购买昂贵的硬件,后来证明不兼容并造成问题。但是在我们开始之前…

你真的需要吗?

当我开始更认真地对待深度学习或机器学习时,我遇到的一件事是:计算

我过去做过机器人,觉得现在是我自己创建终极深度学习平台的最佳时机,它将像任何东西一样处理信息,并以极快的速度工作。

但是很明显,当你有云计算时,为什么要花这么多钱。当你不需要维护任何机器,也不担心它有一天会过时时,为什么不按照你的意愿,在你想要的任何时候建立另一个实例呢?

好吧,深度学习的故事说的是别的东西。博客[1][2][3]比较了它的多个方面,漂亮地概括了一切。最后:

从长远来看,使用本地深度学习机器实际上比使用云实例更便宜、更快、更容易。[1][2][3][4]

所以,我们来创造自己的深度学习机器吧。

但是,首先,如果你不是一个 DIY 的人,并且正在寻找一个预建的深度学习系统,我推荐 Exxact 的深度学习工作站,由英伟达 RTX 2080 Ti、特斯拉 V100、泰坦 RTX 或 RTX 8000 GPU 提供支持,并提供 3 年保修。他们的工作站起价 3700 美元。

目录:

  • CPU
  • 储物解决方案
  • 主板
  • 冷却解决方案
  • 案例
  • 闸板
  • PSU
  • GPU
  • 显示器和键盘
  • 安装操作系统
  • 最终想法
  • 参考文献

我们将在接下来的章节中详细讨论每一项。

中央处理器

Ryzen threadripper CPU

鉴于现在大部分深度学习模型都运行在 GPU 上,CPU 的使用主要是为了数据预处理。

如果您经常处理千兆字节的数据,并且如果您在分析部分做了大量工作,必须进行大量查询才能获得必要的见解,我建议您投资一个好的 CPU。

否则,投资一个中级处理器不会有任何坏处,因为 CPU 只在 GPU 进行训练时帮助批处理调度和其他小进程。

AMD 的 threadripper 系列非常强大,性价比极高。我选择了 Threadripper 1900x,8 核 16 线程 CPU。

重要事项:

由于高性能价格比,我随时会选择 AMD。这就像是为相同的性能支付了英特尔同类产品一半的价格。

搜索 youtube 进行安装或查看主板指南。这非常简单明了,但是芯片有点脆弱。小心轻放。

储存;储备

三个可用选项是:

  • HDD (硬盘驱动器)
  • SSD (固态硬盘)
  • NVME SSD (非易失性存储器快速)

硬盘是一个旋转的磁盘,上面有毛笔写和读比特。由于它是机械的和完全机动化的,所以性能很慢,占用更多的空间,并且更容易损坏和破坏数据。

固态硬盘:它们体积小,速度快,没有任何移动部件。虽然有点贵。这在整体体验中当然很重要。当操作系统加载到固态硬盘存储之上时,会变得非常流畅。在深度学习中,当你几乎每次都要处理数 GB 的数据时,文件传输速度非常快。SATA 3 插槽使用 AHCI 驱动程序,最高传输速度可达 600 Mbps。

NVMe 固态硬盘:不使用 SATA 总线,而是使用 PCIe,性能大幅提升。此外,使用的传输协议不是 AHCI,而是 NVMe,提供了高效的并行处理。最后,我们这里说的是 2–3gb/s。不同型号的数字不同。

它仍然是一项新技术,就其提供的功能而言,它比 SSD 贵得多。与常规固态硬盘相比,NVME 固态硬盘在操作系统中的性能几乎不会有所提升,而且文件传输的等待时间也会大大减少。此外,NVMe 的意思是,确保主板有 m2 插槽,这也增加了它的价格,因为旧的没有它。

要了解更多关于 SSD 和 NVME SSD 技术的信息,你可以去看看 Kingston[ 20 ]写的一篇短小精悍的博客,里面有很多对比两者的视觉图像。此外,这个 youtube 视频用动画很好地解释了 NVMe。

英特尔推出了具有 3D 交叉点晶体管的 Optane 存储,可提供更高的密度和性能。但是非常昂贵,根本不值这个价钱。更多关于 Optane 的信息在这里[ 6 ]。

我选择了 500 GB 的 NVMe M2 固态硬盘,因为我可以为我获得的高速度支付额外的费用。不然 SSD 比 HDD 好很多。

重要事项:

假设您的数据将驻留在 RAM 或 GPU VRAM 中。在训练数据时,存储并不重要。

从性价比来看,投资固态硬盘比投资硬盘更好。

NVMe SSD 以为很快就贵了,还需要兼容主板。

母板

正如你所看到的,它们有不同的尺寸。标准尺寸决定了你想要的箱子类型。根据您的需要,在给定的主板上,您可以检查:

  • 内存的 DIMM 插槽
  • GPU 的 PCIe 插槽
  • NVMe 固态硬盘的 M2 插槽(如果你很快就会使用)
  • 固态硬盘的 SATA 端口
  • 根据需要提供雷电 3/USB 3.0/2.0 接口。

为将来的升级提供额外的插槽是件好事。人们一般会升级到更高的 RAM,并且将来还会添加多个 GPU。

选择会因人而异。预装机器通常通过使用没有足够插槽用于未来升级的主板来节省资金。你可以在这里选择。

重要事项:

确保你的 CPU 支持给定的主板。可以选择 CPU 和主板的最佳组合来省钱。

许多人关心每个 PCIE 插槽的通道数量。用几个 GPU 完全没关系。在 Tim dettmers 的博客[ 7 ]中,“CPU 和 PCI-Express”一节以 Imagenet 数据集为例对此进行了精彩的解释。因此,不要因为另一家提供 16 车道 PCIe 而不是 8 车道就额外付费。

如果您计划在未来添加更多 GPU,请确保 PCIE 插槽足够远。鉴于这些天来 GPU 如何在他们的 beafy 散热器中采用多风扇结构,随着 NVIDIA 不断增加越来越多的核心,大多数 GPU 占用 2 个 PCIE 插槽的空间。(否则,你将不得不寻找一个垂直安装的 GPU 连接器,这是昂贵的,也不容易在大多数国家获得。)

GPUs taking space of 2 PCIe slots.

冷却

是的,考虑到硬件正在经历的压缩级别,这个主题需要自己的部分。

你必须保持冷静的两个元素是 CPU 和 GPU。

风扇有不同的尺寸。

此外,240/360 毫米风扇配置仅指并排安装 2/3 个 120 毫米风扇。

CPU 冷却

a typical CPUs exposed top-view

Two types of CPU cooler

  • 风扇冷却器
  • 一体式液体冷却

正如你所看到的,液体冷却和风扇一起有一个泵,使水在管子周围循环。有些主板带有单独的 CPU 风扇和泵连接器。它们也可以用于常规风扇端口。在传统的风扇中,这些热量是通过铜管传递给风扇的。这意味着只有一个连接器用于风扇。

两者都有相似的表现,但各有不同。我强烈推荐观看关于这个的 LinusTechTips youtube 视频。

GPU 冷却

1st one is open-air. 2nd is a blower-style config.

GPU 散热是内置的,开箱即用。这两种配置是:

  • 露天冷却器
  • 鼓风机式风扇

Airflow in both the configurations.

因为露天扔在所有方向的空气,并有多达 3 个风扇,他们更适合单 GPU PC,也给更好的超频结果。

这在多 GPU 系统中成为一个问题。一个 GPU 抛出的空气被其他 GPU 消耗,增加了它们的温度,这种情况一直循环下去,直到整个系统上升到非常高的温度。因此,在多 GPU 配置中,吹风机式更好,因为它可以带走电脑机箱中的热量,新鲜空气可以进入 GPU。

liquid cooling hardware on a GPU

液冷是存在的,但这需要打开 GPU 并将其安装到单独的硬件上,这很可怕,也使保修无效,即使有一天你想达到这一水平,也很难在所有国家获得零件。

多 GPU 值得额外付出代价吗?

虽然单个 GPU 可以处理,但大多数情况下温度不会超过 80 度。但是对于多 GPU 系统,冷却成为一个大问题。即使 SLI 桥或 NVLink(现在由 NVIDIA 公司命名)可以将多个 GPU 连接在一起,优化也会受到严重影响。理想情况下,将 2 个 GPU 连接在一起应该可以提供 2 倍的性能,但在大多数情况下,与使用单个 GPU 相比,您最终只能获得 40%的额外提升。这不仅消耗更多的电力,导致更高的电费,而且供暖问题使事情变得更糟。所以,如果你准备好付额外的钱,并且非常需要它,我建议你去试试。

一体式液体冷却:

非常昂贵的一体式液冷存在。部件在大多数国家都不容易买到,而且如果你不确定要放入的电脑外壳的兼容性,购买和安装也有风险。此外,它们可能会在某些时候泄漏,更换可能是一个大问题。总的来说,额外的努力也不值得的性能或价格。

要有多少粉丝?

良好的空气流动是深度学习装备的必备条件。这可以通过进气和排气风扇来实现。但是,极限是什么?

我建议您在前面安装两个进气风扇,在后面安装一个排气风扇。它会给你足够的气流。

在这之后,增加更多的风扇只会使温度稍微下降。LinusTechTips 视频[ 9 ]通过在许多不同的风扇和位置配置中做实验,为我解决了这一切。

重要事项:

确保检查您订购的 CPU 冷却解决方案是否适合主板上的特定支架。例如 AMD Threadripper CPU 使用 TR4 安装支架。

确保使用热敷膏。很奇怪,一个人如何能够通过在笔记本电脑上再次应用热贴来获得显著的提升。Dave2D 的 youtube 视频[10]视频详细展示了统计数据。

确保你把风扇放在正确的位置。安装并打开主板后,务必检查所有风扇的气流方向。

检查主板支持的风扇数量。否则,您可能需要将它们直接连接到 PSU,让它们一直全速运行,而不是通过主板软件来控制它们的速度。

情况

好吧,这可能是个问题。无论你如何小心,有时,电缆可能会稍微短一点,或者 RAM 会妨碍你计划放在机箱顶部的 CPU 散热器。小问题就来了。有些也会让你不好过。一些 PSU 或主板制造商也提供电缆扩展器。如果你想获得一个流畅的构建体验,你也可以观看在线 youtube 构建视频并获得相同的产品。但是在大多数情况下,事情都解决得很好。

但是另一个能提供最好的气流!

在大多数情况下,适当的气流不是问题。这只是一种营销策略,不同的外壳制造商宣传他们如何为组件提供最佳气流。

重要事项:

在极少数情况下,电缆长度可能是个问题。你可以得到扩展器。

有些箱子有可拆卸的风扇。有些给它们预装在其中,有些有可拆卸的风扇。

确保根据您的主板尺寸选择合适的型号。一个给定尺寸的箱子也可以装更小的型号。例如,电子 ATX 案件将支持其较小的版本,如迷你 ATX 或微型 ATX。相应地钻孔。因此,错误地得到一个更大的案件不是问题。尽管如此,有些人还是喜欢看办公桌上的小巧美人。

确保你有一个适合 PSU 的房间。他们有一个单独的 PSU 车厢。如果可能的话,检查一下它的大小。

音频插孔、USB type 2/3、thunderbolt 的前置 IO 均视情况而定。所以一定要根据自己的需求来选择。显然,您可以使用主板上的端口,但它们将位于电脑的背面。

有些机箱仅在顶部安装液体 CPU 冷却器,而有些机箱仅允许将风扇放在前面。确保检查可能的配置。

before and after cable management

有足够的拉链和扎带,便于完美的线缆管理。请记住,线缆管理是一门艺术。

您可以使用 PCpartPicker 的网站[11]查看您选择的所有零件之间的兼容性。

随机存取存储

everything can come with LEDs in them

如果您处理大型数据集,如图像或某种日志数据,您的数据可以完全放在 RAM 中,这有助于显著加快处理时间,因为这是 CPU 在没有将数据放入 L1 或 L2 缓存后使用的内存。对于通常不适合 VRAM 的数据集,在 RAM 和 GPU VRAM 之间进行传输。与任何其他存储解决方案相比,这是非常快的,传输速率约为 20 Gbps。

机器中应该有大量的 RAM,但是如果您有大量的预处理工作要做,那么 8 到 16 GB 就足够了。

与 XMP 或极端的内存配置文件设置,可以超频内存到更高的速度。但实际上,这并不重要。时钟速度为 3000 MHz 的 RAM 比 2400 MHz 的工作速度稍快,但这并不是一个很明显的改进,因此性能价格比非常低。此外,你的 RAM 速度一般不会成为系统的瓶颈,因此 17 Gbps 的传输速度会使 PC 比 20 Gbps 的慢。

重要事项:

确保您使用的 DDR4 RAM 与您的主板兼容。大多数主板制造商也会提供支持的硬件列表。

安装多个 RAM 记忆棒时,不要混用不同的时钟速度和制造商。建议使用完全相同类型的 RAM。

内存插槽号已给定,根据您拥有的内存数量,您必须将其放入各自的插槽中。请参阅主板手册。

这些老丨虎丨机让我想起了当年我们用来购买和玩的游戏盒!!。

(left) a full gaming console. (right) Inside of a gaming cassette

确保你在内存巷回去的时候,眼泪没有掉在主板上。即使在它的顶部做了最后的覆盖电镀,插槽也有线路开放,人类的眼泪含有 0.3 毫克的盐,足以打碎东西。顺便说一下,海水中每一滴含有 1.75 毫克的盐。

程序存储单元(Program Storage Unit)

获得 PSU 时需要注意两件事:

  • PSU 电力公司
  • PSU 港口

对于第一个问题,您需要找出系统的总功耗。对于功耗较小的机器,输出功率较高是可以的,但反之则不行。使用以下公式计算总功耗(瓦特):

n —您希望拥有的 GPU 总数,也包括未来增加的数量。

m——您拥有的硬盘或固态硬盘的总数,也包括未来增加的硬盘或固态硬盘。

额外的 200 瓦用于其他外围设备,并留有安全余量。

你可以很容易地在他们的官方网站上找到每个组件的功率使用情况。

对于第二个,确保提供的插槽数量与您要安装的数量相等。或者简单地添加 PCPartPicker 的网站列表[ 12 ]中的所有部件,您将在最终兼容性部分了解您是否缺少总端口。

PSU 主要有:

  • CPU 插槽:显然是为了 CPU
  • 外设插槽——GPU 和其他东西。
  • SATA 插槽:用于存储解决方案
  • 24 针 ATX 插槽:为您的主板供电

一个好的电源设备是必须的。气流,即使风扇数量较少,也会自行解决,但请确保为您的系统提供清洁和充足的电力。

重要事项:

切勿将转换器插头用于 PSU 插座。适配器与插头轻微接触,会产生大量热量。此外,适配器的材料大多很便宜,并有指定的安培容量,如果超过将烧毁插座。

由于印度的电源插座有 5 安培和 15 安培的支持,对于深度学习钻机,你必须将其放在 15 安培容量的更大插座中。如果你的 PSU 上有 G 型英国插头,最好切断插头并接上你需要的支持更高安培输出的插头,而不是放一个适配器。

由于 15 安培的插头离我的钻机很远,我面临着扩展问题。最后,我去了一个 9 米的额外电缆扩展。我确保延长电线的质量是一流的,因为距离越长,电阻越大,最终电压降越大。仅使用所需厚度的高质量铜线。

显示器和无线键盘

由于我们不做游戏装备,4K 显示器或 144 赫兹刷新率显示器不是我们要找的。

Tim Dettmers 在他的博客中提到,他是如何使用 3 台显示器的,并且非常喜欢。我非常同意他的观点,但是对我来说,我想两台显示器已经足够了。但是,多显示器设置肯定会让你更有效率。

鉴于如今显示器已经变得如此便宜,你可以很容易地选择 LED,而不是 24 或 27 英寸屏幕的 LCD。

键盘和鼠标也是如此。带有 RGB 照明和长按键行程的机械开关的游戏设备是不必要的。

我个人更喜欢笔记本电脑风格的小键盘。此外,无线电话比有线电话稍微贵一点,但是它让环境看起来更干净、更漂亮。如今,无线键盘和鼠标的单个 USB 端口也出现了。

重要事项:

查看 GPU 规格,了解其支持的显示器数量。几乎都支持一个以上。

您可能需要购买一个显示器端口来连接 hdmi/VGA 转换器,以支持多个显示器。检查规格,看看你的 GPU 有多少 HDMI,VGA 或显示端口。

国家政治保卫局。参见 OGPU

这是你深度学习装备的核心。真正训练的地方。这当然是一个大话题,需要一个独立的博客。但是,至少要拿出点东西来,我建议去:

  • RTX 2080 Ti 或
  • RTX 2070(这个不支持 NV link)——便宜很多。

他们有一个 16 位精度选项可以加速。新架构有一些非常好的性能增益。

你也可以通过购买易贝的二手图形处理器来节省一大笔钱。

一辆 GTX 1080 Ti 也是一个很好的选择。此外,不要认为使用旧的会降低性能,这在另一个 LinusTechTips 视频中再次得到了证明。

重要事项:

我强烈推荐查看蒂姆·德特默的成熟博客[ 14 ],他在那里对这个话题做了绝对公正的评价。

我强烈建议只使用 NVIDIA GPUs 进行深度学习,因为 CUDNN 和 CUDA 工具包与目前的深度学习库高度兼容,无论是 Keras、Tensorflow、PyTorch 还是任何其他库。

安装操作系统

深度学习软件首先与基于 Linux 的机器兼容。

我已经安装了 Ubuntu 18.04,因为它现在有 LTS(长期支持),我没有检查在我以前的 16.04 LTS 版本上工作的不兼容的库。但是主要的深度学习库根本不会有任何问题。

拿一台可以工作的笔记本电脑。从 Ubuntu 的官网[ 15 ]下载操作系统,如果可能的话别忘了捐款支持。使用像 Rufus[ 16 ]这样的免费软件创建一个可启动的笔式驱动器,将其插入端口并启动您的电脑。

你会看到 BIOS。一般是删除按钮或者某个 Fn 按钮。检查所有连接的组件,看看是否一切都被检测到。

您可能需要优先选择连接的 USB 进行引导,以确保可引导磁盘得到加载。

按照说明安装 Ubuntu。

在这段 youtube 视频中可以看到这整个过程[ 17 ]。

最后的想法

最后,这是一个有趣和令人兴奋的过程,你一定会喜欢的。如果你过去没有造过机器,那也没关系。没什么复杂的。硬件社区为您提供了全面的保护。现在事情非常模块化。还有一些网站可以让你看到所有部件的兼容性,比如 PC Part Picker[ 18 ]。你可以随时在 Bitwit[ 19 ]等频道参考 youtube 上充满硬件构建视频的视频,看看如何做到这一点,顺便说一句,当涉及到生活时,观看它是纯粹的幸福。

感谢你的阅读,祝贺你坚持到最后,感谢桑德普·T·T21 编辑了这篇博客。下次见,爱 u 3000:)

参考

[1]medium.com,陈明杰,为什么建造自己的深度学习计算机比 AWS (2018)便宜 10 倍

[2]詹妮弗·维拉,选择你的深度学习基础设施:云与内部辩论 (2018),determined.ai

[3] 预构建 vs 构建自己的深度学习机器 vs GPU 云(AWS) (2018),bizon-tech.com

[4] 云与内部部署:深度学习哪个更好?(2018) ,exxactcorp.com

[5] Powercert 动画视频,Youtube.com m . 2 NVMe 固态硬盘讲解— M.2 vs 固态硬盘 (2018)

[6] 英特尔 Optane 技术,Intel

[7]蒂姆·德特默斯,深度学习的完整硬件指南 (2018),TimDettmers.com

[8] Linus Tech Tips,为什么你不应该用水冷却你的电脑 (2019),Youtube.com

[9] Linus Tech Tips, Case 粉丝——你应该有多少? (2015),Youtube.com

[10]戴夫·李, $12 Hack 提升你的笔记本电脑性能! (2017),Youtube.com

[11] 完成建造【pcPartPicker.com

[12] 系统建造者,pcPartPicker.com

[13] Linus Tech Tips,性能下降—这是真的吗? (2016),Youtube.com

[14] Tim Dettmers,深度学习需要哪些 GPU:我在深度学习中使用 GPU 的经验和建议 (2019),TimDettmers.com

Ubuntu.com Ubuntu 桌面下载 18 . 04 . 2

[16] Rufus ,Rufus.ie

[17] LinuxPlus,如何安装 Ubuntu 18.04 Youtube.com LTS(2018)

[18] 建造指南,pcPartPicker.com

【19】bit wit,如何搭建 PC!步步为营 (2017),Youtube.com

[20] 了解 Kingston.com NVMe 和固态硬盘技术

如何用 python 轻松创建自己的问答系统

原文:https://towardsdatascience.com/how-to-create-your-own-question-answering-system-easily-with-python-2ef8abc8eb5?source=collection_archive---------1-----------------------

如何使用 cdQA-suite 在您自己的(私人)数据上创建 QA 系统

机器理解的历史起源于人工智能中第一个概念的诞生。聪明的艾伦·图灵在他的著名文章《T2》中提出了计算机器和智能“现在被称为图灵测试作为智能的标准。近 70 年后,问答(QA)仍然是人工智能中最困难的任务之一,它是 MC 的一个分支。

然而,自去年以来,由于深度学习研究的发展和迁移学习技术的出现,自然语言处理领域经历了快速的发展。强大的预先训练的 NLP 模型,如 OpenAI-GPT 、 ELMo 、 BERT 和 XLNet 等,均由该领域的顶尖研究人员提供。

随着这些进步,一些改进的系统和应用程序将会出现。其中一个系统是 cdQA-suite ,这是我和一些同事在法国工程学院巴黎电信和欧洲个人理财领导者法国巴黎银行的合作下开发的一个软件包。

开放域质量保证与封闭域质量保证

当我们考虑 QA 系统时,我们应该知道两种不同的系统:开放域 QA (ODQA)系统和封闭域 QA (CDQA)系统。

开放域系统几乎可以处理任何问题,并且只能依赖于一般的本体和世界知识。这样一个系统的一个例子是 DrQA ,一个由脸书研究公司开发的 ODQA,它使用维基百科的大量文章作为它的知识来源。由于这些文件涉及几个不同的主题,我们可以理解为什么这个系统被认为是一个 ODQA。

另一方面,封闭领域系统处理特定领域下的问题(例如,医学或汽车维修),并且可以通过使用适合唯一领域数据库的模型来利用特定领域的知识。cdQA 套件的构建是为了让任何想要构建封闭领域 QA 系统的人都能轻松完成。

cdQA 套件

[## cdQA

一个端到端的封闭领域问答系统。- cdQA

github.com](https://github.com/cdqa-suite)

cdQA 套件由三部分组成:

  • cdQA :一个易于使用的 python 包,用于实现 QA 管道
  • cdQA-annotator :一个为模型评估和微调方便问答数据集注释的工具
  • cdQA-ui :一个可以耦合到任何网站并可以连接到后端系统的用户界面。

我将解释每个模块是如何工作的,以及你如何使用它在你自己的数据上建立你的 QA 系统。

cdQA

cdQA 架构基于两个主要组件:检索器和阅读器。你可以在下面看到系统机制的示意图。

Mechanism of cdQA pipeline

当一个问题被发送到系统时,检索器在数据库中选择最有可能包含答案的文档列表。它基于与 DrQA 相同的检索器,该检索器基于一元语法和二元语法创建 TF-IDF 特征,并计算问句与数据库中每个文档之间的余弦相似度。

在选择了最有可能的文档后,系统将每个文档分成段落,和问题一起发送给读者,这基本上是一个预先训练好的深度学习模型。使用的模型是著名的 NLP 模型 BERT 的 Pytorch 版本,由 HuggingFace 提供。然后,阅读器在每段中输出它能找到的最可能的答案。在阅读器之后,系统中还有最后一层,它通过使用内部得分函数来比较答案,并根据得分输出最可能的答案。

使用 cdQA python 包

在开始使用这个包之前,让我们安装它。您可以使用pip来安装它,或者从源代码中克隆存储库。对于本教程,我还将下载法国巴黎银行的数据集(一个从他们的公共新闻网页上摘录文章的数据集)。

# Installing cdQA package with pip
pip install cdqa# From source
git clone [https://github.com/cdqa-suite/cdQA.git](https://github.com/cdqa-suite/cdQA.git) &&
cd cdQA &&
pip install .

现在,您可以打开 jupyter 笔记本,按照下面的步骤来查看 cdQA 是如何工作的:

您应该有如下输出:

The output of a QAPipeline prediction

您可以注意到,系统不仅输出一个答案,还输出找到答案的段落以及文档/文章的标题。

在上面的代码片段中,需要预处理/过滤步骤来将 BNP Paribas 数据帧转换为以下结构:

Structure of the Dataframe that should be sent to cdQA pipeline

如果您使用自己的数据集,请确保您的数据框架具有这样的结构。

当使用模型的 CPU 版本时,每个预测需要 10 到 20 秒才能完成。这个适中的执行时间是由于 BERT 阅读器,这是一个非常大的深度学习模型(约 110M 参数)。如果你有 GPU,可以直接用型号models/bert_qa_vGPU-sklearn.joblib的 GPU 版本。这些预先训练好的模型也可以在 cdQA github 的发布页面上找到:https://github.com/cdqa-suite/cdQA/releases

培训/微调读者

您还可以提高预训练阅读器的性能,该阅读器在 SQuAD 1.1 数据集上进行了预训练。如果您有一个注释数据集(可以在 cdQA-annotator 的帮助下生成),其格式与小队数据集相同,您可以在其上微调阅读器:

# Put the path to your json file in SQuAD format here
path_to_data = './data/SQuAD_1.1/train-v1.1.json'cdqa_pipeline.fit_reader(path_to_data)

请注意,这种微调应该使用 GPU 来执行,因为 BERT 模型太大,无法用 CPU 来训练。

你也可以在官方教程中找到其他方法来完成同样的步骤:https://github.com/cdqa-suite/cdQA/tree/master/examples

cdQA-注释器

为了方便数据注释,团队构建了一个基于 web 的应用程序,即 cdQA-annotator 。

为了使用它,您应该将您的数据集转换为一个 JSON 文件,格式类似于 SQuAD:

from cdqa.utils.converters import df2squad# Converting dataframe to SQuAD format
json_data = df2squad(df=df, squad_version='v1.1', output_dir='.', filename='dataset-name.json')

现在您可以安装注释器并运行它了:

# Clone the repo
git clone https://github.com/cdqa-suite/cdQA-annotator# Install dependencies
cd cdQA-annotator
npm install# Start development server
cd src
vue serve

现在,您可以转到 http://localhost:8080/ ,在加载您的 JSON 文件后,您将看到如下内容:

cdQA-annotator interface

要开始注释问答配对,您只需写下一个问题,用鼠标光标突出显示答案(答案将自动写出),然后点击Add annotation:

Annotating question-answer pairs with cdQA-annotator

注释完成后,您可以下载它,并使用它根据您自己的数据对 BERT 阅读器进行微调,如前一节所述。

cdQA-ui

该团队还提供了一个基于 web 的用户界面来耦合 cdQA。在这一节中,我将描述如何使用链接到cdQA后端的 de UI。

首先,您必须通过在您的 shell 上执行来部署一个cdQA REST API(确保您在cdQA文件夹上运行它):

export dataset_path=path-to-dataset.csv
export reader_path=path-to-reader-modelFLASK_APP=api.py flask run -h 0.0.0.0

其次,您应该继续安装 cdQA-ui 包:

git clone [https://github.com/cdqa-suite/cdQA-ui](https://github.com/cdqa-suite/cdQA-ui) &&
cd cdQA-ui &&
npm install

然后,启动开发服务器:

npm run serve

您现在可以在 http://localhost:8080/ 上访问 web 应用程序。您将看到类似下图的内容:

Web application of cdQA-ui

由于应用程序通过 REST API 很好地连接到后端,您可以提出一个问题,应用程序将显示答案、找到答案的段落上下文以及文章的标题:

Demonstration of the web application running

在网站中插入界面

如果你想在你的网站上连接界面,你只需要在你的 Vue 应用程序中导入以下内容:

import Vue from 'vue'
import CdqaUI from 'cdqa-ui'Vue.use(CdqaUI)import Vue from 'vue'
import BootstrapVue from "bootstrap-vue"Vue.use(BootstrapVue)import "bootstrap/dist/css/bootstrap.css"
import "bootstrap-vue/dist/bootstrap-vue.css"

然后插入 cdQA 接口组件:

演示

你也可以在官方网站上查看该应用的演示:https://cdqa-suite.github.io/cdQA-website/#demo

结论

在本文中,我介绍了cdQA-suite,这是一个用于部署端到端封闭领域问答系统的软件套件。

如果你有兴趣了解更多关于这个项目的信息,可以随时查看官方的 GitHub 库:https://github.com/cdqa-suite。如果您喜欢这个项目,并且认为它对您和您的应用程序有价值,那么请不要犹豫开始并跟踪这个库。

我们最近发布了 1.0.2 版本的cdQA包,它是高性能的,显示了非常有希望的结果。然而,仍有改进的余地。如果你希望对这个项目有所贡献,并有助于这些改进,你可以看看我们目前的问题:https://github.com/cdqa-suite/cdQA/issues。请随意选择一个并进行拉取请求:)。

干杯!

来源:

  • GitHub 上的 cdQA 套件库:https://github.com/cdqa-suite
  • 来自谷歌的官方 BERT 版本:https://github.com/google-research/bert
  • 拥抱脸的 Pytorch 版伯特:https://github.com/huggingface/pytorch-pretrained-BERT
  • 阵容数据集:https://rajpurkar.github.io/SQuAD-explorer/
  • https://github.com/facebookresearch/DrQA/脸书研究公司的 DrQA:
  • DeepPavlov,一个拥有开放域 QA 系统的库:https://medium . com/DeepPavlov/Open-Domain-question-answering-with-DeepPavlov-c 665 D2 ee 4d 65
  • https://openai.com/blog/better-language-models/
  • https://allennlp.org/elmo
  • XLNet:https://arxiv.org/abs/1906.08237

如何在谷歌助手上创建你的个人习惯跟踪器

原文:https://towardsdatascience.com/how-to-create-your-personal-habit-tracker-on-google-assistant-a15fb304c561?source=collection_archive---------19-----------------------

一个程序员为所有程序员设计的跟踪你的习惯的最懒的方法!

序言

在很长一段时间里,我一直试图在日常生活中加入新的习惯。我尝试了各种应用程序、纸张模板等。但是都不好用。我通常会忘记填充它们,或者觉得这样做太累了。最近,我得到了一个新的谷歌 nest mini,睡觉前用它聊天很有趣。所以,我想为什么不让谷歌助手帮我追踪我的习惯。

它是如何工作的

我:“嘿谷歌,跟习惯追踪器聊聊”
助手:“获得习惯追踪器的测试版”
习惯追踪器:“你今天锻炼了吗?”
我:“是”
……更多问题……
HabitTracker:“你看了什么论文吗?”
我:“没有”
HabitTracker:“我问了我所有的问题”
之后,在我的“习惯”google sheet 中插入新的一行:

Nothing feels better than filling a spreadsheet with your voice!

如何创造你自己的

本教程我们要做的:
1。创建一个 Google 表单并添加您自己的问题
2。创建一个可以编辑您的工作表
3 的服务。设置您的 Dialogflow 项目
4。和你的习惯追踪者谈谈

您需要一些基本的编程知识和一个 Google 开发人员帐户来完成这个演练。如果您想修改代码的某些部分,了解一点 Dialogflow 概念是有益的。完成演练大约需要一个小时。

1.创建您的谷歌表单

我用来填充 google 表单的脚本有一些假设,您应该遵守:

  • 为时间保留第一列
  • 保留前两行提问

你基本上可以复制这张表并添加你自己的问题。为后面的步骤保存您的电子表格键。

2.创建用于编辑工作表的服务

现在,您需要创建一个 google 服务帐户,并与它共享此文档。查看本节教程。经过这一步,你应该有你的client_emailprivate_key

3.设置您的 Dialogflow 项目

Dialogflow 是用于创建对话机器人的谷歌服务。我们需要设置它,并将其连接到我们自己的 web 服务,以使事情正常工作。你需要在 Dialogflow 中上传我的 GitHub 项目中的一些文件,这些文件可以直接从这里下载。

  1. 首先,您需要创建一个新项目。
  2. 从左侧菜单,转到实体部分并上传是-否实体。实体是 Dialogflow 可以从对话中检测到的概念,并将其传递给我们的服务。
  3. 从左侧菜单中,转到 intents 部分并删除默认的欢迎意图。然后,上传动态意图。
  4. 从左侧菜单,进入完整菜单,并启用行内编辑器。将中的index.js内容复制到中,将中的package.json内容复制到中,并粘贴到它们的标签页中。现在你应该修改index.js并添加你自己的配置。这基本上是代码的前 3 行。
    所有的逻辑都在里面index.js它创建一个 Dialogflow 应用程序来处理请求,它连接到 google 电子表格,读取问题,并在所有问题都得到回答时添加一个新行。
  5. 部署您的功能!可惜,这不是结局。Firebase 函数不允许您向测试计划中的其他服务发出请求。你也必须升级你在 Firebase 的计划。Blaze 计划几乎是免费的,因为你的函数每天被调用的次数不会超过几次。

4.测试一切

在 Dialogflow 的右边部分,你可以通过说或输入“跟踪我的习惯”来开始与你的习惯跟踪器对话。你可以检查 Firebase 函数日志,看看是否一切顺利。最后,你可以直接在谷歌助手上测试它,只需点击“查看它如何在谷歌助手上工作”链接,然后从那里将你的机器人部署到你的所有设备上。

收场白

我用谷歌助手追踪我的习惯已经有 10 天了,感觉真的比其他方法好。首先,我有更多的动力去做我的习惯,因为当谷歌助手询问我的习惯时,对它说“是”的感觉真的很好;不知何故,这和我小时候老师问我有没有做作业的时候很像。说好的时候感觉真的很好,说不的时候感觉很丢人
第二,真的很简单,不打扰你睡觉。你不需要看着屏幕,你不需要你旁边的手机或者纸和笔。
最后但并非最不重要的一点是,数据保存在谷歌表单上的感觉真的很好。我可以随心所欲地处理我的数据,任何第三方都无法访问。这对于纸质习惯跟踪器和没有导出功能的第三方应用来说都不容易。

希望你喜欢我的文章和快乐习惯追踪!

如何在分析中避开 SQL 中间人

原文:https://towardsdatascience.com/how-to-cut-out-the-sql-middle-person-in-analytics-9687d640cecc?source=collection_archive---------12-----------------------

不断地为您的客户手动执行 SQL 查询?这里有一个让他们自助的方法。

我目前的人生目标之一是帮助数据分析师削减他们工作中无聊、麻木的方面,以便他们可以专注于更有趣、有用和酷的东西。

我在分析团队中看到的一种常见情况是,分析师扮演了一个不必要且高度重复的中间人角色,即业务用户反复需要某些特定数据,而由分析师手动执行这些重复的 SQL 查询来提取数据并将其发送给客户端。相同或非常相似的查询,一次又一次。不好玩。实际上在今天的技术下完全没有必要。

我爱 R 生态系统。我喜欢它的原因之一是因为它可以让你轻松地做一些神奇的事情,将数据源与基于 web 的交互联系起来。在这篇文章中,我将向您展示如何使用 R Shiny 建立一个简单的 web 应用程序,它将允许您的非技术专业客户从 SQL 数据库中选择他们想要的原始数据,并将其提取和下载到 Excel 电子表格中。这是去掉中间人的安全方法,因为您可以控制谁可以访问 Web 应用程序,以及允许它从数据库中检索哪些数据。

我将在这里使用一个简单的场景来说明这些概念,但是这个想法可以扩展到能够向您的客户端提供大量可下载的预处理数据。

你需要什么

  1. r 安装了shinydplyropenxlsxrmarkdownodbc包。
  2. 您希望从中检索特定数据的 SQL 数据库。在本文中,我将假设它是一个 Oracle SQL 数据库。
  3. RStudio Connect 文档/应用托管平台,或至少访问一个闪亮的服务器。

我们的简单示例场景

让我们假设你是一家连锁兽医诊所的数据分析师。每天您都会收到一些关于预约和预约取消的数据请求。我们会问两个问题:在这几年中,我们为每种动物预约了多少次?其中有百分之多少被取消了?您已经厌倦了一次又一次地使用相同的 SQL 查询来回答这些问题。

您的约会数据库表称为APPTS_DB,它有许多列,特别是DATE(格式为DD-MMM-YYYY,例如01-MAR-2017)、ANIMAL_TYPE(例如CatDog)、CANCEL_FLAG(如果约会被取消,则为二进制1,否则为0)。

我假设你知道闪亮应用的结构。在这篇文章中,我将把这个闪亮的应用写成一个交互式 R markdown .Rmd文档。有关这方面的更多信息,请参见此处。

步骤 1:将您的 SQL 查询转换成 R 中的函数

将常用的 SQL 查询转换成 R 函数确实是一个好主意,即使您在本文中没有做任何其他事情。它允许您在 R 会话中用一个命令执行常见的查询。

为了将这一点构建到您的应用程序中,这一步可以在一个单独的 R 脚本中完成,您可以将其加载到您闪亮的应用程序中,或者它可以作为应用程序本身的代码块来完成。我们假设是后者。

首先,我们建立一个到数据库的连接。如果您打算将代码存储在 Github 或其他任何可能被他人看到的地方,我建议将您的凭证放在系统环境中。

``` {r db_connect}db_conn <- odbc::dbConnect(odbc::odbc(), dsn = Sys.getenv("DSN"), # <- databaseuid = Sys.getenv("UID"), # <- user idpwd = Sys.getenv("PASS")) # <- password```

首先,我们用占位符编写 SQL 查询,然后使用gsub() 用函数参数替换占位符,然后运行查询。我们希望设置它来提取从指定的起始年到结束年的时间段内按动物类型的约会总数,并计算取消率。理想情况下,我会建议您使用dbplyr以整洁的形式完成这个查询,但是我在这里将使用原始 SQL 来完成,因为大多数读者对此都很熟悉。

``` {r query_fn}# create query functionappt_query <- function (start_yr, end_yr) {# write query with placeholders qry <- "SELECT ANIMAL_TYPE, COUNT(*) NUM_APPTS, SUM(CANCEL_FLAG)/COUNT(*) PERC_CANCELLEDFROM APPTS_DBWHERE EXTRACT(YEAR FROM DATE) BETWEEN start_year AND end_year          GROUP BY ANIMAL_TYPEORDER BY ANIMAL_TYPE"# replace placeholders with function arguments qry <- gsub("start_year", start_yr, qry)qry <- gsub("end_year", end_yr, qry)# execute query odbc::dbGetQuery(db_conn, qry)} ```

这非常强大,因为它允许使用简单的命令如appt_query(2015, 2017)获取信息。您也可以使用一个简单的paste()函数将 SQL 查询粘贴在一起,但是我发现使用gsub()更容易管理和检测错误。

步骤 2:设置闪亮的应用程序输入和下载按钮

现在,我们为最终用户设置了一些简单的输入,以及一个下载按钮,他们将按下该按钮来执行查询并下载他们需要的数据。

在这个简单的例子中,只需要用户输入起始年份和结束年份。我们将从 2010 年开始我们的年度期权,到今年结束

``` {r user_input}# get current yearcurr_year <- format(Sys.Date(), "%Y")# set up panel to select start and end yearsmainPanel(HTML("<br>"),selectInput("start_yr", "Select start year:",choices = c(2010:curr_year)),selectInput("end_yr", "Select end year:", choices = c(2010:curr_year)),HTML("<br>"),uiOutput("downloadExcel")
)# generate download button confirming the input selectionoutput$downloadExcel <- renderUI(downloadButton("downloadData", paste("Download Data for", input$start_yr, "to", input$end_yr, "in Excel"))
)```

这将创建一个带有下载按钮的用户输入面板,确认所选择的年份。这个 download 按钮将链接到一个名为downloadData的服务器进程,在这里我们将执行查询并写入一个 Excel 文件供用户下载。

步骤 3:编写后台代码来执行查询和下载数据

现在我们编写服务器进程来执行查询和下载数据。这变得更简单了,因为我们设置了一个简洁的函数来执行查询(参见步骤 1)。我们还将建立一个整洁的进度条,以便用户可以看到该进程是如何进展的。对于一个可以立即完成的简单查询来说,这是不必要的,但是如果您正在使用许多不同的查询构建一个多选项卡的电子表格,那么它是必不可少的,以便让用户确信正在发生一些事情。

``` {r query_and_download}# use downloadHandleroutput$downloadData <- downloadHandler(# give download file a name   filename = function() {paste0("animal_appt_data_", input$start_yr, "_", input$end_yr, ".xlsx")},# download and populate excel file content = function(file) {# create progress bar for user with first stepshiny::withProgress(min = 0,max = 1,value = 0,{shiny::incProgress(amount = 1/2,message = "Retrieving data from database...")# get data using function data <- appt_query(input$start_yr, input$end_yr)# set up an excel file in a tab called "Appointment Data" shiny::incProgress(amount = 1/2,message = "Writing to Excel...") wb <- openxlsx::createWorkbook()openxlsx::addWorksheet(wb, "Appointment Data") # design a nice header style so the results look professional hs1 <- openxlsx::createStyle(fontColour = "#ffffff", fgFill = "#4F80BD",halign = "left", valign = "center", textDecoration = "bold",border = "TopBottomLeftRight", wrapText = TRUE)# write the results into the "Appointment Data" tab with a nice border openxlsx::writeData(wb, "Appointment Data", x = data,startRow = 1, startCol = 1, borders = "surrounding",headerStyle = hs1)# save Excel file and send to download openxlsx::saveWorkbook(wb, file, overwrite = TRUE) } # <- end progress bar 
) # <- end withProgress})  # <- close content wrapper and downloadHandler function```

步骤 4:向客户端提供访问权限

使用这种方法,客户端只能访问您为其设计的数据。如果您使用 RStudio Connect 共享平台,您可以将其发布为应用程序,并仅向特定个人或群组提供访问权限,确保只有授权的客户端才能访问。如果您使用 Shiny Server Pro,请从用户文档中寻求如何控制用户访问的建议。

结论和延伸

如果你是一个流利的闪亮的用户,你可能会立即掌握这里发生了什么。如果没有,你可能需要更多的培训,在你接受这个之前。这种方法可以扩展到非常强大。仪表板可以使用ggplot2plotly来设计,而不是——或者除了——Excel 下载。像asyncfuturepromises这样的包可以用于使用异步编程的多个并发用户的伸缩(更多信息见这里)。在最高级的情况下,可以使用这里介绍的初始概念在 Shiny 上构建和托管一个完整的灵活的商业智能平台。

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedInTwitter上找我。

如何应对冒名顶替综合症

原文:https://towardsdatascience.com/how-to-deal-with-imposter-syndrome-c5f7694817bf?source=collection_archive---------23-----------------------

诀窍?把冒名顶替综合征当做优点,而不是缺点。

Photo by Shuto Araki on Unsplash

我第一次走进人工智能聚会时,我觉得我不应该在那里。

第二次走进一个机器学习的活动,我觉得我不应该在那里。

当我第 20 次走进一个人工智能聚会时,我觉得我不应该在那里。这是在做了一年机器学习工程师之后。

但还是有所不同。第一次和第二十次的区别。

除了实地经验外,我还有实践经验。我参加过很多活动,我知道那种感觉会在那里,我越来越擅长处理它。我用它作为动力。提升自己的动力。

我意识到其他人可能也有同样的感受。我会对自己说,我们来这里都是有原因的,我们来这里都是为了学习,我们来这里都是因为我们对相似的东西感兴趣。

问题是,这个过程,冒名顶替的感觉,不会止于事件。到处都有。

当我开始在网上写文章时,我害怕点击发表按钮。

当我写一个关于我生活的故事时,我问自己,谁会想读这个?

当我走进政府大楼,编写我在网上学会的数据科学代码时,我觉得我不应该在那里。

当我开始在我的卧室里制作视频时,同样的事情。谁会想看这个?

我。

就是他。我想要阅读这篇文章。我希望看到我的代码被很好地使用。我想要去参加这个活动。我想在 20 年后看这个视频,以此来提醒我从哪里开始。

你可能会把冒名顶替综合症视为一种弱点。我曾经。不再是了。现在我认为这是我最大的优势之一。

最大的优势?

通常,价值来自于发现它的弱点并找出它的反面。

冒名顶替综合症可能是你最大的优势,因为它意味着你意识到了自己的能力。这意味着你意识到你可以改进。因为你意识到了这一点,如果你以正确的方式去做,你就会进步。

冒名顶替综合症可能永远不会消失。但是你会更好地处理它。

而不是让冒名顶替综合症阻碍我。我用它来推动我前进。

如果我承担了编写代码的责任,它最好运行良好。

如果我承担了发表文章的责任,它们最好值得一读。

如果我承担了制作视频的责任,它们最好值得一看。

我告诉自己。

你不是骗子,你就是你。

你也应该这样做。

如何处理嘈杂人群中的异常值?

原文:https://towardsdatascience.com/how-to-deal-with-outliers-in-a-noisy-population-736d7a048199?source=collection_archive---------26-----------------------

定义异常值可能是一项简单的任务。另一方面,决定如何处理它们总是需要一些更深入的研究。

动机

数据可能会有噪音。当你有一个小的(相对于人口规模),随机样本的人口,尤其是嘈杂的人口,它可以是一个相当大的挑战,如果不是不可能的,建立一个模型,将概括得很好。

假设您构建了一个简单的线性模型,该模型对您的数据表现不佳。然后,您决定计算学生化残差,并移除超出特定范围的所有观察值。因此,您的模型更符合数据。最后,你把它投入生产,这是一场噩梦。

噪声数据并不罕见,它会极大地影响您的发现。知道如何识别和如何处理对任何准确的发现都很重要。模拟是帮助我们探索和更好理解这个问题的一个很好的工具。

模拟异常值和简单的线性模型

如果你还没有,你应该建立自己的模拟。这是巩固你从统计教科书或课程中学到的知识的好方法。您可以尝试从头开始创建示例,甚至可以随意修改。

为此,我喜欢使用 Rstudio。比方说,我们正在就二手车相对于里程数的定价向二手车经销商提供建议。让我们假设这两个变量的大小为 100,可以使用简单的线性回归很好地建模。我将用以下系数定义真实人口回归线:

b0 <- 21345
b1 <- -0,1349

让我们通过从均值为 76950.45、标准偏差为 16978.58 的正态分布中取样来创建独立变量里程:(这些值是根据可用的数据集选择的,此处为。)

mileage <- rnorm(n = 100, mean = 76950.45, sd = 16978.58)

接下来,我将引入带有随机误差项的噪声。我将从标准偏差等于 500 的正态分布中对其进行采样,并且我将更改单个值以创建合适的异常值。

eps <- rnorm(n = 100, mean = 0, sd = 500)
eps[81] <- 15000

通过改变这个单一值,随机误差项标准偏差增加了三倍:

> sd(eps)
[1] 1586,312

因变量的时间:

price <- (b0 + b1*mileage + eps)

让我们绘制数据:

Figure 1: Scatter plot of mileage versus price showing the true regression line in black, the least-squares line in blue and two outliers colored yellow and red.

我们可以清楚地看到图 1 中的两个异常值。其余里程值方面,两者都有不寻常的值。两者都是高杠杆点。但是,如果我们只去掉红点,我们会发现它是唯一有影响的点:

Figure 2: Scatter plot after the removal of the influential point. Although the yellow point is influencing the least-squares line by decreasing its slope, its influence is so small it can be ignored.

如果我们比较这两个模型的统计数据,我们可以看到一些非常不同的值。例如,在我们去除影响点之后,剩余标准误差从 1518 下降到 514,这分别非常接近误差项标准偏差的实际值 1586 和 500。

这是两个残差图:

Figure 3: Left: Scatter plot of the residuals before removing the influential point. Right: Scatter plot of the residuals after removing the influential point.

我们在本例中没有看到但应该提到的一点是,有时不影响最小二乘方线的异常值可能具有较大的残差。这仍然是一个问题,因为正如我们在上面看到的,一个大的残差会产生一个大的残差标准差,我们用它来确定置信区间和 p 值。

解决示例问题

现在我们需要决定是否要完全移除影响点。对这个问题要格外小心。你需要一个非常好的理由来删除它。如果我们观察这两个模型的 R 平方,我们会看到很大的不同。具有影响点的模型具有大约 60%的 R 平方,而当影响点被移除时,R 平方为 95%。这种差异可能看起来是删除的一个足够好的理由,但就其本身而言,它不是。

为了更好地理解这一点,我们需要了解一个经常被忽视的简单事实。我们的目标不是预测过去,而是预测未来。上述数据的小窗口由 100 个单独的观察值组成。在该窗口上计算的每个统计量都是真实总体统计量的点估计。简单的线性回归确实擅长捕捉窗口内两个变量之间的关系,但不一定能捕捉到窗口外的关系。在使用你的模型进行推断时,你应该非常小心。当我们从这两个模型中选择一个时,我们实质上是对总体做了一个假设。没有影响点 RSE 的模型小三倍。这意味着 95%的置信区间将缩小三倍。本质上,我们的预测会更有信心。数据中没有任何东西告诉我们可以对人口做出如此自信的假设。为了了解种群的样子,我们需要做一些研究。与模拟不同,我们永远不会知道真实的人口统计是什么样子。所以我们需要一个想法,我们需要对人口进行假设。

让我们想象一下,我们明显的目的地是我们的客户,汽车拍卖商。车主告诉我们,这辆车是一辆不寻常的旧车,吸引了一小群非常想要它的买家的注意。他们相互竞价,把价格抬得异常高。此外,老板向我们保证,这是该公司 20 多年历史中唯一的一次,不会再发生了。他们处理普通的日常车辆。

有了这些知识,我们回到我们的模型,自信地去除异常值。就模型统计而言,这意味着我们确信模型的剩余标准误差为 514,这进一步意味着我们可以假设真实误差项标准偏差接近该数字(因为数据是模拟的,所以我们知道它等于 500)。如果我们想得到正确的其他点估计,这个人口估计是至关重要的。

如果所有者不是如此自信,我们就不应该决定移除异常值。相反,我们可以探索二手车市场,并试图找到真实误差项标准差的外部估计。如果我们的模型,或者任何其他的模型,忽略了我们不能确信在生产中不会发生的极端值,那么它在投入生产时会表现很差。剔除不当的异常值会导致过于自信的估计。

结论

忽略或删除异常值是很诱人的。没有非常好的理由不要做它。总是做外部研究,以便找到假设的真实人口统计数据。这可能是说起来容易做起来难。

在这个例子中,真实世界不像模拟数据那样容易理解。尽管如此,我认为这个例子应该作为进一步研究的动力。它应该激励你去解决一个现实世界的问题,不仅仅是用一个数学公式来决定你的数据中哪些离群值应该被删除,而是去实验和假设真实的人口统计数据。只有深入了解总体情况,才能回答要剔除哪些异常值的问题。

参考

戴维·M·迭斯、克里斯托弗·D·巴尔(2015 年)。统计学第三版。openintro.org

加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼(2017)。统计学习导论及其在 r。

阿里尔·马尔登(2018)。模拟!模拟!—第 1 部分:线性模型。

安德鲁·盖尔曼,约翰·卡林(2014)。超越功率计算:评估 S 型(符号)和 M 型(幅度)误差(2014)。心理科学透视第 9 卷第 6 期 641-651 页。

布兰登·福尔茨(2019)。统计学 101:线性回归、异常值和有影响的观察。

深度学习时代如何应对不确定性

原文:https://towardsdatascience.com/how-to-deal-with-uncertainty-in-the-era-of-deep-learning-977decdf84b5?source=collection_archive---------16-----------------------

TensorFlow 在深度学习社区中引入了概率建模

Photo by Hossein Soltanloo on Unsplash

最近,每天都有新的出色的机器学习应用发布,很可能是由一些深度学习模型驱动的。在表面之下,成千上万的公司将相同的技术应用于各种不同的过程。最迟当它支持关键决策时,你应该考虑每一个预测的确定程度。我们将解释为什么会这样,如何定义不确定性,并最终查看一些代码示例,以便您能够在下一个项目中应用我们的发现。

特洛伊斑马的故事

我们来做一个思维实验。假设你是一家组织旅行的公司,你想为客户的冒险创造一个更安全的体验。作为一名机器学习工程师,你的目标可能是创建一个图像分类器,将周围的动物标记为“潜在危险”或“可能无害”。这个程序会让顾客感到安全,并在必要时给予他们预防措施。

幸运的是,一个月前你在所有的车上安装了摄像头,这样你现在就有了大量斑马、蛇、长颈鹿等的图像。你马上开始训练你的神经网络。初步评估显示,您的模型运行得相当好,可以检测出各种潜在危险的蛇和无害的斑马。

“那太好了”,你想,“但是如果我在实践中使用这个模型,而一只在数据中被低估甚至完全不存在的动物出现在我的相机前,那该怎么办?”

这个模型被迫在两个可能的结果中选择一个,尽管它实际上没有任何线索。进一步想象一下,在这种情况下,(几乎)未知的动物是一只老虎。由于某些相似性(条纹、四条腿等),模型可能会在其内部表示中定位照片。)更接近斑马,而不是捕食者,因此错误地分类了情况。

Photo by Smit Patel on Unsplash

如果模型能够传达其不确定性,并且因为您主要对客户的安全感兴趣,您可以校准您的系统,以便在有疑问时做出防御性反应,这不是很好吗?

预测不确定性有许多原因,但从我们的建模角度来看,基本上可以归结为两类。最简单的方法是把它看作与数据和模型相关的不确定性。

任意不确定性

前者可能是更明显的一个。每当你在相同的环境下进行多次测量时,每次都不可能得到完全相同的结果。这是为什么呢?原因有几个:如果你用的是传感器,每个设备本身都有它的准确度、精密度、分辨率等。在手动实验室样本的情况下,所使用的技术、个人技能和扮演其角色的经验。基本上,测量的每个方面都是未知的,因此会引入某种随机性,这属于这一类。

如果你能够减少随机的不确定性,取决于你对收集数据的方式有多大的影响力。

认知不确定性

既然我们已经涵盖了数据中的不确定性,那么模型呢?这不仅仅是模型解释给定数据的能力的问题,而是数据包含所有已知信息的确定程度的问题。看待认知不确定性的另一种方式是衡量一个(无限的)模型集合对结果的认同程度。如果多个模型得出严重偏离的结论,这些数据显然没有描绘出全貌。

例如,试图拟合复杂函数的简单模型、太少或缺少数据等都可能导致认知上的高度不确定性。这就是你作为建模者的经验可以大放异彩的地方。是不是缺少了一个重要的特性?在你的训练数据中,有没有代表不足的情况?你选对型号了吗?

实用的方法

由于两种类型的不确定性在所有预测中都不是恒定的,所以我们需要一种方法来为每个预测分配特定的不确定性。这就是新的 TensorFlow Probability 软件包介入拯救世界的地方。它提供了一个框架,将概率建模与我们钟爱的深度学习模型的能力相结合。

chart 1: example data

为了演示的目的,我们将采取一个非常简单的回归问题,只有一个输入和一个输出维度。训练数据的两个 blobs 在它们的标准偏差方面不同,并且在它们之间是我们没有任何数据的空间。模型能够以任何有意义的方式考虑和交流这些方面吗?

我们将采用两层神经网络。第一个以 sigmoid 为激活,第二个以 identity 函数为激活。到目前为止,一切如常。

最后缺少的步骤是来自张量流概率的新TFP . layers . distributionλ层。它返回的不是一个张量,而是一个TFP . distributions . distribution,你可以用它来执行你期望从分布中得到的所有类型的操作,比如采样,导出它的均值或标准差等等。

chart 2: aleatoric uncertainty

chart 3: aleatoric uncertainty (standard deviation)

你注意到第二致密层的两个神经元了吗?他们需要学习输出分布的均值和标准差。

你可以看到,通过预测一个分布而不是一个单一的值,我们越来越接近我们实际想要达到的目标。如前所述,两个斑点具有不同的方差,并且模型在其预测中反映了这一点。可以认为,对于每个斑点,该模型预测了关于拟合的平均曲线的恒定方差,该方差似乎与数据不匹配,但是这是由于有限的模型复杂性,并且将随着自由度的增加而解决。

但是在两个 blobs 之间发生了什么呢?这不是我们对一个没有数据的空间中的不确定性度量的期望,对吗?谁说在那个空间里,在远离拟合函数的某个地方,没有另一个不可测量的斑点?没人;我们只是不知道。模型也没有。不管怎样,你不应该对模型的插值感到太惊讶。

毕竟,这就是模型的作用:在没有数据的情况下,学习最符合已知数据且不损害这一目的的函数。

那么,我们如何弥补这种信息的缺乏呢?事实证明,我们之前已经讨论过解决方案:考虑认知不确定性。

基本方法是将使用分布代替单个变量的想法向前推进一步,并将其应用于所有模型参数。因此,我们以之前的示例为例,用 TFP . layers . dense variative 层替换两个 Keras 密集层。因此,该模型不仅学习一组权重和偏差,而且将其所有参数视为随机变量,其或多或少的方差取决于它找到最佳拟合的确定程度。在推断期间,模型从参数分布中取样,这导致每次运行的不同预测。因此,必须进行几次推断,并计算总体平均值和标准偏差。

chart 4: aleatoric and epistemic uncertainty

chart 5: aleatoric and epistemic uncertainty (standard deviation)

这个升级版的模型如何处理我们的玩具数据?我们可以看到,它仍然反映了两个 blobs 附近的不同方差,尽管它们似乎都增加了。这实际上是有意义的,因为我们看到的是两者的总和,即任意的和认知的不确定性。

此外,在两个数据点之间,行为发生了更剧烈的变化:由标准偏差表示的模型不确定性现在在我们没有任何可用数据的情况下达到峰值。这正是我们所希望的。

让我们再看一下我们的例子,并思考为什么它实际上是有效的。概括地说,该模型试图找到最符合数据的函数。难道没有很多其他函数能像图表 4 中的函数一样很好地拟合数据吗?例如,如果将曲线沿 x 轴稍微向左或向右移动,损耗不会显著变化。因此,造成这种移动的模型参数具有广泛的分布。在给定数据的情况下,模型对这个参数相当不确定。

如果您对完整的代码示例感兴趣,可以看看 jupyter 笔记本。它基于tensor flow probability团队与他们的博客就同一主题发表的一篇文章。如果你想更深入地研究,我推荐查看一本 jupyter 笔记本的重写版由 Cameron Davidson-Pilon 撰写的《黑客的贝叶斯方法》一书。我非常喜欢他们展示内容的互动方式。

结论

通过查看一个使用张量流概率的简单示例,我们看到了在我们的模型中考虑不确定性的重要性,以及如何克服随之而来的挑战。虽然这个库还很年轻,但我预计它很快就会变得成熟起来,因为它提供了一种简单的方法,通过无缝地适应 Keras 来结合概率建模和深度学习。

希望在从预测中得出重要决策之前,关注模型的可靠性将成为越来越普遍的做法。看到可以说是最广泛使用的深度学习库为此奠定基础,至少是朝着正确的方向迈出了一大步。

如果你觉得这篇文章有帮助,请在评论中告诉我你的想法和经历,别忘了在 Medium 和 LinkedIn 上关注我。

如何使用梯度检查调试神经网络

原文:https://towardsdatascience.com/how-to-debug-a-neural-network-with-gradient-checking-41deec0357a9?source=collection_archive---------6-----------------------

理解数学并学习如何执行梯度检查

Photo by Sue Thomas on Unsplash

当从零开始实现一个神经网络时,反向传播可以说是更容易出错的地方。因此,在调试神经网络时,调试此步骤的方法可能会节省大量时间和麻烦。

这里将介绍梯度检查的方法。简而言之,该方法包括使用数值方法来近似梯度。如果它接近计算的梯度,那么反向传播是正确实现的!

让我们深入了解更多的细节,看看如何在项目中实现它。

对于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。

Bugs are scary… Let’s get rid of them with gradient checking!

一点微积分

假设你有一些微积分的知识,梯度检验会非常容易理解。

我们知道反向传播计算导数(或梯度)。在微积分课程中,你可能记得导数的定义如下:

Definition of the derivative

上述定义可用作导数的数值近似值。取足够小的ε,计算出的近似值将在ε平方的范围内具有误差。

换句话说,如果ε为 0.001,则近似值将偏离 0.00001。

因此,我们可以用它来近似梯度,进而确保反向传播正确实现。这构成了梯度检查的基础!

矢量化实现

现在,在用 Python 实现梯度检查之前,我们需要定义一种矢量化形式的梯度检查。

让我们将权重和偏差矩阵重新整形为一个大向量 theta。同样,它们各自的所有导数都将被放入一个向量 d_theta 。因此,近似梯度可以表示为:

Vectorized approximation of the gradient

注意上面的等式和极限的定义几乎是一样的!

然后,我们应用以下公式进行梯度检查:

Gradient check

上面的等式基本上是由向量的范数之和归一化的欧几里德距离。在其中一个向量非常小的情况下,我们使用归一化。

作为ε的值,我们通常选择 1e-7。因此,如果梯度检查返回值小于 1e-7,则意味着反向传播被正确地实现。否则,您的实现中可能会出现错误。如果该值超过 1e-3,则可以肯定代码不正确。

代码

为了便于理解,让我们编写梯度检查代码,并将其应用于一个简单的示例。如果你卡住了,代码在这里可用。

我们从定义一个非常简单的激活函数开始:

然后,我们实现反向传播:

当然,您会注意到反向传播是正确实现的。随意放一个错误,以测试梯度检查的鲁棒性。

现在,我们实现梯度检查:

完美!让我们检查一下反向传播是否正确实现了:

您应该会看到以下内容:

恭喜你!您现在知道如何使用梯度检查来调试您的神经网络了!如果您在不使用框架的情况下构建神经网络,这尤其有用。否则,像 TensorFlow 和 Keras 这样的框架会自动处理反向传播步骤,您可以放心地假设它已正确实现。

在未来的帖子中,我将展示如何使用正则化来改进神经网络。

干杯!

如何在亚马逊 SageMaker 和微软 Azure 机器学习工作室之间抉择

原文:https://towardsdatascience.com/how-to-decide-between-amazon-sagemaker-and-microsoft-azure-machine-learning-studio-157a08af839a?source=collection_archive---------3-----------------------

两者都可以更快地构建模型,但是针对的用户类型非常不同

我最近发表了一篇微软 Azure Machine Learning Studio(Studio)的走查,对它的简单和强大印象良好。但是,还有其他工具也声称可以使机器学习更容易,并加快模型开发。我想知道他们如何比较?所以,本周,我要看看亚马逊 SageMaker (SageMaker)以及它与 Studio 的比较。

当我将 SageMaker 与 Studio 进行比较时,我发现了一种非常不同的建模方法。每种工具的供应商都声称提供全面管理的服务,覆盖整个机器学习工作流程,以快速构建、训练和部署机器学习模型。这是完全正确的。然而,他们以截然不同的方式实现这一点。

Azure Studio 有一个拖放 UI,其中机器学习建模过程是在画布上构建的(如果用户没有太多偏离,完全没有代码)。用户可以避开复杂的数据工程、开源库和 Python 编码。该产品面向数据分析师、公民数据科学家以及其他希望以简单、直观的方式构建模型的人。

另一方面,SageMaker 严重依赖代码,大部分用户交互都是在熟悉的 Jupyter 笔记本上进行的(当然,这是数据科学家最常用的工具之一。)SageMaker 环境将允许最大的灵活性(使用 Python——数据科学家最流行的编码语言),但需要比 Studio 更多的数据工程、数据存储和计算资源方面的知识。

因此,虽然这两种产品都使数据科学变得更容易,但这实际上是比较苹果和橙子的情况,因为它们的运作方式如此不同。SageMaker 不适合 Studio 的目标用户,他们不了解编码和数据工程,Studio 似乎限制了精通软件的数据科学家和开发人员,他们习惯于编码他们想要的任何东西。

要了解为什么这些产品是为不同的用户设计的,最好是通过屏幕截图浏览模型构建的过程,了解每个产品如何进行设置、获取数据、准备数据、构建和训练模型、对模型进行测试和评分以及部署。

对于 SageMaker,我将使用 Python3 实现 XGBoost 算法,为一家银行的市场部预测一位客户是否会购买 CD。对于 Studio,我将使用各种汽车属性进行线性回归,以预测汽车的价格。下面是这两种产品的工作原理。

设置—创建环境

亚马逊 SAGEMAKER

使用 Amazon SageMaker,我们首先在云中创建一个 Jupyter 笔记本实例。

创建笔记本实例是为了让用户可以访问 S3 (AWS 存储)和其他服务。请注意,在这个设置过程中,用户正在决定他们应该访问哪些 S3 存储桶,选择他们的云实例的大小和其他技术细节,这可能会让公民数据科学家感到困惑。

AZURE 工作室

Azure 机器学习工作室的启动点是主页。

与 SageMaker 中所需的初始设置和实例管理相比,Studio 看起来更像一个业务应用程序,并且跳过了复杂性。基本布局显示在左侧的以下选项卡中:

项目——代表单个项目的实验、数据集、笔记本和其他资源的集合

实验-您创建或保存的实验

Web 服务——您从实验中部署的 WEB 服务模型

笔记本—您创建的 Jupyter 笔记本

数据集-您已上传到 Studio 的数据集

训练模型-您在实验中训练并保存的模型

获取数据

AZURE 工作室

Studio 允许您在该屏幕截图的左侧导入和保存数据集。在这个例子中,我选择了一个标签为汽车价格数据(原始数据)的数据集,然后将这个数据集拖到实验画布上。

studio 的工作方式是通过创建画布来进行机器学习实验。在画布上,用户拖放必要的组件,如数据集、转换、算法等..在有序的流程中进行模型实验。在测试和决定模型之后,实验被转换为工作模型并发布。

数据科学家欣赏的一个非常好的特性是能够快速查看数据列和分布,以了解他们正在处理的数据。要查看这些数据,只需单击数据集底部的输出端口,然后选择 Visualize。

亚马逊 SAGEMAKER

在本例中,将数据放入 SageMaker 的过程是用 Python 以编程方式完成的。用户选择数据集(可以是 CSV 文件等。)并将其导入熊猫数据框架进行分析。这被集成到后面显示的 SageMaker 的数据准备部分。在本例中,代码类似于 Python 命令:

model_data = pd.read.csv(…。)

准备数据

亚马逊 SAGEMAKER

在 SageMaker 中,一旦用 Python 编写了数据,用户就可以自由地以编程方式转换列,删除缺少数据的行等..完全灵活。稍后,我将向您展示一些样例代码,其中包括重新格式化标题和列,作为模型选择部分的一部分。

为了在训练模型之前在 SageMaker 中完成数据准备,还需要完成许多步骤来配置环境。注意:这里再次强调容器、数据框架、库,定义正确的 S3 桶和国家区域。这种复杂性对 Studio 中的用户是屏蔽的。

首先,我们需要选择我们正在使用的 Python 版本——conda _ Python 3。

为了准备数据、训练机器学习模型并部署它,我们需要导入一些库并定义一些环境变量。在这种情况下,这样做的代码如下所示。我们将运行 Jupyter 笔记本中的代码。

我们将需要一个 S3 桶来存储我们的训练数据,一旦我们处理了它,这也需要定义。

接下来,我们需要将数据下载到我们的 SageMaker 实例,并如上所述将其加载到 Pandas 数据帧中。要做到这一点,应该如下所示:

AZURE 工作室

与基于代码的方法相比,Studio 提供了一种拖放的可视化方法。Studio 中的数据集和模块具有由小圆圈表示的输入和输出端口——输入端口在顶部,输出端口在底部。要在实验中创建数据流,需要将一个模块的输出端口连接到另一个模块的输入端口。您可以随时单击数据集或模块的输出端口,查看数据流中该点的数据。

Studio 使数据准备过程对业务用户来说非常容易。它们提供了一个模块(选择数据集中的列,以完全删除不需要的列(在本例中为归一化损失列,它有许多缺失值)。我们只需将数据集模块中的选择列连接到我们的汽车数据集,并选择要排除的列。

类似地,为了删除丢失数据的行,我们将清除丢失数据模块拖到实验画布上,并将其连接到数据集模块中的选择列。

建立&训练模型

这一步包括将数据分成训练和测试子集,选择预测所基于的特征,并选择最适合数据的算法。

分割数据并选择特征

亚马逊 SAGEMAKER

将数据分成训练集和测试集是通过几行 Python 代码完成的。训练数据(本例中为客户数据集的 70%)将在一个称为梯度优化的迭代周期中使用,以学习模型要素并以最小的误差从输入要素中推断分类标签。这似乎是 SageMaker 在这个例子中的一个优势,因为功能选择(独立变量)是自动执行的,而在 Studio 中,我们手动选择功能,正如您将看到的。剩下的测试数据(30%)将用于稍后评估模型的性能。

AZURE 工作室

为了在 studio 中分割数据和选择特性,我们使用 Dataset 和 split data 模块中的 select 列。

Studio 允许我们通过选择我们认为将提供预测能力的列来选择传递给训练算法模块的特性,并进行迭代,直到我们获得所需的性能。我确实发现 Studio 中的一些机器学习算法确实使用特征选择或维度缩减作为训练过程的一部分。当我们使用这些算法时,我们可以跳过特征选择过程,让算法像 SageMaker 一样决定最佳输入。对于线性回归,我们手动选择特征。

为了分割数据,我们将使用分割数据模块,直观地选择分割百分比,而不是像在 SageMaker 中那样进行编码。

训练模型

亚马逊 SAGEMAKER

我们已经预先确定将使用 SageMaker 预构建的 XGBoost 算法。类似于我们在准备数据部分如何在 Studio 中消除列和行,我们可以在 SageMaker 中用 Python 进行相同类型的数据清理和重新格式化。下面的代码(在单元格#6 中)重新格式化训练数据的头和第一列,并从 S3 存储桶加载数据。

接下来,我们需要设置 SageMaker 会话,创建 XGBoost 模型的实例(估计器),并定义模型的超参数。这个的代码在 7 号单元格。

加载数据并设置 XGBoost 估计器后,我们现在可以在 ml.m4.xlarge 实例上使用梯度优化来训练模型,方法是使用单元格#8 中的代码在 Jupyter 笔记本中选择 run。

AZURE 工作室

为了添加我们希望使用的学习算法,我们展开画布左侧的机器学习类别,并展开初始化模型部分。我们已经预先确定我们将使用线性回归,所以选择线性回归模块并将其拖到画布上。接下来,我们将找到火车模型模块并将其拖动到实验画布上。将线性回归模块的输出连接到训练模型的输入,并将分割数据模块的训练数据(左端口)连接到训练模型,如图所示。

单击火车模型模块,然后在属性窗格中单击启动列选择器,然后选择价格列。价格是我们的模型将要预测的价值..我们将价格从可用列移动到选定列列表中。

我们终于可以进行实验了。我们现在有了一个经过训练的回归模型,可以进行价格预测,我们在 Studio 中的模型创建流程如下所示:

测试、评分和部署模型

亚马逊 SAGEMAKER

要在 Sagemaker 中测试模型,我们必须首先部署它,这是一个与在 Studio 中不同的过程。为了在服务器上部署模型并创建端点,我们在 Jupyter 的 cell 9 中运行以下代码。为了预测测试数据中的客户是否注册了银行产品,我们将在 Jupyter 的单元格 10 中运行代码。

为了评估性能,我们编写 Python 代码来比较实际性能和预测性能,并生成如下结果表。

从这些结果中,我们可以得出结论,该模型准确地预测了测试数据中 90%的客户的结果,对于注册的客户,精度为 65% (278/429),对于未注册的客户,精度为 90% (10,785/11,928)。

最后,在 Sagemaker 中,我们还需要记住终止我们的会话并清理云资源,以消除我们帐户中的进一步费用。下面的代码删除了 SageMaker 端点和 S3 存储桶中的对象。

AZURE 工作室

既然我们已经在 75%的数据上训练了 Studio 模型,我们可以使用它来对另外 25%的数据进行评分,以查看我们的模型运行得有多好。我们通过将乐谱模型模块拖到实验画布上,并将训练模型的输出连接到它来实现这一点。然后,我们将分割数据模块的测试数据输出(右端口)连接到评分模型模块,如图所示。

然后,我们运行实验,并通过单击底部端口并选择 Visualize 来查看分数模型的输出。预测价格与模型使用的所有已知要素数据一起显示在“评分标签”列中。列 price 是数据集中实际已知的价格。

与 SageMaker 一样,我们希望评估我们的模型表现如何。为此,我们将评估模型模块拖到画布上,并简单地将其连接到得分模型的输出。现在,当我们再次运行这个实验时,我们可以看到平均误差和 R 平方等的统计结果...

在对模型的准确性感到满意之后,Studio 通过一个设置 Web 服务按钮就可以轻松地将模型发布给其他人使用。在我们决定了模型的特征和算法之后,该选项通过消除模型中的数据分割、训练和其他不必要的步骤,将模型从实验转换为预测实验。我们最后一次运行这个模型来检查结果,它已经准备好了一个 API 密匙供其他人在 Azure 上使用。

总结

微软和亚马逊都提供了一个强大的流程和基于 UI 的工具,以加速和简化 Azure Studio 和亚马逊 SageMaker 的机器学习模型开发过程。但是这些工具是为完全不同的用户设计的。

Studio 提供了一个漂亮的拖放界面,带有简单的模块来执行常见的功能,如访问数据、清理数据、评分和测试模型以及部署等..它旨在引导公民数据科学家和初学者完成构建机器学习模型的过程,同时保护他们免受管理云实例、Python 编码和 Jupyter 笔记本的复杂性的影响。

SageMaker 是为开发人员和数据科学家的需求而构建的,他们习惯于在 Jupyter 笔记本上工作,用 Python 编程,并希望获得灵活性和对资源的完全控制。但是 SageMaker 的用户无法避免其他云操作复杂性,如云实例管理——知道要选择的集群大小、位置以及完成工作后关闭集群。除了 Python 编程之外,这些类型的任务会使 SageMaker 成为大多数试图构建模型的业务分析师的不合适的选择。

但是一个产品比另一个产品能产生更精确的模型吗?我不认为模型的准确性会将一个与另一个区分开来,因为这两个产品都允许我们导入任何所需的算法,并且这两个产品都在不同的模型上提供了一些自动化的功能选择。我怀疑一个产品能比另一个产品始终产生更精确的建模结果,这有什么可概括的区别。

真正的区别在用户设计点。SageMaker 面向数据科学家/开发人员,Studio 面向公民数据科学家。但是,Studio 也支持 Jupyter 笔记本界面,这使得数据科学家也可以使用 Studio 和 Azure 机器学习服务的云基础设施来完成 SageMaker 在亚马逊云基础设施上提供的功能。为此,对于更多类型的用户来说,Studio 可能是一个更通用的选择。

关于作者

史蒂夫·迪尔(Steve Dille)是硅谷的产品管理和营销领导者,曾在数据管理、分析、商业智能和大数据领域的公司高管团队中成功完成了 5 次公司收购和 1 次 IPO。最近,他是 SparkPost 的 CMO,在他的帮助下,SparkPost 从一家内部高容量电子邮件发送者转变为领先的预测分析驱动的云电子邮件 API 服务,并从 1300 万美元增长到超过 5000 万美元。他目前正在通过在加州大学伯克利分校攻读信息和数据科学硕士学位,建立数据科学、人工智能和机器学习方面的深厚知识。他过去的学历包括芝加哥大学布斯商学院的 MBA 学位和匹兹堡大学的计算机科学/数学学士学位。他曾在 NCR 担任软件开发人员,在惠普担任产品经理,在赛贝斯(Sybase)担任数据仓库总监,在许多其他初创公司和中型公司担任产品或 CMO 副总裁。

如何定义和执行你的数据和 AI 策略?

原文:https://towardsdatascience.com/how-to-define-and-execute-your-data-and-ai-strategy-a391676baa42?source=collection_archive---------17-----------------------

迄今为止,许多公司都在投资数据和人工智能(AI)。随着术语的变化,这些活动可能被称为人工智能、高级分析、数据科学或机器学习,但公司的目标是相同的:增加当前业务的收入和效率,并开发新的数据支持产品。众所周知,要在数字经济中保持竞争力,公司的内部流程和产品需要智能——而智能来自数据和人工智能。没有数据和 AI,成功的数字化转型是不可能的。

根据我们的经验,评估一家公司的数据和人工智能成熟度的最佳方式是从关注公司如何利用其数据和分析人员开始。不太成熟的公司会错过某些角色,例如,他们可能有数据科学家,但没有数据工程师,这意味着数据环境没有正确地产品化。或者数据和分析专家分散在整个组织中,但没有以系统的方式表明招聘决策是由个别有远见的业务领导做出的,而不是与公司范围的战略保持一致。

在过去的三年里,我们公司 DAIN 工作室参与了芬兰、德国、奥地利、瑞士和荷兰不同公司和行业的 40 多个数据和人工智能项目。我们的客户通常是大型上市公司。在我们的工作中,我们定义了数据和人工智能战略,评估了人工智能执行项目,并就数据治理、组织和运营模式等主题向公司提供建议。我们还建立了云基础设施,设计了数据,并开发了可扩展的机器学习模型。我们已经就如何成为数据驱动和使用人工智能为他们带来好处向数十位商业领袖提供了建议。这篇文章回顾了我们的一些发现,并提出了前进的最佳实践。

当我们在 2016 年初成立我们的公司时,人工智能一词刚刚从 20 世纪 60 年代开始复活。在 2016 年之前,很酷的术语是“大数据”(现在听起来已经无可救药地过时了),在此之前是“高级分析”和“数据科学”(仍在使用!).虽然许多数字化本土公司在 2016 年的业务中应用了先进的数据和人工智能方法,但许多老牌公司却没有。数字化以及由此产生的对数据和人工智能的需求扰乱了许多老牌公司的商业模式,令它们措手不及。面临来自数字原生公司竞争的行业,如媒体和零售业,不得不转变自己,快速采用数据利用。相比之下,许多制造企业仅处于数字化和数据转型的初级阶段。

由于数据和人工智能意识的增加,许多老牌公司已经开始了有针对性的数据和人工智能计划,并对扭转业务和吸引明星人才抱有很大期望。然而,项目进行了几年后,许多人表现出疲惫的迹象,并且没有满足高级经理和领导对进度不满意的期望。已经在选定的领域进行了试点,甚至可能已经推出了支持数据的产品,但预期的大规模业务转型尚未发生。数据和 AI 仍然是小众活动,而不是商业的前提。在某些情况下,人们会私下谈论“不能透露名字的项目”结果,管理层变得越来越不耐烦,不知道如何摆脱常规。

现实是没有捷径可走。亚马逊、谷歌、苹果和脸书都使用了非常不同的商业策略来获得他们目前的市场主导地位和全球影响力,但他们的共同成功可以说是他们对数据价值的理解和早期定位的远见。他们由内而外地工作,不断强调能力建设,同时在内部开发、测试和部署顶级技术,以便为客户提供最佳产品。对于老牌的非数字公司来说,道路更加崎岖。旧公司已经建立了工作方式,数字不成熟的人,和遗留的基础设施。克服这些问题需要公司领导层坚定的决心和毅力。这意味着将数据和人工智能纳入决策制定的所有方面的核心——从战略到运营,并得到与数据驱动的决策制定相一致的关键绩效指标的支持。这种行动通常表现为在领导层会议的议程上关注数据和人工智能能力发展——从董事会到首席执行官,再到高级经理。这通常是高瞻远瞩的人力资源经理的议程,他们明白数字人才对公司至关重要。

根据我们的经验,商业领袖需要高度参与数据和人工智能战略执行的所有方面,以及支持计划所涉及的能力。我们发现,全身心投入的领导力是成功实现数字化转型和成为数据驱动型公司的共同特征之一。

有时,领导层理解成为数据和人工智能驱动的重要性,但觉得自己对主题的知识不足。这是一个好迹象。许多大学和咨询公司为商业领袖提供数据和人工智能培训。一个有效的方法是定制一个数据和人工智能研讨会,作为领导力战略日的一部分。一句警告的话:有时商业领袖错误地将注意力集中在统计学、计算机科学和编码上,以此来增强他们对人工智能的理解。虽然编码对于数据科学家和数据工程师来说是一项关键技能,但商业领袖最好将精力放在为数据和人工智能创造有效的公司环境上。这意味着设定业务目标,雇用合适的人,教育员工,承诺投资,并为数据和人工智能实施有效的运营模式和组织。最好的方法是为组织设定明确的目标和激励,并遵循这些目标和激励。

在下一节中,我们将深入探讨在定义和执行数据和人工智能策略时应该考虑的主题。

1.设定数据和人工智能愿景

数据和 AI 策略成功的前提是知道自己的商业目标。你有哪些必胜的战役?未来需要在哪些方面取得成功?显然,访问数据将有助于定义业务优先级,但重要的是要记住,数据和人工智能不会解决你在商业模式、产品和服务方面的问题。数据和人工智能将帮助你做出更明智的决策,更快地获取信息,自动化流程,并比人脑更快地交付产品——但它不会构建或取代商业愿景和想法的缺乏。

AI 优先级源自业务优先级。由于数据和人工智能将在不同的领域做出不同的贡献,因此在评估公司的数据和人工智能工作的重点时,应该考虑每个业务领域的业务案例以及人工智能对案例的相对重要性。

例如,在销售和营销中使用数据和人工智能通常会很快产生结果,而在产品开发中使用它们需要较长时间,但最终会产生巨大而有影响力的结果。通常从流程优化案例开始是有意义的。效率提高 1%或避免停机可能意味着节省数百万欧元。计算成本节约案例的业务案例比计算新业务的业务案例更容易。早期成功对于沟通以获得组织的认同以及增加对已展示的人工智能优势的总体理解非常重要。

获得对数据和人工智能愿景的支持和认同同样重要。这样做的传统方法是为数据和人工智能建立一个业务案例,显示计划投资的基线内部回报率(IRR)(当前状态),并将其与数据和人工智能投资的 IRR(未来状态)进行比较。沿着这些路线制定战略是理解大局的一个很好的练习,然而,需要记住的是,对于许多数字产品、服务和企业来说,“不做数据和人工智能”的选择是不可行的。如果没有数据和人工智能,谷歌会是谷歌吗?

数据和人工智能利用的自然起点是当前业务流程的优化:业务模型、产品、服务、内部流程和功能(如营销、人力资源)。一旦你对帮助你当前业务的数据和人工智能用例有了坚实的理解,也应该调查新的数据驱动的商业机会。这些包括数据货币化(例如,出售数据)和数据合作伙伴关系(通过汇集来自多个组织的数据来创建新产品)。这两个话题都不容易,但其中的机会值得研究。

2.数据资产管理/数据治理

高质量数据的可用性是成功的产品化人工智能的基础。如果数据是根据欧盟地平线 2020 计划(2016)建议的公平原则(可发现—可访问—可互操作—可重用)构建的,则可以称为资产。以不同格式和本体驻留在不同系统中的数据,缺少关键属性(如唯一标识符),不是资产。如果数据资产不可重用,每一项数据科学/人工智能活动都将是一项独立的、可能是大型的 IT 工作。“一次构建,多次使用”的原则是实现数据资产价值最大化的关键。例如,对于在线服务的个性化,您可能希望使用来自在线和移动渠道的行为数据、CRM 数据以及消费者在线和离线交易,而不仅仅是来自在线服务本身的数据。产品化数据资产的目标是支持所有用例。

构建公司的数据资产时,从优先业务机会/用例所需的数据开始。这听起来不言自明,但在许多公司中,设计数据的 IT 团队和业务职能之间存在组织上的脱节。在最坏的情况下,数据工程团队忙于构建一个数据资产,将各种数据源集成到一个公共的数据环境中,但是这些不是业务需要的数据源。结果,双方都以沮丧告终。

开始构建数据资产的一个好的实用方法是评估当前数据的“公平”程度。这一过程被称为数据尽职调查或数据清点。数据尽职调查回答如下问题:存在哪些数据?它在哪里?如何访问它?它的质量如何?能和其他数据联系起来吗?它的恢复需要多少努力?,我们是否遗漏了一些明显的数据源(考虑用例)?一旦确定了数据资产的当前状态,就可以制定其开发的路线图。

3.解决方案架构和技术

解决方案架构和技术指的是数据资产的技术方面。除了数字原生公司,现有的公司通常有大量的遗留基础设施。定义业务和人工智能愿景以及数据尽职调查后的首要任务之一是让一位经验丰富的数据和解决方案架构师对当前的技术架构进行批判性研究,并定义目标架构及其开发路线图。这个任务也应该遵循端到端用例逻辑,用于从操作系统(例如 CRM、ERP)、数据仓库、云环境、分析环境和业务接口系统收集数据。传统上,来自 BI 世界的许多数据解决方案架构停留在数据仓库级别解决报告用例。然而,自动机器学习/人工智能解决方案需要链接回运营系统,这意味着运营系统需要成为数据和解决方案架构的一个组成部分。例如,要将您的消费者数据资产(包括单个微细分、次佳报价和其他消费者评分)实时用作现代全渠道营销自动化系统的一部分,您需要建立端到端架构。有时营销部门监管营销技术,而它负责后端系统。这可能导致营销只使用营销数据(例如在线、电子邮件),而丢弃许多其他有趣的数据源,因为他们没有意识到它们的存在。在最糟糕的情况下,应该创建公司范围内的 ML/AI 算法的数据科学团队不参与任何活动。

管理从传统 IT 系统到数字世界的过渡通常是一个漫长的过程。虽然自动化和人工智能最终会降低成本,但在过渡期间,随着新旧解决方案并存,成本可能会增加。此外,一个典型的 IT 部门的预算与当前系统的操作和维护紧密相关,而开发预算却不多。新的技术解决方案需要新的投资。

4.数据保护和隐私

数据保护和隐私是消费者和那些有权访问消费者数据的人最关心的问题。数据保护涉及数据收集、处理和利用。根据欧盟通用数据保护条例(GDPR ),必须定义数据处理的合法权益,并告知用户其数据的收集、处理和组合。必须为用户提供退出和拒绝数据处理的机制。必须定义不同数据处理系统之间数据流的用户标识级别。

当使用数据并确保遵守隐私立法时,根据人工智能用例的期望状态而不是当前用例来编写隐私策略是至关重要的。重点是避免这样一种情况,即当你想开发超目标、个性化的人工智能模型时,你的隐私政策允许你仅出于报告目的使用你的数据。

建立公司范围隐私政策的良好团队由企业所有者、隐私律师和人工智能策略师(或数据科学家)组成。具有技术背景的人工智能策略师将帮助将业务用例转化为数据和人工智能需求,并与隐私律师讨论不同选项的解释(包括用户体验)。

5.人类技能

数据和人工智能之旅需要组织中的新角色。虽然确切的角色术语各不相同,但四个不同级别的业务流程都需要数据和人工智能角色:

1)业务单位(损益)和业务职能(如销售、营销、财务)

2)数据科学(和商业智能)

3)数据资产管理

4)数据平台和技术解决方案

业务用例来自业务层面(#1)。除了实际的业务人员,人工智能战略家的角色也在这里。人工智能战略家将业务愿景和目标转化为数据和人工智能需求,监督项目执行,并确保项目成果被业务流程所利用。大多数公司没有这个角色,但我们认为它是成功执行数据和人工智能项目的最关键角色之一。如果没有人工智能策略师,具有商业/工程背景的人和数据科学家之间的沟通距离往往太远,可能需要一些时间来调整。人工智能战略家的良好背景是希望将自己发展成为商业和管理人才的高级数据科学家。随着时间的推移,人工智能战略家将开发人工智能产品所有权任务的责任。

一些咨询公司以“分析翻译”的形式呈现这一角色,尽管这与我们的定义相似,但我们强调人工智能战略家作为业务影响驱动者的角色。

除了人工智能战略家,商业领袖本身也需要了解数据和人工智能的机会,以便推动主题向前发展,并将人工智能成果融入各自的业务流程。

虽然大多数公司缺乏人工智能策略师的角色,但许多公司已经聘请了数据科学家(#2)。数据科学家以各种形式出现,有着不同的背景。作为教育背景,许多人学习了定量方法,如计算机科学、数学、统计学、物理学或工程学。拥有不同类型教育背景的数据科学团队是有意义的。例如,具有统计学或计量经济学背景的人擅长统计推断,而具有计算机科学背景的人精通机器学习技术和编码。物理学家被训练来处理物理现象和模型,并跳出框框思考。有时精通数据的社会学家、心理学家或生物学家可以给团队带来不同的观点。

由于机器学习/人工智能是一个新领域,因此对有经验的数据科学家有很大的需求。我们建议招聘一名高级数据科学家或人工智能策略师作为第一批雇员,让他们建立一个由经验丰富的人和有前途的年轻人才组成的平衡团队。

一个常见的错误是只雇用数据科学家,而不填补技术角色,如数据工程师和数据架构师(#3)或平台工程师和解决方案架构师(#4)。这导致了数据科学家的高度沮丧,因为他们必须从源系统中检索数据并自己构建数据库。在实践中,这通常意味着数据资产和数据基础设施将无法正确构建。数据科学团队将进行试点并构建单点解决方案,但可扩展的数据基础将遥不可及。数据科学家接受的培训是建立机器学习模型,而不是进行提取、转换和加载(ETL)、数据库和云解决方案。随着试点规模的扩大,这种挫败感将蔓延到管理层。

现在很多人自称数据科学家或者数据工程师。可能很难区分走路和说话。除了查看该领域潜在招聘者的教育和过去的工作经验,我们建议在招聘中使用评估测试。根据手头的角色,它可以被定义为强调工作的各个方面。在我们自己的招聘过程中,我们使用评估测试,这比面试更能揭示候选人的更多信息。你可以用一种有趣和富有挑战性的方式来定义评估,这样候选人就会喜欢并乐于这样做。

一个好的开始是聘请一位在商业、数据、数据科学和技术方面有经验的首席数据和人工智能官来雇用人才并建立团队。除了主题专业知识之外,此人还应该具备出色的领导能力和沟通技巧,因为他们需要与组织中不同层次的人进行有效沟通。

6.数据和人工智能组织

最佳的数据和人工智能组织结构取决于整体公司规模和组织、文化、人工智能成熟度水平以及数据/人工智能任务的类型。

一般来说,要让事情进展顺利,建立卓越中心(CoE)会将注意力集中到这个主题上。根据 CoE 在公司中的位置,它将负责不同的领域。CoE 可能仅由数据科学和 BI 团队组成,而技术团队(数据工程、平台)驻留在其中。或者,CoE 可以负责技术方面,而数据科学家则在业务部门工作。需要仔细研究最佳设置。根据我们的经验,大多数公司将受益于通用的技术基础设施和数据资产,以及某种类型的集中式数据科学团队,这可以解决最困难的用例,并创建可扩展的人工智能产品组合,供所有业务部门和功能使用。

人工智能策略师应该最佳地坐在业务单元中,以推动人工智能用例向前发展,但在开始时,他们也可以驻留在数据科学团队中,并从那里帮助业务。

在一个成熟的数据/人工智能驱动的公司中,随着整个公司在日常业务中使用数据,CoE 的作用将变得越来越小。在成熟阶段,CoE 将继续关注常见的数据治理主题,如数据质量和完整性、技术系统、本体和标准。

有时,为了让开始变得容易,引入一个公司范围的人工智能计划来推动数据和人工智能议程是有意义的——前提是该计划存在 2-3 年,然后将被解散。一个项目的好处是,你不需要在早期阶段做出直线组织的决策,但是随着时间的推移,你会了解什么类型的团队结构适合你的组织。

7.运营模式

与数据和 AI 组织密切相关的一个话题是不同业务部门之间的运营模式。优先的业务用例应该驱动数据和人工智能的发展。为了让数据专家在最重要的用例上工作,企业领导人应该建立一个人工智能指导小组,或者将数据和人工智能开发纳入现有的领导团队会议。CoE 负责人应该推动会议议程。除了一个跨单元的指导小组,单独的用例领域应该有他们自己的,可操作的指导小组。

对于 CoE 的第一年,数据和 AI 开发预算应该集中。预算推动优先化,如果没有集中的预算,数据和人工智能活动将无法扩大规模。单个业务单位不希望承担公司范围内的能力建设(例如,通用数据模型、基础设施、API)的成本,即使这对整个公司来说是最佳的。这意味着人工智能解决方案往往会成为独立的、不相连的孤岛。此外,如果没有一个共同的路线图、优先顺序和明确的治理,贡献最大的业务将要求他们获得资源,即使资源在战略上可以更好地用于其他领域。

重要的是要记住,这不仅仅与数据专家有关。业务流程和业务人员从根本上受到数据和人工智能利用的影响,例如,在营销中,为了推动基于触发的个性化营销,数据和目标模型需要可用,但营销内容制作、客户处理模型、渠道策略、前端系统等也是如此。与传统营销相比,持续、数据驱动的营销需要营销人员具备不同的技能和能力。流程自动化也是如此:如果数据科学家构建了一个预测性的服务维护模型,那么只有当服务车队和技术系统能够对预测做出及时的干预时,才能获得业务影响。

增加业务影响的一个聪明方法是给数据/人工智能项目中的每个人相同的激励。例如,如果目标是通过人工智能驱动的目标定位将营销活动提升 20%,那么这个目标应该交给营销人员、数据科学家和数据工程师。这可能会招致一些反对,但最终会给公司带来最好的结果。

8.数据科学和 ML/AI 算法

像数据资产一样,算法也可以被视为算法资产。这意味着,随着时间的推移,机器学习/人工智能算法的组合将变得公平。每一个新的分析建模练习都不需要从头开始,而是建立在经过测试的代码之上。随着时间的推移,这将使数据科学团队更加高效。像软件编码团队一样,它要求数据科学团队使用通用的代码库和标准。

为数据和算法资产建立维护流程也很重要。如果维护过程仍然没有部署,开发团队仍然处于停滞状态,因为他们的努力是为了保持生产中的当前资产。通过对数据和算法组合应用维护过程,可以发现和开发新的解决方案。

最后的话

总而言之,成功执行数据和人工智能需要以下步骤:

1.根据您的业务优先级,制定您的数据和人工智能用例;

2.了解您的数据和人工智能项目及促成因素的当前状态;

3.定义您的数据和人工智能愿景以及执行路线图,包括投资;

4.执行旨在生产就绪的第一个用例;

5.扩大运营规模。

有时人们会认为,AI 驱动的公司的最高水平是当所有的决策和业务流程都由自动化算法完成时。然而,这是一种误解。自动化和人工智能不会自己做出明智的商业决策。AI 成熟度的最高水平是当整个公司走向一个方向,筒仓被解散,数据和 AI 被每个人作为日常业务的一部分使用。一切能自动化的都将自动化,人类需要确保自动化以智能的方式完成。

如何定义公平性以检测和防止机器学习中的歧视性结果

原文:https://towardsdatascience.com/how-to-define-fairness-to-detect-and-prevent-discriminatory-outcomes-in-machine-learning-ef23fd408ef2?source=collection_archive---------4-----------------------

为了检测机器学习预测中的歧视性结果,我们需要比较我们的模型如何对待不同的用户群。

这可以通过在我们的模型中定义一个描述公平概念的度量来实现。例如,在看大学录取时,我们可以比较男女的录取率。这相当于使用人口统计上的均等作为公平的数学定义。它指出,在理想世界中,获得积极结果(例如:被大学录取)的群体之间的差异应该为零。然而,这很少发生,这就是为什么我们需要跟踪差距。

人口均等是我们可以用来描述数学公平的定义之一。在本帖中,我们将回顾分类模型中最常见的三个定义。选择正确的公平类型非常重要;否则,错误的指标会导致有害的决策,我们将对此进行探讨。

从示例开始

在这篇文章中,我将用一个信用模型的例子来解释数学公平的主要定义。我们将研究何时以及如何使用它们是有意义的。

我们将使用的历史数据可以描述如下:

  • 已还贷款:全额还贷款者。
  • 违约:无力偿还贷款而违约的人。

Figure 1: example of a classification credit model

让我们假设我们正在建立一个纯粹基于“收入”的信用模型。我们的模型旨在了解那些能够全额偿还贷款的人的典型收入,并将他们与那些倾向于违约的人区分开来。

这意味着我们只需要在我们的训练集中设置一个收入阈值,以决定未来谁可以获得贷款(这是图 1 中的虚线)。那些超过阈值的人将获得贷款(正面预测)。门槛以下的人是得不到贷款的人(负面预测)。

数学公平的第一个例子:人口均等

人口统计均等表明,受保护阶层(如性别)的每个部分的比例应平等地获得积极成果。积极的结果是首选的决定,如“上大学”、“获得贷款”或“看到广告”。如前所述,理想情况下差值应该为零,但通常情况下并非如此。

让我们假设我们正在建立一个完全基于“收入”的信用模型(见图 2)。我们可以决定对每个组使用不同的需求水平,这样 A 组获得贷款的人的百分比就等于 b 组获得贷款的人的百分比。

数学定义

在数学术语中,人口统计均等要求结果独立于受保护的 A 类:

Equation 1: Probability of getting an outcome is independent of A

关于混淆矩阵,我们要求正率(PR)对于保护类的每个段都是相同的。

正比率(A=0) =正比率(A=1)

在实践中,我们可能不要求正利率的差异等于零,但我们的目标是将这一差距最小化。

什么会出错?

假设我们想要创建一个舞蹈团体。我们正试图从一群专业舞者、流行歌手和一些演员中挑选我们的舞蹈团队。历史上的刻板印象告诉我们,舞蹈演员和流行歌手将非常适合这份工作。然而,我们几乎可以肯定演员们可能不会。

假设我们得到了上面 GIF 中的结果,职业舞者和流行歌手在这种情况下会被认为是天生的高手。憨豆先生糟糕的舞蹈表演确实会加强我对演员不擅长舞蹈的偏见。

当决定做出时,演员们还没有像专业舞者和流行歌手一样有机会学习舞蹈。如果我们立即要求人口统计均等,这可能导致促进历史偏见。

现在来看一个更严肃的例子。比方说,我们希望让更多女性加入由典型的“男生俱乐部”组成的董事会。这可能不是最欢迎女性的环境。我们需要有一个适当的计划,以便环境是包容性的,新的少数群体得到正确的支持。否则,我们有强化历史偏见的风险。

何时使用人口统计均等

在以下情况下,我们应该使用人口统计均等作为公平的定义:

  • 我们希望改变我们当前世界的状态,以改善它 (例如:我们希望看到更多的少数群体获得成功)
  • 我们意识到历史偏见可能影响了我们数据的质量 (例如:ML solution 被培训来雇佣软件工程师,而以前几乎没有女性被雇佣)
  • 我们制定了一个计划来支持无特权群体,以防止历史偏见 (例如:制定惩罚董事会非包容性行为的政策)

大学录取倾向于实现人口均等。一个很好的例子是牛津大学通过招收更多来自弱势背景的学生来提高多样性。在这种情况下,学生有很高的学术潜力,但他们的教育可能已经中断,或者他们必须克服个人的劣势。这一组的学生在开始他们的学位课程之前将得到额外的支持,延伸到一个完整的基础学年。

数学公平的第二个例子:机会均等

Figure 3: use of different income thresholds to achieve Equal Opportunity

平等机会是指每个群体都应该以平等的比率获得积极的结果,假设这个群体中的人有资格获得积极的结果。

如果我们看一下图 3 中的例子,我们可以看到准确预测的阳性百分比在两组中都是 50%。

如果我们仔细想想,这就像是在说:

假设你会跳舞,你可以成为我们舞蹈队的一员。

数学定义

机会均等要求积极结果独立于受保护的 A 类,条件是 Y 实际上是积极的:

Equation 2: Probability of getting a positive outcome is independent of A, conditional on Y being an actual positive

基于混淆矩阵,我们要求受保护类的每个片段的真实肯定率(TPR)相同。

真阳性率(A=0) =真阳性率(A=1)

在实践中,我们可能不要求实际正利率之差等于零,但我们的目标是将差距最小化。

什么会出错?

Figure 4: many False Positives are introduced in Group B to be able to achieve Equal Opportunity

如果我们看一下图 4,我们可以看到两个组的真实阳性率(TRP)是相同的,这是机会均等所要求的。

但是,如果我们关注 B 组,我们可以注意到引入了许多假阳性。在这种情况下,误报是指那些在实际上可能违约的情况下获得贷款的人。这意味着我们将在 B 组中更大范围地损害信用评分,这将导致完全不同的影响。

何时使用平等机会

在以下情况下,我们应该使用平等机会作为公平的定义:

  • 非常强调正确预测积极结果 (例如:我们需要非常擅长检测欺诈交易)
  • 引入误报对用户和公司来说都不昂贵 (例如:错误地通知客户欺诈活动对客户和发送警报的银行来说都不一定昂贵)
  • 目标变量是不被认为是主观的 (例如:给谁贴上“好”员工的标签会引起偏见,因此非常主观)

如上所述,考虑到“误报”形式的错误不会对客户或处理该情况的公司产生代价高昂的负面影响,使用平等机会可能是欺诈检测的合适案例。此外,将交易标记为欺诈应该是一个明确的决定,而不是受到重大偏见的。

数学公平的第三个例子:均等的赔率

Figure 5: use of different income thresholds to achieve equalised odds

数学公平的最终定义是均等赔率,这是我们将在本博客中讨论的最具限制性的概念。

这个概念规定模型应该:

  • 正确识别各组之间比率相等的积极结果(与机会均等相同),而且
  • 在各组之间以相等的比率误分类阳性结果(在各组之间产生相同比例的假阳性)

我们可以在图 5 中看到这样一个例子,其中我们以 50%的正确率识别出两组的阳性结果,但两组的假阳性比例相同,均为 25%。

数学定义

均等赔率要求正结果独立于受保护的 A 类,以实际 Y:

Equation 3: Probability of getting a positive outcome is independent of A, conditional on Y

基于混淆矩阵,我们要求保护类的每个片段的真阳性率(TPR)和假阳性率(FPR)相同。

真阳性率(A=0) =真阳性率(A=1)

假阳性率(A=0) =假阳性率(A=1)

在实践中,我们可能不要求真阳性率和假阳性率之差等于零,但我们将致力于使这两个差距最小化。

什么会出错?

Figure 6: The False Positive Rate (bar chart, left y-axis) is minimised when enforcing Equalised Odds at the expense of lower profits (line chart, right axis)

鉴于这是最具限制性的定义,试图为每个群体实现平等的 TPR 和 FPR 可能会导致利润下降。这是因为模型性能可能会因无法优化多数群体的准确性而受到影响。

图 6 是实施均等赔率时可能发生的情况的一个例子。我建立了一个信贷模型来确定谁应该获得贷款,并分析了 40 岁以上和 40 岁以下人群的公平定义。在这种情况下,与其他公平定义相比,利润在均等赔率期间受到严重惩罚。

对于这个例子,在建立模型之前,没有做任何工作来检测或减轻偏差,这可能解释了为什么利润如此之低。这也表明了应用偏差缓解技术(如“重新称重”)和对缺失数据进行良好分析的重要性,以便在不损害货币价值的情况下为每个人建立良好的模型。

何时使用均等赔率

在以下情况下,我们应该使用均等赔率作为公平的定义:

  • 重点强调正确预测积极结果 (例如:正确识别谁应该获得贷款来推动利润),以及
  • 我们非常关心最大限度地减少代价高昂的误报 (例如:减少对无力还款者的贷款发放)
  • 目标变量是不被认为是主观的 (例如:标注谁是‘好’员工会导致偏见,因此非常主观)
  • 模型的回报功能没有受到严重影响 (例如:业务的收入或利润功能仍然很高)

信用模型是一个很好的例子,用均等的赔率来定义公平。我们通过接受尽可能多的能够全额偿还贷款的客户来创造商业价值。然而,我们也关心最大限度地减少“误报”,即那些获得贷款但无法偿还的人。

误报会损害客户的信用评分,从而影响他们未来的金融机会。这也会给发放贷款的银行带来很高的成本。

同时,将贷款标记为全额支付或违约是一个非主观的决定和清晰的过程。

结论

在这篇博客中,我们学习了可以应用于分类模型的“数学公平”的三个最常见的定义。我们研究了何时使用每个公平指标是有意义的,以及在应用它们时需要考虑什么。

我们必须开始分析我们的模型如何对不同的客户群产生不同的影响。否则,我们就有大规模传播系统性歧视的风险。

如果您对本文有任何反馈或建议,请在下面的评论框中留下👇。

如何与您的数据科学团队一起交付具体的商业价值?

原文:https://towardsdatascience.com/how-to-deliver-concrete-business-value-with-your-data-science-team-6fe314475184?source=collection_archive---------33-----------------------

机器学习和深度学习领域的快速发展带来了先进的算法。这些先进的算法能够转变组织,从而获得多重商业价值。组织已经开始投资于数据科学团队,以引领数字化转型之旅,在竞争中脱颖而出。

Image by Gerd Altmann from Pixabay

大多数组织是否都在加快数字化转型的市场速度?

对于许多组织来说,数字化转型是一个非常缓慢而痛苦的过程。根据行业统计,70%到 80%的数据科学项目没有达到预期。

让我们探究为什么…

这一探索为什么数据科学解决方案无法达到预期结果的尝试是基于我自己的个人经历,从其他世界的经历中得到验证,并得到了我的另一半 Arshad 的贡献。我相信会有其他观点,我乐于听取。

在开始之前,让我简单解释一下数据科学

数据科学是一个多学科领域,通过理解数据模式从结构化和非结构化数据中获取相关见解,从而预测未来。数据科学是一门艺术和科学,它使用数学、机器学习、计算机编程、统计建模、数据工程和可视化、模式识别和学习、不确定性建模、数据仓库和云计算。

我们是否了解富达正在努力解决的业务痛点?

大多数数据科学项目都是从高层次的目标开始,没有足够清晰的细节。让我们用一个例子来检验

高层次目标-增加业务部门或特定产品组合的销售额。

  • 是否有我们正在努力解决的特定最终用户/业务难题,或者我们正在解决的业务期望是什么?一个企业 可能正在努力理解基于动态市场条件增加产品组合销售的杠杆。
  • 预期用途是什么,谁将使用该解决方案,他们将如何使用该解决方案? 品类经理希望做一个假设分析,以了解如果他们增加/减少一个影响因素,会对销售产生多大影响。
  • 如何衡量数据科学解决方案的成功? 本季度产品组合的销售预测应该在实际销售额的 15%-20%上下,或者企业是否希望了解趋势,或者他们只是希望了解可以用来更好地管理销售的杠杆。

一旦我们清楚了为什么我们需要数据科学解决方案来解决业务问题,我们就可以开始设计解决方案来解决什么问题和如何解决。

为了让数据科学解决方案取得成功,我们使用了极限协作方法

极端协作:持续协调协作问题定义、解决方案设计,以及与所有利益相关方一起优先考虑具有最高业务价值的业务目标

合作理解并设定现实的期望

业务/终端用户有他们希望数据科学解决方案解决的痛点或期望。即使需求有冲突,我们也需要理解不同利益相关者的期望。这包括最终用户、与问题密切相关的任何人,还包括领导团队。

我们需要使用极端的协作方法来考虑利益相关者的所有需求,如采访不同的利益相关者以获得不同的观点,通过观察他们和举办设计研讨会来了解客户的旅程。这些将在下面用来理解业务需求的工具和技术中详细提及。

有时,利益相关者可能有不切实际的期望。期望需要重新设定,以设定正确的范围和成功标准。所有利益相关方应就范围和成功标准达成一致。在某些情况下,我们可能认为一个小的业务流程变化就能解决问题,而不是一个复杂的数据科学解决方案。因此,这是设定正确方向的非常关键的一步。

基于业务价值协作确定业务目标的优先级

毕竟,利益相关者有共同和明确的期望,优先考虑痛点或期望。这需要所有利益相关者的合作,我称之为极端合作。极度协作是建立在彼此的想法和优势之上,以实现共同的目标或目的

在确定了业务目标之后,对具有最大业务价值的难点或期望结果进行优先级排序,业务价值可以根据

  • 数字化转型让您的组织更上一层楼。通过量化上市延迟的成本,可以很好地理解这一点。
  • 业务或流程改进。如果流程改进完成了,投资回报会是多少?
  • 确保生物的安全。生物安全和可持续生活的环境与商业收益一样重要

在协作确定优先级时,我们还需要考虑以下问题

  • 数据充足性挑战: 正确数据的可用性是一项挑战。我们可能没有解决问题所需的所有关键数据元素,或者数据标签可能是问题所在
  • 数据质量问题: M 缺失数据、不一致的数据、不兼容的数据格式是大多数非数字化组织的常见问题
  • 数据安全: 保护数据免受内部和外部风险。数据敏感性分类不正确可能会成为安全威胁

谁最适合适度的业务期望和业务目标的优先级?

这个练习最好由了解业务的人来完成,他们可以用自己的语言交流,而不会被技术细节所困扰。对数据有很好的理解,对数据科学有详细的了解,能够使用技术语言。在与业务人员交谈时,反映业务术语的用法是关键,同样,向数据科学团队反映数据科学术语的用法有助于弥合差距。

有哪些工具和技术可以用来理解业务需求?

探索客户之旅,了解当前问题以及他们对解决方案的期望。这可以通过以下方式实现

  • 采访不同但相关的业务领域。每个小组都有不同的视角,这将有助于构建更大的图景。对于产品组合的销售预测,与销售和营销团队、品类经理、生产团队、财务团队讨论,以构建更大的图景。
  • 观察最终用户的行动,如有可能。这将有助于了解他们当前的切入点,也有助于通过了解终端用户使用的数据来设计数据科学解决方案
  • 获取利益相关者之外的不同观点:通过在白板上陈述要解决的问题,搅动海洋以获得清晰的观点。让组织中的其他人提出他们的观点。在与所有利益相关者的共同会议中进行讨论后,根据相关性和事实筛选出观点
  • 设计或解决方案研讨会用业务用户自己的语言向他们重述痛点和旅程。在这里,我们会仔细考虑所有相互冲突的要求,考虑所有不同的观点,并就数据科学解决方案的期望和商业价值达成一致,该解决方案涉及包括领导团队在内的所有利益相关方

极端协作的优势是多方面的

  • 痛点、期望和想法的交流有助于清晰地阐明潜在的问题。
  • 每个既是问题的一部分又是解决方案的一部分的人都说同样的语言,并且更好地理解彼此的世界
  • 由于假设大大减少,澄清是即时的
  • 过度沟通可能会发生,但这比沟通不足和做出错误假设要好

他们是否有与不同利益相关者合作的规则?

  • 设定正确的期望:所有利益相关方应对为什么需要数据科学解决方案以及该解决方案将实现的目标有一个共同的看法
  • 减少/消除假设:小组做出的任何假设都将得到讨论和验证。如果假设无法得到验证,那么就让数据来说明问题。
  • 多学科团队的协作:一个团队的强大取决于它相互协作以及与其他团队为业务目标而工作的能力。致力于数据科学解决方案的不同学科必须协同工作,以减少返工

协作消除了假设,在不同的团队和团队成员之间建立了信任,并创造了一个发挥彼此优势的环境

总是进行小的、增量的、迭代的解决方案开发

通过短时间、快速、迭代的增量周期来获取业务数据洞察,这使得数据科学解决方案变得异常重要。这是一种快速而正确的快速进近

这种方法有两方面的帮助:

  • 快速准确的数据和业务知识。
  • 理解什么与我们试图解决的问题相关,什么不相关的能力。不是所有的数据都是好的。

快速失败和立即纠正的好处

企业对将要实现的目标有了清晰的了解,对不断变化的市场趋势有了数据洞察。数据工程团队可以更好地了解需要提供给数据科学团队的相关数据,数据科学团队可以构建多个模型,然后决定哪一个模型更适合当前的问题。

成功执行数据科学解决方案的态度

拥抱失败,不断学习

失败是件好事,因为它教会你错过了什么。对于每一次迭代,理解什么对解决方案有效,什么无效。就下一步的改进措施进行头脑风暴讨论。

失败不是致命的,但不承认失败并从中吸取教训绝对是致命的

"成功不是最终的,失败也不是致命的:重要的是继续下去的勇气."——温斯顿·丘吉尔

持续学习、监控和改进是成功的关键。失败只是成功的垫脚石。

所有利益相关方持续学习数据科学基础知识、数据和模型改进,以达到成功标准。

当设定对数据科学解决方案的期望或成为数据科学解决方案的一部分时 “无知根本不是福”。

了解可以利用数据科学的领域对企业有好处。

同样,对于数据工程、数据科学和数据可视化团队成员来说,拥有扎实的业务理解也非常重要。

数据科学解决方案的所有利益相关方需要理解并使用同一种语言。这确保了团队中的每个人都清楚地相互理解,这对成功非常关键

总结要点以满足对数据科学解决方案的期望:

  • 明确业务期望/痛点。我们为什么选择数据科学解决方案,谁将使用该解决方案,以及如何使用该解决方案。
  • 为理解所有利益相关方并为其设定现实的期望而进行的极端协作
  • 使用极限协作,根据业务价值确定业务目标的优先级
  • 使用工具和技术找出潜在的问题和棘手问题
  • 短而快速的迭代增量循环解决问题。一次一步
  • 拥抱失败,并通过短时间的反复循环从失败中学习
  • 确保所有利益相关者使用相同的易于理解的语言,不使用团队中每个人都不理解的任何技术术语。
  • 所有交叉学科之间的交叉教育是强制性的

分享你的想法,评论!!!

参考资料:

[## 为什么您没有从数据科学中获得价值

当今的企业不断产生大量数据,但这并不总是转化为可操作的数据…

hbr.org](https://hbr.org/2016/12/why-youre-not-getting-value-from-your-data-science) [## Gartner 表示,近一半的首席信息官正计划部署人工智能

据 Gartner 公司称,有意义的人工智能(AI)部署才刚刚开始

www.gartner.com](https://www.gartner.com/en/newsroom/press-releases/2018-02-13-gartner-says-nearly-half-of-cios-are-planning-to-deploy-artificial-intelligence)

如何部署机器学习模型

原文:https://towardsdatascience.com/how-to-deploy-a-machine-learning-model-dc51200fe8cf?source=collection_archive---------5-----------------------

机器学习

使用 FastAPI+uvicon 创建生产就绪的 API

Photo by SpaceX on Unsplash

你在网上看到的任何机器学习文章都在讨论模型的复杂性以及如何正确应用它们。尽管这些文章可能很有趣也很有价值,但只有少数文章考虑了创建模型后会发生什么:

部署 ML 模型需要哪些步骤?

不幸的是,我能找到的大多数文章都讨论了如何使用 Flask 快速创建端点,但是没有意识到 Flask 本身很难用于生产。

从命令行运行 Flask 时,您首先看到的是以下内容:

显然,要使它完全投入生产,还需要做更多的工作和考虑。

部署模型时要考虑的事情

  • 扩展您的 API
  • 容器化您的 API 环境
  • 记录您的 API
  • 重新训练您的模型以避免模型漂移
  • 记录您的 API 和模型
  • 云还是内部部署?

在本文中,我们将一起经历几个步骤,让您的 API 为生产做好准备,无论是在本地还是在云上,重点是文档、日志和伸缩。

我们将使用 FastAPI 代替 Flask。这并不是因为 Flask 有什么问题,而是我相信 FastAPI 可以让你更快地投入生产。

文档结构

你可以在这里从得到所有的数据和文件。对于本指南,请确保您的文档结构如下:

.
├── **app**
│   └── main.py
│   └── sample.log
│   └── **data** │         └── encoder.pickle
│         └── features.pickle
│         └── model.pickle
│
├── **notebooks** │   └── preprocessing.ipynb
│   └── test_connection.ipynb
│   └── data.csv
│
├── requirements.txt
└── Dockerfile

这将有助于防止错误,尤其是在创建 Docker 容器时。

1.准备文件

我们将要部署的模型用于预测人员流动。你可以在这里得到数据。前几行如下所示:

我们首先加载数据并保存我们希望在模型中使用的特征的名称。这有助于跟踪列的顺序。当您指的是薪水时,您不希望意外地输入年龄值。

接下来,由于列 SalesSalary 是分类的,我们将应用并保存一个 hot 编码实例。一键编码将一个列转换为具有 0 或 1 的 n 列,其中 n 等于唯一类别的数量。我这样做是因为它在部署您的模型时显示了一些额外的复杂性。

最后,我使用现成的 LightGBM 分类器来预测营业额。该模型被保存,以便可以在我们的 API 中使用。

Preprocessing the data and creating the model

在我们准备好数据并保存了所有必要的文件之后,是时候开始创建 API 来服务我们的模型了。

注意:保存模型有几种方法,每种方法都有自己的优缺点。除了酸洗,你还可以使用 Joblib 或者使用 LightGBM 的内部程序。

2.生产就绪 API

生产通常意味着终端用户可以访问的 API 形式的端点。对于 python 来说,有很多选择,比如烧瓶、猎鹰、小星星、 Sanic 、 FastAPI 、龙卷风等。

FastApi

出于三个原因,我们将在本文中使用 FastApi:

  • 像 Flask 一样,您可以用最小代码设置一个端点
  • 它是难以置信的快,它的速度与 NodeJS 和 Go 不相上下
  • 自动创建open API(Swagger)和 ReDoc 文档

然而,这是个人经验,幸运的是,您可以很容易地将 FastApi 换成其他东西。

紫玉米

我们用 Uvicorn 来服务我们的 FastAPI 服务器。与更传统的 WSGI 服务器相比,Uvicorn 是允许异步进程的 ASGI 服务器。这将加快应用程序的速度,并使您更接近生产性能。

美国石油学会

首先,我们需要安装 FastAPI 和 Uvicorn:

pip install fastapi
pip install uvicorn

安装完必要的包后,我们可以开始创建主文件。在这个文件中,我们确保加载了之前保存的所有必要文件。

然后,我们创建一个名为Data的类,它定义了模型中使用的所有变量。这有助于跟踪我们使用的变量,而且还基于我们创建的类创建文档。

最后,我们创建了预测方法。在这种情况下,数据被提取出来并按正确的顺序排列。像我们之前所做的那样,应用了一键编码。然后,预测以 0 或 1 的形式返回。

main.py

现在我们已经安排好了一切,我们可以从您的控制台使用以下命令加载服务器:

uvicorn main:app

main是指文件的名称(main.py ),而app是指 main.py 中 FastApi 实例的名称。如果一切正常,您可以看到服务器运行在 http://127.0.0.1:8000 。

要测试它是否返回预测,您可以运行以下代码:

还可以用 Postman 测试 API,这是一个很棒的 API 开发工具。

虽然从技术上讲,您的 API 现在可以用于生产,但是包含文档、记录 API 中发生的事情以及将您的解决方案容器化将会很有帮助。

3.证明文件

很有可能您不是在现有服务中实现 API 的人。如果您记录了端点,以便可以毫无困难地使用它,那就更好了。幸运的是,FastApi 会基于我们之前创建的Data类自动创建文档。

FastApi 有自动文档内置的方法:OpenApi (Swagger)和 ReDoc。

OpenApi

启动 FastAPI 服务器后,您可以访问http://127 . 0 . 0 . 1:8000/docs查看自动生成的服务器文档。你甚至可以按“试试看”来看看服务器是否如预期的那样工作。

雷多克

像 OpenAPI/Swagger 一样,ReDoc 生成参考文档。它通过允许您创建一个高度可定制的基于 react 的模板来扩展它们。FastAPI 在http://127 . 0 . 0 . 1:8000/redoc自动创建文档。

:如果你想看 ReDoc 的大范围现场版,可以去看看http://redocly.github.io/redoc/。

4.记录

我见过许多人使用print()语句来跟踪他们代码内部发生的事情。这对小型应用程序来说没问题,但是当您在开发测试验收生产 (DTAP)之间切换时,您可能不想显示相同的消息。

这就是日志的用武之地。它允许您为应用程序设置特定的日志记录级别,并且只在超出该级别时显示消息。

我们的 API 将受益于日志,主要有两个原因:

  • 我们可以跟踪 API 是否还在工作,以及它遇到了哪些问题
  • 我们可以跟踪模型的输入并检查其性能

如果我们保留所有输入数据以便进一步分析,这将非常有趣。这将为我们提供以前从未见过的数据信息,并可能改进模型。

日志记录级别

有些错误可能不如其他错误有趣。在生产中,您可能希望显示致命错误,而不是应用程序的进度信息。当您调试应用程序时,这可能会有所不同。

为了解决这个问题,我们可以使用日志记录的:

  • **DEBUG** —调试应用程序时有用的信息。值= 10
  • **INFO** —申请进度信息。值= 20
  • **WARNING** —关于潜在有害情况的信息。值= 30
  • **ERROR** —关于非致命错误的信息。值= 40
  • **CRITICAL** —关于严重和致命错误的信息。值= 50

如果我们将记录器设置在**WARNING**级别,那么将只显示**WARNING****ERROR****CRITICAL**

本地记录器

为了在本地使用记录器,我们初始化记录器并设置其最低级别:

import loggingapp = FastAPI()# Initialize logging
my_logger = logging.getLogger()
my_logger.setLevel(logging.DEBUG)

最低级别现在设置在**DEBUG**,这意味着基本上所有级别的记录都会显示。当你将你的模型投入生产时,我建议你将它设置为**WARNING**

要使用记录器,只需调用它并指定日志记录的级别。该消息将被打印到控制台:

my_logger.error("Something went wrong!")

现在,你可能想要保存日志到一个文件。为此,只需用此语句代替上面的setLevel:

logging.basicConfig(level=logging.INFO, file='sample.log')

5.使用 Docker

既然我们已经有了要部署的 API,我们可能希望使用 Docker 将应用程序容器化。Docker 将您的应用程序及其所有依赖项打包,以确保它在任何环境下都能无缝工作。这使得跨环境部署应用程序变得更加容易,而不需要太多额外的集成步骤。

首先确保你已经安装了 Docker 。因为我们希望有一个跨环境的稳定的应用程序,所以为应用程序指定一个requirements.txt 是很重要的。

下一步是创建 Dockerfile 本身,它是运行我们的 API 的一个包含版本所需要的。幸运的是,FastAPI 的开发人员已经创建了 python 映像,允许在适当的环境中运行 FastAPI:

Dockerfile

将上面的代码保存在 docker 文件中,导航到该文件夹并运行以下命令:

docker build -t myimage ./
docker run -d --name mycontainer -p 80:80 myimage

这将构建并运行我们在 Dockerfile 文件中指定的映像。

您的 API 现在已经准备好了,可以从 http://127.0.0.1/docs 访问。

结论

在这个(有点)全面的指南中,我们已经经历了为您的模型创建 API 和将应用程序容器化的 5 个步骤。现在,您可以选择在本地托管它,或者通过云解决方案(如 AWS 或 Azure)部署 Docker。

请注意,我试图尽可能全面地阐述这一点,同时包括我认为重要的主题。但是,一些更高级的主题被排除在外,例如:

  • 处理概念漂移
  • 保护您的 API
  • 配置 Gunicorn 服务器
  • 为不同阶段创建单独的 docker 文件(DTAP)
  • 使用 CI/CD 自动重新训练您的模型
  • 使用 Kubeflow 和 Kubernetes 简化生产
  • 等等。

所有的代码都可以在这里找到:

[## 马尔滕格尔/毫升-API

关于创建一个生产就绪的 API 来为您的 ML 模型服务的指南。

github.com](https://github.com/MaartenGr/ML-API)

感谢您的阅读!

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

如何从贝鲁特部署神经网络

原文:https://towardsdatascience.com/how-to-deploy-a-neural-network-from-beirut-3e4db10fe525?source=collection_archive---------19-----------------------

Photo by Zheka Boychenko on Unsplash

贝鲁特是黎巴嫩华丽的首都,也伴随着繁华都市的典型问题。除此之外,它还遭受着频繁的停电和世界上最慢的互联网连接之一。

这里也是我度过暑假的地方,也是本文的理想试验场:如何用亚马逊的 SageMaker 和 PyTorch 以 web 应用的形式部署神经网络。

在继续之前,建议将存储库克隆到 SageMaker 中,以遵循这个漫长的过程。整个项目从开始到结束都托管在这个 GitHub 库中。

下载数据

对于这个任务,我们将使用 Maas 等人的 IMDb 数据集,它包含 25,000 条用于训练的高度极性电影评论,以及 25,000 条用于测试的评论。我们创建一个目录并下载数据:

加工和清洁

Photo by Pablo Lancaster Jones on Unsplash

下载完数据后,我们需要将其转换成可读的格式。下面的 read_ibmd_data 函数读入每个评论,并将它们组合成一个单一的输入结构。

然后,我们将正面和负面的评论结合起来,并使用 prepare_imdb_data 函数对结果记录进行洗牌。

在继续之前,让我们检查一下我们做得怎么样。下面的评论值为 1,表示它是正面的。

Contains *spoilers* - also, my quotes may not be exact.<br /><br />Everyone always notes the satire in social commentary and economic parallels - how true. But to me, I see this movie as much more than that. I love the symbolism of this guy in a glowing white suit. There is so much confusion and filth in the world around him, but it won't stick. Alec Guiness was the perfect guy to play this - his boyish grins and eternal curiousity are so appropriate:<br /><br />"That's ingenious - can you tell me, what is the ratio of ink to petrol?"<br /><br />The only moment of defeat is when he realizes that his invention hasn't worked after all - standing there almost naked. Yet, more than shame is the simple disappointment that "it didn't work." He's never really intimidated by people. Remember,<br /><br />"But Sidney, we want to stop it too."<br /><br />Barely a moments hesitation before he's off trying to get away again. Does he show any sign of the pain such a betrayal must've caused? No.<br /><br />Also notable is Dapne's role. She is sick and tired of money and power. She thinks she's finally found love, outside of her father's company. At first she doesn't really care about Sidney anymore than anyone else. But that moment when he falls off her car and she goes back to see if maybe she killed him - and yet he is still thinking only of the beauty of his invention. She's finally found something she thinks is worth living for. The funny thing is that it's not even romance. It is friendship, but of such an ephemeral nature that the title almost doesn't fit. It's more admiration, and perhaps even inspiration.<br /><br />Upon her discovery that Michael has no real love for her, and that her father is completely incompetent to take care of her, she gives into cynicism and tries to temp Sidney. Fortunately she finds that there really are people in this world living for more than power, money and lust. What a refreshment:<br /><br />"Thank you Sidney. If you would've said 'yes' I think I'd have strangled you."<br /><br />I love the very end, when all of this crazy business seems to have come to nothing. But then, the bubbly, quirky beat starts up and Sidney goes off, his stride matching the tune: dauntless. Where is Daphne? We don't really know - but they weren't really in love and she wasn't really a scientist. He got help escaping and she got "a shot in the arm of hope." (Pollyanna) A cont'd relationship would've been nice, but as Billy Joel says "it's more than I'd hoped for..."<br /><br />

巧合的是,这是一篇很长的评论,但是略读就能看出它是积极的。它带有许多 html 标签,我们将删除这些标签,因为它们没有增加情感价值。我们还想对我们的输入进行标记,以便在进行情感分析时,像娱乐娱乐这样的词被认为是相同的。

review_to_words 助手函数就是这样做的,它依赖于 NLTK 库。

我们在下面的预处理 _ 数据函数中使用审查 _ 到 _ 单词。它读入数据并缓存结果。这是因为执行该处理步骤可能需要很长时间。这样,如果我们无法在当前会话中完成笔记本,我们可以返回,而无需再次处理数据。

转换数据

Photo by Quino Al on Unsplash

对于我们将在本笔记本中实现的模型,我们将为所有单词构建一个特征表示,作为将评论中出现的单词映射到整数的一种方式。首先,我们将每个单词表示为一个整数。然而,评论中出现的一些词很少出现,因此可能不包含太多用于情感分析的信息。

我们处理这个问题的方式是,我们将固定我们工作词汇的大小,我们将只包括最频繁出现的单词。然后,我们将把所有不常用的单词组合成一个类别,在我们的例子中,我们将把它标记为 1

由于我们将使用递归神经网络,如果每次复习的时间长度相同,将会很方便。为了做到这一点,我们将确定评论的大小,然后用“无词”类别填充短评论(我们将把它标记为 0 ),并截断长评论。

build_dict 实现了对数据的特征转换。注意,即使 vocab_size 被设置为 5000 ,我们只想为最频繁出现的 4998 个单词构建一个映射。这是因为我们想为'无字'保留特殊标签 0 ,为'生僻字'保留特殊标签 1

我们评论中最常见的五个词是什么?不出所料他们是: movifilmoneliketime

稍后,当我们构建一个端点来处理提交的评审时,我们将需要使用我们已经创建的 word_dict 。因此,我们现在将它保存到一个文件中以备将来使用。

现在我们有了单词字典,它允许我们将评论中出现的单词转换成整数,我们使用它将评论转换成它们的整数序列表示,确保填充或截断到固定长度,在我们的例子中是 500

我们首先创建 convert_and_pad 函数来填充单个审查。

然后我们在 convert_and_pad_data 中实现它,将其应用于整个数据。

让我们回顾一下在上面的步骤中我们做了什么。为了处理短评论和长评论,我们将所有评论填充或删减到特定长度。对于短于某个填充长度的评论,我们将用 0 填充。这可能会导致内存问题,但这是标准化评论的必要步骤。

当我们构建包含所有词汇的 word_dict 变量时,我们只使用了训练数据。这意味着在训练和测试数据集之间不会发生数据泄漏。然而,如果训练数据集不是详尽的,我们将会遇到限制。

上传到 S3

我们需要将训练数据集上传到一个简单的存储服务( S3 )中,以便我们的训练代码能够访问它。现在我们将把它保存在本地,稍后我们将上传到 S3。

注意我们保存的数据的格式是很重要的,因为我们在编写训练代码时需要知道它。在我们的例子中,数据集的每一行都具有形式为的标签的长度的评论【500】,其中评论【500】是表示评论中单词的 500 整数序列。

接下来,我们需要将训练数据上传到 SageMaker 默认 S3 存储桶,以便在训练我们的模型时可以访问它。

下面的代码块上传了我们的数据目录的全部内容。这包括 word_dict.pkl 文件。这是幸运的,因为我们将在稍后创建接受任意审查的端点时需要它。现在,我们将只注意到这样一个事实,即它驻留在数据目录中(因此也在 S3 培训桶中),并且我们将需要确保它保存在模型目录中。

构建和培训 PyTorch 模型

Credits: Udacity

SageMaker 上的模型由三个对象组成:

  • 模型工件
  • 培训代码
  • 推理代码

每个组件都相互作用。这里我们将使用 Amazon 提供的容器,并编写我们自己的定制训练和推理代码。

我们将从在 PyTorch 中实现我们自己的神经网络以及一个训练脚本开始。出于这个项目的目的,我们在火车文件夹内的 model.py 文件中提供了必要的模型对象。下面的代码块展示了实现。

我们可能希望调整三个参数来提高模型的性能:

  • 嵌入维度
  • 隐藏维度
  • 词汇量

我们可能希望在训练脚本中配置这些参数,这样,如果我们希望修改它们,就不需要修改脚本本身。首先,我们将编写一些训练代码,这样我们可以更容易地诊断出现的任何问题。

首先,我们将加载一小部分训练数据集作为样本。尝试在笔记本中完全训练模型将非常耗时,因为我们无法访问 GPU,并且我们使用的计算实例不是特别强大。然而,我们可以处理一小部分数据来感受一下我们的训练脚本是如何运行的。

接下来,我们需要编写训练代码本身。我们将把复杂的方面,如模型保存/加载和参数加载留到稍后。

假设我们有上面的训练方法,我们将通过编写代码来测试它是否工作,该代码在我们之前加载的小样本训练集上执行我们的训练方法。尽早这样做的原因是为了让我们有机会修复早期出现的、更容易诊断的错误。

为了使用 SageMaker 构建 PyTorch 模型,我们必须为 SageMaker 提供一个训练脚本。我们可以选择包含一个目录,这个目录将被复制到容器中,我们的训练代码将从这个目录中运行。当执行训练容器时,它将检查上传目录(如果有)中的 requirements.txt 文件,并安装任何所需的 Python 库,之后将运行训练脚本。

当在 SageMaker 中构造 PyTorch 模型时,必须指定一个入口点。这是将在模型训练时执行的 Python 文件。在 train 目录中有一个名为 train.py 的文件,它包含了训练我们的模型所需的大部分代码。唯一缺少的是我们之前编写的 train() 方法的实现。

SageMaker 将超参数传递给训练脚本的方式是通过参数。然后,这些参数可以被解析并在训练脚本中使用。要了解这是如何完成的,请随意查看提供的 train/train.py 文件。

部署测试模型

既然我们已经训练了我们的模型,我们想要测试它,看看它的表现如何。目前,我们的模型接受形式为 review_lengthreview[500] 的输入,其中 review【500】是一系列 500 整数,它们描述了评论中出现的单词,使用 word_dict 进行编码。幸运的是,SageMaker 为具有简单输入的模型提供了内置的推理代码。

我们需要提供一个函数来加载保存的模型。这个函数必须被调用 model_fn() ,并把模型工件存储目录的路径作为它唯一的参数。这个函数也必须存在于我们指定为入口点的 python 文件中。在我们的例子中,已经提供了模型加载功能,因此不需要进行任何更改。

注意,当运行内置推理代码时,它必须从 train.py 文件中导入 model_fn 方法。这也是为什么训练代码被包裹在一个主护中(即if _ _ name _ _ = ' _ _ main _ _ ':)

由于我们不需要对培训期间上传的代码进行任何修改,我们可以简单地按原样部署当前的模型。

在部署模型时,我们要求 SageMaker 启动一个计算实例,该实例将等待数据发送给它。因此,该计算实例将继续运行,直到关闭。了解这一点很重要,因为部署端点的成本取决于它已经运行了多长时间

使用模型进行测试

部署完成后,我们可以读入测试数据,并将其发送到我们部署的模型,以获得一些结果。一旦我们收集了所有的结果,我们就可以确定我们的模型有多精确。

我们现在有一个经过训练的模型,该模型已经部署,我们可以向其发送经过处理的评论,并返回预测的情绪。然而,最终我们希望能够给我们的模型发送一个未处理的评审。也就是说,我们希望将评论本身作为一个字符串发送。例如,假设我们希望向我们的模型发送以下评论。

我们现在需要回答的问题是,我们如何将这个评论发送给我们的模型?

回想一下,在前面的部分中,我们做了两件事:

  • 移除所有 html 标签并阻止输入
  • 使用 word_dict 将评论编码为一个整数序列

为了进行审核,我们需要重复这两个步骤。使用之前的 review_to_wordsconvert_and_pad 方法,我们将 test_review 转换成一个名为 test_data 的 numpy 数组,适合发送给我们的模型。回想一下,我们的模型期望输入形式为 review_lengthreview[500] 。然后我们可以使用预测器对象来预测情绪。

Web 应用程序的部署模型

Photo by SpaceX on Unsplash

现在我们知道我们的模型正在工作,是时候创建一些定制的推理代码了,这样我们就可以向模型发送一个尚未处理的评论,并让它决定评论的情绪。

正如我们在上面看到的,默认情况下,我们创建的评估器,在部署时,将使用我们在创建模型时提供的入口脚本和目录。然而,由于我们现在希望接受一个字符串作为输入,并且我们的模型期望一个经过处理的审查,我们需要编写一些定制的推理代码。

我们将把编写的代码存储在目录中。这个目录中提供的是我们用来构建模型的 model.py 文件,一个 utils.py 文件,它包含我们在初始数据处理过程中使用的 review_to_wordsconvert_and_pad 预处理函数,以及 predict.py ,这个文件将包含我们的定制推理代码。还要注意的是, requirements.txt 会告诉 SageMaker 我们的定制推理代码需要哪些 Python 库。

在 SageMaker 中部署 PyTorch 模型时,我们需要提供 SageMaker 推理容器将使用的四个函数。

  • model_fn:这个函数与我们在训练脚本中使用的函数相同,它告诉 SageMaker 如何加载我们的模型。
  • input_fn:这个函数接收已经发送到模型端点的原始序列化输入,它的工作是反序列化输入,使输入可用于推理代码。
  • output_fn:这个函数获取推理代码的输出,它的工作是序列化这个输出,并将其返回给模型端点的调用者。
  • predict_fn:推理脚本的核心,这是进行实际预测的地方。

对于我们在这个项目中构建的简单网站,我们只需要能够接受一个字符串作为输入,我们希望返回一个单一的值作为输出。我们可以推断,在更复杂的应用程序中,输入或输出可能是图像数据或其他一些二进制数据,这需要更多的努力来序列化。

serve/predict.py 中,我们编写如下推理代码:

既然已经编写了定制推理代码,我们将创建并部署我们的模型。首先,我们需要构造一个新的 PyTorch 模型对象,它指向训练期间创建的模型工件,还指向我们希望使用的推理代码。然后我们可以调用 deploy 方法来启动部署容器。

既然我们已经用定制推理代码部署了我们的模型,我们应该测试一下是否一切正常。这里,我们通过加载第一个 250 正面和负面评论来测试我们的模型,并将它们发送到端点,然后收集结果。只发送部分数据的原因是,我们的模型处理输入然后执行推理所花费的时间相当长,因此测试整个数据集是不允许的。

为 Web 应用程序使用模型

现在我们知道我们的端点正在按预期工作,我们可以设置与之交互的 web 页面。

到目前为止,我们一直通过构建一个使用端点的预测器对象来访问我们的模型端点,然后只使用预测器对象来执行推理。如果我们想创建一个访问我们模型的 web 应用程序会怎么样?

目前的设置方式使得这不可能,因为为了访问 SageMaker 端点,应用程序必须首先使用 IAM 角色向 AWS 进行身份验证,其中包括对 SageMaker 端点的访问。但是,有一个更简单的方法!我们只需要使用一些额外的 AWS 服务

Credits: AWS

上图概述了各种服务将如何协同工作。最右边是我们上面训练过的 endoint 模型,它是使用 SageMaker 部署的。最左边是我们的 web 应用程序,它收集用户的电影评论,发送出去,并期望得到正面或负面的反馈。

在中间,我们将构建一个 Lambda 函数,我们可以把它想象成一个简单的 Python 函数,只要特定的事件发生,它就可以被执行。我们将授予该函数从 SageMaker 端点发送和接收数据的权限。

最后,我们将用来执行 Lambda 函数的方法是我们将使用 API Gateway 创建的一个新端点。这个端点将是一个 url,它侦听要发送给它的数据。一旦它得到一些数据,它将把这些数据传递给 Lambda 函数,然后返回 Lambda 函数返回的任何内容。本质上,它将充当一个接口,让我们的 web 应用程序与 Lambda 函数进行通信。

设置 Lambda 函数

每当我们的公共 API 接收到数据时,Lambda 函数就会被执行。当它被执行时,它将接收数据,执行任何需要的处理,将数据(评论)发送到我们创建的 SageMaker 端点,然后返回结果。

因为我们希望 Lambda 函数调用 SageMaker 端点,所以我们需要确保它有这样做的权限。为此,我们将构造一个角色,稍后我们可以赋予 Lambda 函数。

使用 AWS 控制台,导航到 IAM 页面并点击角色。然后,点击创建角色。确保 AWS 服务是所选的可信实体类型,并选择λ作为将使用该角色的服务,然后单击 Next: Permissions

在搜索框中键入sagemaker并选中amazonsagemakerfullcaccess策略旁边的复选框。然后,点击下一步:复习

最后,给这个角色一个名字。确保你使用一个我们以后会记住的名字,例如lambdasagemakerole。然后,点击创建角色

现在我们可以创建 Lambda 函数。使用 AWS 控制台,导航到 AWS Lambda 页面,点击创建功能。当我们进入下一页时,确保选择了从头开始创作

现在,用一个我们以后会记得的名字来命名这个 Lambda 函数,例如情绪分析函数。确保选择了 Python 3.6 运行时,然后选择在上一部分中创建的角色。然后,点击创建功能

在下一页,我们可以看到一些关于我们刚刚创建的 Lambda 函数的信息。向下滚动可以看到一个编辑器,我们可以在其中编写 Lambda 函数被触发时将执行的代码。在我们的例子中,我们将使用下面的代码。

我们需要将端点名称添加到 Lambda 函数中。在 SageMaker 笔记本中,我们可以获得这个端点名称:

一旦我们将端点名称添加到 Lambda 函数中,点击保存。Lambda 函数现在已经启动并运行。接下来,我们需要为我们的 web 应用程序创建一个执行 Lambda 函数的方法。

设置 API 网关

既然我们的 Lambda 函数已经设置好了,是时候使用 API Gateway 创建一个新的 API 了,它将触发我们刚刚创建的 Lambda 函数。

使用 AWS 控制台,导航到亚马逊 API 网关,然后点击开始

在下一页上,确保选择了新 API ,并为新 API 命名,例如sensation _ analysis _ API。然后,点击创建 API

现在我们已经创建了一个 API,但是它目前什么也不做。我们想要它做的是触发我们之前创建的 Lambda 函数。

选择动作下拉菜单,点击创建方法。将创建一个新的空白方法,选择其下拉菜单并选择 POST ,然后点击旁边的复选标记。

对于集成点,确保选择了 Lambda 函数并点击使用 Lambda 代理集成。该选项确保发送给 API 的数据不经处理直接发送给 Lambda 函数。这也意味着返回值必须是正确的响应对象,因为它也不会被 API Gateway 处理。

Lambda 函数文本输入框中输入之前创建的 Lambda 函数的名称,然后点击保存。在弹出的对话框中点击 OK ,允许 API Gateway 调用您创建的 Lambda 函数。

创建 API 网关的最后一步是选择动作下拉菜单并点击部署 API 。我们需要创建一个新的部署阶段,并将其命名为相关的名称,例如 prod

我们现在已经成功地建立了一个公共 API 来访问您的 SageMaker 模型!请确保复制或记下所提供的 URL,以调用新创建的公共 API,因为下一步需要用到它。该 URL 位于页面顶部,在文本调用 URL 旁边以蓝色突出显示。一个示例 URL 如下所示:

与端点相关联的链接是:https://ltii177nx3.execute-api.us-west-2.amazonaws.com/prod

部署 Web 应用程序

现在我们有了一个公开可用的 API,我们可以开始在 web 应用程序中使用它。出于我们的目的,我们有一个简单的静态 html 文件,它可以利用前面创建的公共 API。

网站的文件夹中有一个名为index.html的文件。将文件下载到您的计算机上,并在您选择的文本编辑器中打开该文件。应该有一行包含*** 替换为公共 API URL*** 。用上一步中的 url 替换这个字符串,然后保存文件。

现在,如果您在本地计算机上打开index.html,浏览器将作为本地 web 服务器运行,您可以使用提供的站点与您的 SageMaker 模型进行交互。

更进一步,你可以把这个 html 文件放在任何你想放的地方,例如使用亚马逊 S3 上的静态站点。

结果

让我们看看我们的模型在正面和负面评论中的表现。

恭喜你!你现在有一个神经网络驱动的网络应用程序!

这个项目之所以成为可能,得益于 Udacity 的深度学习 nanodegree。我强烈推荐这门课程,作为获得对人工智能的坚实理解的一种方式!

如何使用 Amazon Free ec2 实例部署 Streamlit 应用程序?

原文:https://towardsdatascience.com/how-to-deploy-a-streamlit-app-using-an-amazon-free-ec2-instance-416a41f69dc3?source=collection_archive---------2-----------------------

Image by Gerd Altmann from Pixabay

10 分钟内将数据应用程序上传到网上

如果我们没有一个好的方式来展示它,机器学习项目就永远不会真正完成。

在过去,一个制作精良的可视化或一个小 PPT 足以展示一个数据科学项目,但随着 RShiny 和 Dash 等仪表板工具的出现,一名优秀的数据科学家需要具备相当多的 web 框架知识。

Web 框架很难学。为了一些看似简单的事情,我仍然会对所有的 HTML、CSS 和 Javascript 感到困惑。

更不用说做同一件事的许多方法,这让我们数据科学的人感到困惑,因为 web 开发对他们来说是次要技能。

这就是 StreamLit 的用武之地,它承诺只用 Python 创建 web 应用。

在我关于 Streamlit 的上一篇文章中,我谈到了如何使用简单的 Python 为数据科学家编写 Web 应用。

但是,一个主要的抱怨,如果你去看看那个帖子的评论部分,是关于不能在网络上部署 Streamlit 应用。

这是一个有效的投诉。

开发人员不能在每次客户想要使用应用程序时都带着笔记本电脑出现。这样的 app 有什么用?

所以在这篇文章中,我们将进一步使用 Amazon Free ec2 实例在 Web 上部署我们的 Streamlit 应用程序。

设置 Amazon 实例

在开始使用 amazon ec2 实例之前,我们需要设置一个实例。您可能需要使用您的电子邮件 ID 注册,并在 AWS 网站上设置支付信息。就像简单的登录一样。从这里开始,我将假设您有一个 AWS 帐户,因此我将解释接下来的重要部分,以便您可以继续操作。

  • 使用https://us-west-2.console.aws.amazon.com/console进入 AWS 管理控制台。
  • 在 AWS 管理控制台上,您可以选择“启动虚拟机”。在这里,我们尝试设置一台机器,用于部署我们的 Streamlit 应用程序。
  • 第一步,您需要为机器选择 AMI 模板。我选择 18.04 Ubuntu 服务器,因为它适用于免费层。还有 Ubuntu。

  • 在第二步中,我选择了t2.micro实例,因为它同样符合自由层的条件。如您所见,t2.micro只是一个具有 512 MB RAM 的 CPU 实例。如果你正在处理一个强大的模型或愿意支付,你可以选择一个更大的机器。

  • 继续按下一步,直到你到达“6。配置安全组”选项卡。您需要添加一个规则,类型为:“自定义 TCP 规则”,端口范围:8501,源:Anywhere。我们在这里使用端口 8501,因为它是 Streamlit 使用的自定义端口。

  • 您可以单击“查看并启动”,最后单击“启动”按钮来启动实例。单击启动后,您可能需要创建一个新的密钥对。在这里,我创建了一个名为 streamlit 的新密钥对,并使用“Download Key Pair”按钮下载它。请妥善保管此密钥,因为每次您需要登录到此特定机器时都会用到它。下载密钥对后,单击“启动实例”

  • 现在,您可以转到您的实例,查看您的实例是否已经启动。提示:查看实例状态,它应该显示“正在运行”

  • 选择您的实例,从描述中复制 公共 DNS(IPv4)地址 。应该是 ec2 开头的东西。
  • 一旦你在你保存了streamlit.pem文件的文件夹中运行以下命令。我在这里屏蔽了一些信息。
chmod 400 streamlit.pemssh -i "streamlit.pem" ubuntu@<Your Public DNS(IPv4) Address>

安装所需的库

哇,那可真难。完成上述所有步骤后,您应该能够看到虚拟机的 ubuntu 提示符。我们需要设置这台机器来运行我们的应用程序。我将使用我在上一篇文章中使用的同一个streamlit_football_demo应用程序。

我们首先安装 miniconda,并将其路径添加到环境变量中。

sudo apt-get updatewget [https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh](https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh) -O ~/miniconda.shbash ~/miniconda.sh -b -p ~/minicondaecho "PATH=$PATH:$HOME/miniconda/bin" >> ~/.bashrcsource ~/.bashrc

然后,我们为我们的应用程序安装额外的依赖项来运行。这意味着我安装了 streamlit 和 plotly_express 。

pip install streamlit
pip install plotly_express

我们的机器已经准备就绪,可以运行了。

在 Amazon ec2 上运行 Streamlit

当我设置好实例后,我可以从 Github 获取我的演示应用程序的代码。或者你可以选择创建或复制另一个应用程序。

git clone [https://github.com/MLWhiz/streamlit_football_demo.git](https://github.com/MLWhiz/streamlit_football_demo.git)cd streamlit_football_demo
streamlit run helloworld.py

现在,您可以转到浏览器并键入外部 URL 来访问您的应用程序。我的地址是[http://35.167.158.251:8501](http://35.167.158.251:8501)。这是输出。如果你想玩这个应用程序,现在就可以打开。

不过这是一个很小的问题

我们已经开始运行我们的应用程序,让全世界都可以看到。但是每当你要关闭 SSH 终端窗口时,这个过程就会停止,你的应用程序也会停止。

那我们怎么办?

TMUX 来救援了。TMUX 允许我们甚至在离开终端窗口后继续运行我们的会话。这也有助于许多其他事情,但我将只是通过我们需要的步骤。

首先,我们停止使用Ctrl+C并安装tmux

sudo apt-get install tmux

我们使用下面的命令启动一个新的tmux会话。我们将会话的名称保留为 StreamSession。这里你可以用任何名字。

tmux new -s StreamSession

您可以在屏幕底部看到会话名称为“StreamSession”。您现在可以在tmux会话中开始运行 streamlit。

streamlit run helloworld.py

您将能够在[外部 URL](http://35.167.158.251:8501/) 看到您的应用。 下一步是分离我们的 TMUX 会话 ,这样当您离开 SSH shell 时,它将继续在后台运行。为此,只需按下Ctrl+B and then D(按 D 时不要按 Ctrl)

您现在可以关闭您的 SSH 会话,应用程序将继续在外部 URL 运行。

瞧啊。我们开始运行了。

Pro TMUX 提示: 您可以使用下面的attach命令重新连接到同一个会话。最棒的是,您可以关闭 SSH shell,然后几个小时后再回来,重新连接到一个会话,从关闭 SSH shell 时所在的位置继续工作。

tmux attach -t StreamSession

简单的故障排除:

如果您的应用没有在 8501 托管, 这意味着 streamlit 应用的一个实例已经在您的系统上运行,您需要停止它。为此,您可以首先找到进程 ID

ps aux | grep streamlit

您将看到如下内容:

ubuntu   **20927**  2.4 18.8 713780 189580 pts/3   Sl+  19:55   0:26 /home/ubuntu/miniconda/bin/python /home/ubuntu/miniconda/bin/**streamlit** run helloworld.py

你将需要 杀死这个进程。你可以简单地通过

kill -9 20947

结论

Our Final App

Streamlit 使创建应用程序的整个过程民主化了,我不能再推荐它了。如果你想了解更多关于如何用 Streamlit 创建令人敬畏的网络应用程序,那么请阅读我的上一篇帖子。

在本帖中,我们 使用亚马逊 ec2 在 AWS 上部署了 一个简单的 web app。

在这个过程中,我们创建了自己的 Amazon ec2 实例,登录到 SSH shell,安装了 miniconda 和依赖项,运行了我们的 Streamlit 应用程序并了解了 TMUX。一天的学习够吗?

所以去展示这些疯狂的技能吧。以轻松的语气结束,正如斯登冲锋枪·苏特拉在他的讽刺作品中所说,我非常喜欢:

秘诀:重要的不是你知道什么,而是你表现出什么。

如果你想了解更多关于如何构建机器学习项目和最佳实践的信息,我想调出他在 Coursera 深度学习专业化中出色的第三门课程名为构建机器学习项目。一定要去看看。

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

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

如何部署大模型

原文:https://towardsdatascience.com/how-to-deploy-big-models-72001ef9ab9e?source=collection_archive---------18-----------------------

AppEngine 和 Kubernetes 上的 500 MB py torch

我最近部署了一个 500MB Pytorch 模型。出乎意料的难!在这篇文章中,我记录了我犯的错误和权衡。

对于非批处理,在 CPU 上运行几乎和 GPU 一样快,所以如果可以的话,我建议从 GPU 开始。

简单的方法会失败

Tensorflow Serving 看起来还可以,但是将我们的模型从 Pytorch 转换成 ONNX 可能会有的困难。我们还想让本地代码尽可能简单,以便于开发。为了确保服务器快速启动,我将模型复制到带有. gitignore 条目的代码库中。我将 pytorch-pretrained-bert 添加到我的 requirements.txt 中,这增加了超过 300MB 的依赖项。

首先我尝试了谷歌 AppEngine (GAE)标准环境。当我尝试部署时,远程构建失败,并显示一条神秘的错误消息。我最终发现这是因为我的应用程序已经超出了远程构建环境的最大值。根据支持论坛,没有办法增加内存限制。

我想也许 Heroku 会支持更大的有效载荷,但它原来有同样的 500MB 限制和一个更合理的错误信息:“编译的 slug 大小:634M 太大了(最大是 500M)。”

然后我设置了一个 docker 容器来部署在 GAE 灵活环境上。这也失败了,因为机器在运行时耗尽了内存,并被无声地终止了。我通过查看内存使用量发现了这一点,并看到它超过了默认限制。我提高了的内存需求,它开始服务了!但是它在服务器上仍然非常慢(仅加载静态页面就需要 30 秒),但是在本地却很快。

我发现主要的区别是 Gunicorn vs Flask 开发服务器。由于某种原因,Gunicorn 没有对健康检查做出反应。我试图在 Flask 中手动实现这些检查,但是没有用。然后我尝试用 Flask dev 服务器进行部署,我知道这是不允许的,因为它不提供像请求队列这样的东西。每个请求都很快,但是 flask dev 服务器不是按比例构建的。我在本地用 Gunicorn 测试了 Docker 容器,发现它和 AppEngine 上的一样慢。我尝试了许多神奇的配置选项,包括详细日志记录,但没有任何帮助或揭示问题。在评估了许多备选方案后,我最终选定了女服务员。这是非常糟糕的记录,但我最终找到了神奇的调用。成功了!

出于某种原因,部署仍然需要一个半永恒的时间(大约 15-30 分钟),所以为了加快速度,我在本地执行我的docker build,然后再执行docker push已经构建好的映像。

添加 GPU 支持

AppEngine 不支持 GPU,所以我用了Google Kubernetes Engine(GKE)。事实证明,仅仅给你的节点添加 GPU 是不够的。您还需要安装驱动程序。创建集群和设置服务应该是这样的:

gcloud config set compute/zone us-west1-b
cloud container clusters create duet-gpu --num-nodes=2 --accelerator type=nvidia-tesla-k80,count=1 --image-type=UBUNTU
gcloud container clusters get-credentials duet-gpu
kubectl apply -f [https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/ubuntu/daemonset-preloaded.yaml](https://raw.githubusercontent.com/GoogleCloudPlatform/container-engine-accelerators/master/nvidia-driver-installer/ubuntu/daemonset-preloaded.yaml)
kubectl apply -f [cloud.yaml](https://github.com/JasonBenn/duet/blob/master/cloud.yaml)

然后使用kubectl get ingress找到你的公共 IP。这需要一分钟来调配。

像 Heroku 和 AppEngine 这样的托管服务试图将开发人员与 DevOps 隔离开来,但这种承诺似乎并没有扩展到大型模型,尤其是 Pytorch 模型。在这篇文章中,我展示了如何使用 Flask 和服务员部署到 GAE 灵活环境和 GKE。现在我有了一个有效的食谱,以后就可以轻松地主持更多的节目了。好的一面是,我们仍然可以从 GAE 免费获得自动缩放、日志记录等功能。对 GKE 来说,这只是一个配置。

你找到更简单的方法了吗?留个条!

如何使用 DeepStream 在 NVIDIA Jetson Nano 上部署 ONNX 模型

原文:https://towardsdatascience.com/how-to-deploy-onnx-models-on-nvidia-jetson-nano-using-deepstream-b2872b99a031?source=collection_archive---------4-----------------------

在 Jetson Nano 上测试 DeepStream 的多流神经网络推理性能的实验。

Jetson Nano. (Source)

将复杂的深度学习模型部署到小型嵌入式设备上是一项挑战。即使有针对深度学习优化的硬件,如 杰特森纳米 和推理优化工具,如 TensorRT ,瓶颈仍然可以在 I/O 管道中出现。如果模型必须处理具有多个输入和输出流的复杂 I/O 管道,这些瓶颈可能会加剧。拥有一个能够以端到端的方式处理所有瓶颈的工具不是很好吗?

向深溪问好

原来有一个 SDK 试图缓解这个问题。 DeepStream 是一款 SDK,针对 NVIDIA Jetson 和 T4 平台进行了优化,以提供无缝的端到端服务,将原始流数据转换为可操作的见解。它构建在 GStreamer 框架之上。在这里,“原始流数据”通常是连续的(和多个)视频流,“可操作的见解”是深度学习或其他分析算法的最终输出。

The DeepStream pipeline. (Source)

DeepStream SDK 使用其定制的 GStreamer 插件来提供各种功能。值得注意的是,它有基于推理和物体跟踪的插件。下图列出了他们插件的功能。关于他们插件的详尽技术指南,你可以参考他们的插件手册。

Plugins available in DeepStream. (Source)

我特别喜欢 DeepStream 的一个特性是,它以流水线方式优化了整个 I/O 处理。我们还可以堆叠多个深度学习算法,异步处理信息。这允许您增加吞吐量,而没有手动创建和管理多处理系统设计的麻烦。

最好的部分是,对于一些支持的应用程序,如对象检测,跟踪,分类或语义分割,DeepStream 易于使用!对于这样的应用,只要你有一个兼容格式的深度学习模型,只需要在一些文本文件中设置几个参数,就可以轻松启动 DeepStream。

在这篇博客中,我们将在 DeepStream 上设计并运行一个实验来测试它的功能,并看看它是否易于在 Jetson Nano 上使用。

实验

为了测试 DeepStream 的功能,让我们在 Jetson Nano 上部署一个预训练的对象检测算法。出于几个原因,这是一个理想的实验:

  • DeepStream 针对英伟达 T4 和杰特森平台上的推理进行了优化。
  • DeepStream 有一个使用 TensorRT 进行推理的插件,支持对象检测。此外,它会自动将 ONNX 格式的模型转换为优化的 TensorRT 引擎。
  • 它有支持多种流输入的插件。它也有插件来保存多种格式的输出。

ONNX 模型动物园有一堆预先训练好的物体探测模型。我从动物园选择了微型 YOLO v2 型号,因为它很容易与 DeepStream 兼容,而且足够轻,可以在杰特森纳米上快速运行。

注:我确实试过使用来自动物园的 SSD 和 YOLO v3 型号。但是有一些兼容性问题。我的 GitHub 知识库中讨论了这些问题,以及验证和处理此类情况的技巧。我最终使用微型 YOLO v2,因为它很容易兼容,没有任何额外的努力。

现在,我们要研究的特性如下:

  1. 多个输入流:运行 DeepStream,同时对多个视频流进行推理。具体来说,我们将尝试使用多达 4 个视频流。
  2. 多输出接收器:在屏幕上显示结果,并使用 RTSP 进行流式传输。该流将被连接到网络的另一设备访问。

实验将评估性能(每秒帧数,FPS)和易用性。接下来的几节将指导您如何在 Jetson Nano 上设置 DeepStream 来运行这个实验。这个实验使用的所有代码都可以在我的 GitHub 库上获得。如果你只是好奇结果如何,请随意跳到结果部分。

入门指南

在本节中,我们将浏览一些说明,为我们的实验做好准备。

第 1 部分:设置您的 Jetson Nano

按照Jetson Nano 开发工具包上的说明设置并启动您的 Jetson Nano。如果你在设置上遇到一些问题,我强烈推荐以下这些 资源。

我想强调一些可能会帮你省去一些麻烦的要点:

  • 建议至少用 32GB 的 MicroSD 卡(我用的是 64GB)。
  • 您需要有线以太网连接。如果您需要将 Jetson Nano 连接到 WiFi,您需要使用 Edimax EW-7811Un 等加密狗。
  • 你需要一个直接接受 HDMI 输入的显示器。我无法使用带有 VGA-HDMI 适配器的 VGA 显示器。

第 2 部分:安装 DeepStream SDK

现在你已经有了你的 Jetson Nano,我们可以安装 DeepStream 了。Nvidia 已经整理了 DeepStream 快速入门指南,你可以按照 Jetson 设置部分下的说明进行操作。

在您使用上面的链接安装 DeepStream 之前,我想强调一下我的安装经验:

  • 安装程序会建议您使用 Nvidia SDK 管理器安装 Jetpack。我跳过了这一步,因为我意识到在第 1 部分(上面)中使用操作系统映像在默认情况下具有大多数必需的依赖性。
  • 在快速入门指南的“安装 DeepStream SDK”小节中,我使用了方法 2。

在安装了 DeepStream 并提升了时钟之后(如指南中所述),我们可以运行他们的一个示例来验证安装是否正确完成。将(**cd**)移动到您的 DeepStream 安装文件夹中,并运行以下命令:

deepstream-app -c ./samples/configs/deepstream-app/source8_1080p_dec_infer-resnet_tracker_tiled_display_fp16_nano.txt

在执行时,您应该会看到类似这样的内容:

Output on executing DeepStream using the sample configuration file.

如果你看到类似的东西,恭喜你!如果你愿意,你可以尝试更多的样品。该指南有一个名为“参考应用程序源详细信息”的部分,提供了示例的描述。

第 3 部分:设置实验

现在你已经安装并测试了 DeepSteam,我们可以继续我们的实验了。我已经将实验所需的所有文件打包在我的 GitHub 存储库中。您可以按照存储库的 readme 文件中关于设置说明的逐步说明进行操作。

在继续实验之前,如果您以前没有使用过 GStreamer,那么浏览一下他们的 基础 页面是值得的。这有助于更好地理解 DeepStream 文档中使用的一些术语。

将您的自定义 ONNX 模型与 DeepStream 接口

在这一节中,我们将探讨如何将 ONNX 模型的输出与 DeepStream 进行接口。更具体地说,我们将逐步完成在 C++ 中创建自定义处理函数的过程,以从 ONNX 模型的输出中提取边界框信息,并将其提供给 DeepStream。

第 1 部分:理解 Tiny YOLOv2 的输出

ONNX 模型以通道优先格式输出形状为**(125, 13, 13)**的张量。然而,当与 DeepStream 一起使用时,我们获得了形状为**(21125)**的张量的展平版本。我们的目标是从这个展平张量中手动提取包围盒信息。

让我们首先尝试直观地理解 ONNX 模型输出的输出张量。考虑输出张量是一个维度为**(B, H, W)**的长方体,在我们的例子中是B=**125**,H=**13**,W=**13**。我们可以分别沿着宽度(W)、高度(H)和深度(B)考虑 X、Y 和 B 轴。现在,XY 平面中的每个位置代表一个网格单元。

让我们想象一个网格单元**(X=0, Y=0)**。对于这个给定的(X,Y)位置,沿着深度轴(B)有 125 个值。让我们以 25 个为一组重新排列 125 个值,如下所示:

Figure A: Interpreting the meaning of the 125 b-values along the B-axis for the grid cell (X = 0, Y = 0).

正如我们在这里看到的,每个连续的 25 个值属于一个单独的边界框。在每组 25 个值中,前 5 个值是边界框参数,后 20 个值是类别概率。利用这一点,我们可以提取 5 个边界框中每一个的坐标和置信度得分,如下所示:

Formulae for extracting the bounding box parameters. (Source)

请注意,我们只在一个网格单元(X=0,Y=0)上执行了此操作。我们必须迭代 X 和 Y 的所有组合,以在每个网格单元找到 5 个边界框预测。

既然我们对信息是如何存储的有了一个直观的概念,让我们尝试使用索引来提取它。在展平输出张量后,我们得到一个存储信息的数组,如下图所示:

Figure B: Flattened representation of the output tensor.

展平的数组有125 * 13 * 13 = **21125**个元素。如上所示,数组中的每个位置对应于索引**(b, y, x)**。我们可以观察到,对于给定的**(y,x)** 值,对应的**b** 值由13 * 13 = **169**隔开。

下面的 Python 中的代码片段展示了我们如何获得对应于给定**(y, x)**位置中 5 个边界框中每一个的**b**值的位置。请注意,如图 A 所示,对于给定的**(y, x)**位置,每个边界框有 25 个**b**值。

## Let **arr** be the flattened array.
## The array **values** contains the value of **arr** at the 25 b_values per ## bbox,x,y combination. **num_anchors** = 5
**num_classes** = 20
**xy_offset** = y * 13 + x
**b_offset** = 13 * 13
**bbox_offset** = 5 + num_classes
for **bbox** in range(**num_anchors**):**values** = []for **b** in range(**bbox_offset**):value = **arr**[xy_offset + b_offset * (b + bbox * bbox_offset)]values.append(value)

剩下要做的就是编写与此相同的 C++ 代码。

第 2 部分:编写边界框解析函数

现在我们已经了解了输出是如何存储和提取的,我们需要用 C++编写一个函数来做同样的事情。DeepStream 需要一个具有如下所示参数的函数:

extern "C" bool **NvDsInferParseCustomYoloV2Tiny**(std::vector<NvDsInferLayerInfo> const& **outputLayersInfo**,NvDsInferNetworkInfo const& **networkInfo**,NvDsInferParseDetectionParams const& **detectionParams**,std::vector<NvDsInferParseObjectInfo>& **objectList**
);

在上面的函数原型中,**outputLayersInfo** 是一个**std::vector**,包含了我们 ONNX 模型的各个输出层的信息和数据。在我们的例子中,因为我们只有一个输出层,我们可以使用**outputLayersInfo[0].buffer**来访问数据。变量**networkInfo** 具有模型期望的高度和宽度信息,变量**detectionParams** 具有关于某些配置的信息,例如**numClassesConfigured**

变量**objectList** 应在每次调用该函数时用作为**NvDsInferParseObjectInfo** 类型对象存储的边界框信息**std::vector**进行更新。因为变量是通过引用传递的,所以我们不需要返回它,因为更改会在源中反映出来。但是,函数在执行结束时必须返回**true**

对于我们的用例,我们创建**NvDsInferParseCustomYoloV2Tiny** ,这样它将首先解码 ONNX 模型的输出,如本节第 1 部分所述。对于每个边界框,我们创建一个类型为**NvDsInferParseObjectInfo** 的对象来存储它的信息。然后我们应用非最大抑制来移除相同对象的重复边界框检测。然后,我们将生成的边界框添加到**objectList** 矢量中。

我的 GitHub 库的**custom_bbox_parser** 目录下有**nvdsparsebbox_tiny_yolo.cpp**,已经为你写好了函数。下面的流程图解释了文件中的逻辑流程。代码可能看起来很大,但那仅仅是因为为了便于理解,它被大量地记录和注释了!

Flowchart approximately describing the flow of logic in the code file.

第 3 部分:编译函数

现在剩下的就是把函数编译成一个**.so**文件,这样 DeepStream 就可以加载和使用它了。在编译它之前,您可能需要在 Makefile 中设置一些变量。你可以参考我的 GitHub 库中自述文件的第 4 步获取说明。一旦完成,进入 GitHub 库并运行下面的命令:

make -C custom_bbox_parser

设置配置文件

好消息是大部分繁重的工作已经完成。剩下的就是设置一些配置文件,告诉 DeepStream 如何运行实验。一个配置文件有一组“组”,每个“组”有一组以密钥文件格式编写的“属性”。

对于我们的实验,我们需要设置两个配置文件。在本节中,我们将探究这些配置文件中的一些重要属性。

第 1 部分:Tiny YOLOv2 的配置文件

我们的 ONNX 模型由 DeepStream 的 Gst-Nvinfer 插件使用。我们需要设置一些属性来告诉插件信息,比如 ONNX 模型的位置,编译后的边界框解析器的位置等等。

在 GitHub 存储库中,已经为我们的实验设置了名为**config_infer_custom_yolo.txt**的配置文件。文件中给出了每个属性设置的注释和理由。有关所有受支持属性的详细列表,请查看此链接。

我们没有使用的一些有趣的属性是“净比例因子”和“偏移”属性。他们基本上使用公式net_scale_factor * (x — mean)缩放输入(x)。我们没有使用这些属性,因为我们的网络直接将未缩放的图像作为输入。

第 2 部分:DeepStream 的配置文件

我们还需要为 DeepStream 设置一个配置文件,以启用和配置它将使用的各种插件。如前所述,GitHub 存储库包含配置文件**deepstream_app_custom_yolo.txt**,它已经为我们的实验设置好了。

与上一部分不同的是,这个配置有“osd”(屏幕显示)、“primary-gie”(初级 GPU 推理机)等一大堆组。此链接包含所有可配置的可能组的信息以及每个组支持的属性。

在我们的实验中,我们定义了一个源组(source0)和三个宿组(sink0sink1sink2)。单源组负责并行读取四个输入视频流。三个接收器组分别用于在屏幕上显示输出、使用 RTSP 传输输出以及将输出保存到磁盘。我们在primary-gie组中提供了 Tiny YOLOv2 的配置文件路径。此外,我们还设置了titled-displayosd组来控制输出在屏幕上的显示方式。

运行深流

这是最简单的部分。您只需运行以下命令:

deepstream-app -c ./config/deepstream_app_custom_yolo.txt

首次启动 DeepStream 需要一段时间,因为 ONNX 模型需要转换为 TensorRT 引擎。建议在此过程中关闭 Chromium 等内存密集型应用。一旦创建了引擎文件,如果在微小的 YOLOv2 配置文件中定义了引擎文件的路径,后续的启动将会很快。

结果

在运行 DeepStream 时,一旦创建了引擎文件,我们就会看到一个2x2平铺显示,如下图所示。拼接显示器中的每个单元对应于不同的流输入。正如所料,所有的四个不同的输入被同时处理。

Output displayed by DeepStream.

因为我们还启用了 RTSP,所以我们可以在rtsp://localhost:8554/ds-test访问流。我使用 VLC 和 RTSP 的地址(在用我的 Jetson Nano 的 IP 地址替换了localhost之后)来访问连接到同一网络的笔记本电脑上的流。请注意,另一个接收器也用于将输出流保存到磁盘。令人印象深刻的是,控制台定期记录每视频流接近 6.7 的 FPS!

FPS per video stream while simultaneously using four video streams.

如果我们有一个单一的输入流,那么我们的 FPS 应该是四个视频的四倍。我通过更改配置文件中的值并再次启动 DeepStream 来测试这一点。正如所料,我们得到了一个巨大的接近 27 FPS 的单一视频流!考虑到它仍然向三个不同的接收器发送输出,性能令人印象深刻。

FPS while using a single video stream.

然而,我们注意到微小的 YOLOv2 的检测精度没有 FPS 那么惊人。这尤其是因为该模型是以牺牲一些准确性为代价来优化速度的。此外,视频中的人面部模糊,模型在训练时可能不会遇到这种模糊。因此,该模型可能会面临额外的困难。

判决和想法

深溪速度惊人。尽管 Tiny YOLOv2 针对速度而非准确性进行了优化,但稳定的高 FPS 性能,同时提供无缝多流处理和 RTSP 流等惊人的功能,是值得赞赏的。

然而,使用 DeepStream 可能并不简单,尤其是如果您的模型与 TensorRT 不完全兼容。在这种情况下,手动编写自己的 TensorRT 层可能是一个更可行的(尽管很乏味)选择。此外,可能会出现这样的情况,即现成的 ONNX 模型的 opset 版本可能高于 DeepStream 当前接受的版本。

尽管如此,我确实觉得 DeepStream 提供的功能是值得努力的。我建议你通过复制我的实验来尝试一下!

如何用 Azure 在边缘设备上部署你的 AI 模型

原文:https://towardsdatascience.com/how-to-deploy-your-ai-model-on-edge-devices-8c38a9519c58?source=collection_archive---------15-----------------------

1。简介

边缘计算是一种模式,其中部分计算在分散的边缘设备上完成,是扩展云计算的一种很好的方式。使用这种模式,人工智能(AI)模型在云中训练并部署在边缘,这具有以下优势:

  • 速度当需要实时决策时,云计算意味着太多的延迟
  • 可用性允许设备在与云的连接受限的情况下离线工作
  • 减少带宽当产生大量数据时,在设备上进行过滤以防止所有带宽被消耗

在这篇博客中,创建了一种功能,可以使用 Azure IoT Edge 和自定义视觉 AI 检测火车上的涂鸦。这是按如下方式完成的:

  • 涂鸦检测模型使用 Azure 自定义视觉进行训练,并导出为 TensorFlow 模型。
  • 模型作为 docker 容器部署在边缘(相机,由 Ubuntu 虚拟机模拟)
  • Edge 设备分析火车视频中的涂鸦。只有在检测到涂鸦时,视频才会放在 Blob on Edge 上,并上传到链接的 Azure 存储中
  • 一旦视频在 Azure 中,视频可以被进一步处理(从视频中提取文本,在 Power BI 仪表板上显示结果,参见我以前的博客

该项目的架构可描述如下:

1. Using AI with Cognitive Services on Azure IoT Edge

在博客的剩余部分,架构的边缘部分通过以下步骤实现:

  • 2.创建和导出人工智能模型
  • 3.将人工智能模型作为容器部署在边缘设备上
  • 4.结论

2.创建和导出人工智能模型

Azure 认知服务是一组可以注入到你的应用中的 API。它包含语音识别、图片中的对象识别和语言翻译的智能算法。还可以通过使用自定义视觉扩展另一个模型来创建自己的 AI 模型。这可以看作是“在预训练图像识别模型的神经网络中添加最后一个自定义层”。该项目采取了以下步骤:

  • 2a。训练自定义视觉模型来检测火车上的涂鸦。
  • 2b。将自定义视觉模型导出为 docker 文件
  • 2c。将导出的模型添加到 Visual Studio 代码项目

2a。训练和部署自定义视觉模型来检测火车上的涂鸦

前往 Custom Vision 网站,使用您的 Azure 广告凭证登录。登录后,选择创建一个具有属性“分类”和多类(每个图像一个标签)的自定义视觉项目。确保选择 General (compact)作为域,否则模型无法作为容器导出,另请参见下文。

2a1. Create Custom Vision API project

然后将以下图像下载到以下 git 项目中的文件夹cognitive services/custom vision images 中:

[https://github.com/rebremer/realtime_video_processing.git](https://github.com/rebremer/realtime_video_processing.git)

第一步,将带有涂鸦标签的涂鸦图片添加到您的项目中。其次,将带有标记涂鸦的 no_graffiti 图片添加到您的项目中,然后进行底片处理。然后使用快速通道训练模型,也见下文。

2a2. Train Custom Vision Api project

您可以通过点击“快速测试”来测试模型,然后使用之前下载的 git 项目从测试文件夹中选择一个图像。

2b。将自定义视觉模型导出为 docker 文件

一旦您定型并测试了模型,您就可以创建模型的端点或者导出它。在这个场景中,模型被导出为 dockerfile。转到您的项目,选择您想要导出的迭代,然后选择 export。随后,选择将模型导出为包含张量流的 dockerfile。pb 文件。

2b1. Export model as dockerfile

在下一章中,模型被添加到项目中。

2c。将导出的模型添加到 Visual Studio 代码项目

在这个项目中, Visual Studio 代码用作编辑器。安装完成后,选择 Open Folder,然后选择打开在步骤 2a 中克隆的 github 项目中的“RealTime_Video_Processing”文件夹。然后替换 EdgeCustomVision/modules/ImageClassifierService/app 文件夹中的 model.pb 和 label.txt,另见下文

2c1. Adding CustomVision model to project

3.将人工智能模型作为容器部署在边缘设备上

在这一部分,项目部署在边缘。博客的这一部分扩展了以下标准 Azure 教程,并执行以下步骤:

  • 3a。安装准备工作
  • 3b。在物联网集线器上安装边缘设备
  • 3c。在边缘设备上安装模块

3a。安装准备工作

需要安装以下预备设备:

  • 安装 Azure 核心工具版本 2.x 。
  • 安装 Azure CLI 。此博客需要 Azure CLI 版或更高版本。运行az --version找到您拥有的版本。
  • 安装对接器
  • 安装 Azure 物联网边缘扩展:一个连接到你的物联网中心的扩展,让你通过 Visual Studio 代码管理你的物联网设备

此外,创建一个存储帐户、物联网中心和 Azure 容器实例,这是本教程剩余部分需要的。

az login# Create resource group
az group create -n blog-rtvideoedge-rg -l westeurope# Create storage account and container
az storage account create -n <stor name> -g blog-rtvideoedge-rg --sku Standard_LRS
az storage container create -n videoblob --account-name <stor name># Create IoT Hub
az iot hub create --resource-group blog-rtvideoedge-rg --name blog-rtvideoedge-iothub --sku F1# Create Azure Container registry
az acr create -n <your unique acr name> -g blog-rtvideoedge-rg --sku Standard -l westeurope

3b。在物联网集线器上安装边缘设备

一个 Ubuntu VM 将作为这个博客中的边缘设备。执行以下命令

# Install extension
az extension add --name azure-cli-iot-ext# Create VM that will serve as Edge device
az vm create --resource-group blog-rtvideoedge-rg --name blog-rtvideoedge-vm --image microsoft_iot_edge:iot_edge_vm_ubuntu:ubuntu_1604_edgeruntimeonly:latest --admin-username azureuser --generate-ssh-keys --size Standard_DS1_v2# Open port such that video processing on Ubuntu VM can be seen in webbrowser
az network nsg rule create --resource-group blog-rtvideoedge-rg --nsg-name blog-rtvideoedge-vmNSG --name port_5012 --priority 1020 --destination-port-range 5012

现在,使用以下命令将虚拟机作为边缘设备添加到物联网中心:

# Create edge registration in IoT Hub
az iot hub device-identity create --hub-name blog-rtvideoedge-iothub --device-id blog-rtvideoedge-vm --edge-enabled# Retrieve keys from edge registration
az iot hub device-identity show-connection-string --device-id blog-rtvideoedge-vm --hub-name blog-rtvideoedge-iothub# And add this key to your VM using the following command:
az vm run-command invoke -g blog-rtvideoedge-rg -n blog-rtvideoedge-vm --command-id RunShellScript --script "/etc/iotedge/configedge.sh '<device_connection_string from previous step>'"

正确创建物联网集线器和边缘设备后,您应该会在门户中看到以下内容

3b1. Edge device created in IoT Hub

3c。在边缘设备上安装模块

在博客的这一部分,将在边缘设备上安装以下模块:

  • 边缘上的 Azure Blob 将用作边缘设备的本地存储,并异步将数据放入链接的存储帐户
  • 由摄像机模块和网络服务器组成的自定义视觉模块,可在其中跟踪视频处理。

现在找到。env 并填写以下变量:

# Replace the value of these variables with your own container registryCONTAINER_REGISTRY_ADDRESS="<Your ACR address>"                       CONTAINER_REGISTRY_USERNAME="<Your ACR username>"                       CONTAINER_REGISTRY_PASSWORD="<Your ACR password>"                                               BLOB_STORAGE_CONNECTIONSTRING="<Your storage account key>"                       BLOB_STRORAGE_CONTAINER="videoblob"                                               PRIVATE_IP_VM="10.0.0.4"                                               LOCAL_STORAGE_NAME="localvideostor"                       LOCAL_STORAGE_KEY="<create string using [https://generate.plus/en/base64?gp_base64_base%5Blength%5D=64](https://generate.plus/en/base64?gp_base64_base%5Blength%5D=64)>"

随后,通过右键单击deployment.edgecamera.template.json文件并选择Build and push IoT Edge Solution来构建整个解决方案,参见下文。

3c1. Build and push IoT Edge Solution

如果出现认证错误,首先在命令行中运行以下命令:az acr login --name <your acr> -g blog-rtvideoedge-rg

在下一步中,构建并推送两个 docker 容器(这可能需要一段时间),并创建一个新的 config/deployment . edge camera . JSON。需要完成以下步骤:

  • 从 Visual Studio 代码将其连接到您的物联网中心(为此需要安装 2a 中提到的物联网边缘扩展)
  • 转到新创建的 config/deployment . edge camera . jsonle,选择Create Deployment for Single device并选择我们在 3b 中创建的边缘设备。然后 docker 映像将被构建并部署到该设备上(这可能需要一段时间)

如果一切顺利,您可以点击物联网边缘在物联网门户中查找设备,另请参见下文:

3c2. Edge modules deployed sucessfully

随后,当您通过使用端口 5012 访问 Ubuntu VM 的公共 IP 来查找正在实时分析的视频时,也请参见下文

3c3. Videos being analyzed in realtime

使用ssh azureuser@<public ip ubuntu vm>和类型sudo docker start camera-capture通过 ssh 进入您的虚拟机可以重启视频处理。用于记录sudo docker logs camera-capturejournalctl -u iotedgesudo systemctl status iotedge。由于视频包含涂鸦,因此将其放在 blob on edge 上,该 blob 将视频异步上传到附带的 blob 存储帐户上。然后可以进一步加工,看我之前的博客怎么做这个。

4.结论

在这篇博客中,我们讨论了带人工智能的边缘计算对扩展集中式云计算非常重要,因为它允许 1)实时决策,2)离线可用性,3)降低带宽以实现成本效益。在这种情况下,创建了一个可以在边缘进行智能处理的项目,如下所示

  • 使用自定义视觉模型对边缘进行涂鸦检测
  • 仅当检测到涂鸦时,才使用 Blob on Edge 将视频添加到 Azure 存储帐户
  • 一旦视频在 Azure 中,数字识别使用 OCR 完成,结果显示在 Power BI 上(参见我之前的博客)

项目的架构如下所示。

4. Using AI with Cognitive Services on Azure IoT Edge

如何使用 Python 将您的数据科学项目轻松部署为 web 应用程序

原文:https://towardsdatascience.com/how-to-deploy-your-data-science-as-web-apps-easily-with-python-955dd462a9b5?source=collection_archive---------7-----------------------

教程+在 Heroku 中部署——Streamlit 带来了革命性的变化,使部署 web 应用程序变得更加容易。

Photo by Christina @ wocintechchat.com on Unsplash

你知道在网上部署应用程序在技术上有多复杂。借助 Streamlit,您可以使用纯 python 创建应用程序,无需担心前端开发。在本地服务器上实现它只需要一个命令。如果你想在网络上使用它,你可以在任何其他云平台上托管它。

Streamlit — Pure Python

在本教程中,您将使用 python 和 streamlit 构建数据可视化应用程序。后来我们把它部署在 Heroku 供公众使用。这是我们将在 Heroku 中构建和部署的一个预告片。

设置简化 it

我们用 pip 安装 Streamlit,如下所示:

pip install streamlit

运行 Streamlit 就像运行一样简单:

streamlit run XXX.py

现在,我们还没有创建我们的应用程序。但是在我们继续之前,我们创建了一个 GitHub 存储库,我们稍后将使用它在 Heroku 中部署应用程序。创建 Github 存储库后,克隆它。

git clone [https://github.com/shakasom/streamlit-medium.git](https://github.com/shakasom/streamlit-medium.git)

从现在开始,我们处理这个文件夹。所以转到这个文件夹:

cd streamlit-medium/

在下一节中,我们将开发一个 python 数据可视化应用程序。

本地应用程序开发

你可以使用你最喜欢的开发环境。让我们创建一个 python 文件来编写应用程序。你想叫它什么都可以。我会把我的叫做 app.py

我们首先导入我们需要的库。

import streamlit as st
import pandas as pd
import plotly_express as px
*import folium* from folium.plugins import HeatMap
import seaborn as sns

本教程的数据是 2016 年 1 月至 6 月华盛顿报道的犯罪。让我们创建一个函数来帮助我们做到这一点。

# Get the data from url and request it as json file@st.cache(*persist*=True, *suppress_st_warning*=True)
*def* load_data():df = pd.read_csv(    “https://query.data.world/s/6joi7hjgjmwifhl2clpldwm36xmvmx")df[“REPORTDATETIME”] = pd.to_datetime(df[“REPORTDATETIME”], *infer_datetime_format*=True)df[“Day”] = df[“REPORTDATETIME”].dt.day df[“Month”] = df[“REPORTDATETIME”].dt.monthdf[“Hour”] = df[“REPORTDATETIME”].dt.hourreturn df

让我们创建 main 函数,当我们执行它时,它会自动运行我们的应用程序。首先,我们使用上面的函数获取数据,并将其命名为 df_data。我们还开始编写标题(st.header)并向我们的应用程序添加图像(st.image)。

*def* main():df_data = load_data()st.header(“Washington Crimes Data Exploration”)st.subheader(“A demo on how to use Streamlit”)st.image(image.jpg", *width*=600)if __name__ == “__main__”:main()

有了这个简单而纯粹的 python 代码,我们可以在本地派生出一个 Streamlit 应用程序。你需要跑:

streamlit run app.py

还有瓦拉!您的应用将在浏览器中启动。让我们检查一下我们目前掌握的情况。一个标题,副标题文本和一个图像,你可以从下面的截图看到。它运行在本地主机端口 8501 上。

Streamlit screenshot

让我们为我们的应用程序添加更多的功能。我们将逐步做到这一点。我们首先在应用程序中显示数据集的一些行。我们还展示了整个数据集的形状。要控制显示项目,可以使用 st.checkbox ,点击一次;它将显示缩进代码中的内容。 st.write 可以拿熊猫做手术,所以如果你想展示头部,我们可以这样做。

if st.checkbox(“show first rows of the data & shape of the data”):st.write(df_data.head())st.write(df_data.shape)

函数中添加上述代码并保存。现在,如果您转到浏览器并刷新或重新运行您的应用程序,您将看到一个复选框,如果您单击它,您将看到数据集的前几行。

Adding checkbox

让我们在应用程序中添加一张地图。首先,我们创建一个函数来返回一个图形。

@st.cache(*persist*=True, *suppress_st_warning*=True)
*def* display_map(*df*):st.subheader(“ Displaying Point based map”)px.set_mapbox_access_token("MAPBOX TOKEN”)fig = px.scatter_mapbox(df, *lat*=”Y”, *lon*=”X”, *color*=”METHOD”\, *zoom*=10)return fig

函数内部,我们可以调出 st.plotly_chart 。有一些内置的图表功能,包括 Matplotlib、Bokeh 等,但任何其他尚未在 streamlit 中实现的库也是可能的,因为我们将在接下来使用 Folium 库。

st.plotly_chart(display_map(df_data))

上面的代码将在我们的应用程序中添加一个美丽的 Plotly 地图,你可以从下面的截图中看到。

Streamlit app

侧栏元素

如果您想使用侧边栏,您可以将 st.sidebar 与任何其他 streamlit 功能一起使用。该方法将在侧边栏中创建您的应用程序元素。让我们看一个使用带有下拉选择的侧边栏的例子— selectbox。

首先,我们创建选择—热图和计数图。

dataviz_choice = st.sidebar.selectbox(“Choose Data Visualization”, [“None”, “Heatmap”, “Countplot”])

让我们为热图创建一个函数。

*def* heat_map(*df*):locs = zip(df.Y, df.X)m = folium.Map([38.8934, -76.9470], *tiles*=’stamentoner’,   *zoom_start*=12)HeatMap(locs).add_to(m)return st.markdown(m._repr_html_(), *unsafe_allow_html*=True)

注意,这里我们使用的是 st.markdown。在 Streamlit 中还没有实现 yellow 库,但是我们可以在上面的代码中以这种方式创建一个 yellow map。

现在,让我们用热图和计数图填写我们的选择。

if dataviz_choice == “Countplot”:st.subheader("Countplot")sns.countplot(“METHOD”, *data*=df_data)st.pyplot()elif dataviz_choice == “Heatmap”:st.subheader(“Heat Map”)heat_map(df_data)

如果您在浏览器中重新运行您的应用程序,您应该会看到一个带有选项的侧边栏。如果我们选择热图,我们的应用程序将如下所示。

Streamlit Heatmap

在下一节中,我们将在 Heroku 中部署应用程序,在那里您可以免费构建应用程序。如果你愿意,你也可以用 AWS 或者 Google 云平台来部署,但是在本教程中,我将使用 Heroku。

在 Heroku 部署应用程序

首先,确保你在 Heroku 注册。然后,我们需要创建四个文件来在云中部署我们的应用程序:Procfile、config 文件、需求和运行时。让我们首先创建 Procfile。当我们想在 Heroku 中剥离应用程序时,我们在这里提供要运行的内容。以下是 Procfile 的外观:

web: sh create_config.sh && streamlit run app.py

保存文件并将其命名为“Procfile ”,不带任何扩展名。

接下来,我们创建配置文件,将其命名为 create_config.sh,并将以下代码粘贴到其中。

mkdir -p ~/.streamlit 
echo “[server]
headless = true
port = $PORTenableCORS = false
” > ~/.streamlit/config.toml

需求文件包含了应用程序需要的库。您可以使用 pip 冻结。requirements.txt 文件如下所示:

streamlit==0.51.0
pandas==0.25.2
plotly-express==0.4.1
seaborn==0.9.0
folium==0.10.0

最后,运行时文件指定您希望应用程序运行的 python 版本。

python-3.7.5

现在我们需要将这些新文件推送到我们的 Github 库。

git add *
git commit -m “deploying files”
git push

我们的本地文件现在被推送到我们的 Github 库,我们可以开始在 Heroku 部署应用程序。在命令行中运行以下命令,然后按任意键。

heroku login

将弹出一个新的浏览器。用你的证件登录 Heroku。一旦你这样做了,回到你的命令行,创建一个这样的 Heroku 应用程序。

heroku create streamlit-medium

最后,我们需要推动 Heroku。

git push heroku master

如果你现在逃跑

heroku open

您的应用程序将在新的浏览器中打开,或者您可以单击提供的 URL。也就是说,你可以与任何人共享这个 URL,他们将从任何地方访问你的应用程序。

Streamlit app deployed in Heroku

结论

在本教程中,我们用 python 和 streamlit 创建了一个数据可视化应用程序。我们还使用 Heroku 在云中部署了应用程序。本教程的代码可以在这个 Github 资源库中找到

[## shakasom/streamlit-medium

你知道他们在网上部署应用程序在技术上有多复杂。有了 Streamlit,您可以用纯粹的…

github.com](https://github.com/shakasom/streamlit-medium)

您可以通过以下 URL 访问 Heroku web 应用程序:

[## 细流

编辑描述

streamlit-medium.herokuapp.com](https://streamlit-medium.herokuapp.com/)

如何将您的机器学习 Web 应用部署到数字海洋

原文:https://towardsdatascience.com/how-to-deploy-your-machine-learning-web-app-to-digital-ocean-64bd19ce15e2?source=collection_archive---------8-----------------------

使用 Fast.ai、Docker、GitHub 和 Starlette ASGI 框架

Y 你已经收集了你的数据,勤奋地清理了这些数据,把它们塞进你精心微调的模型中,并花费了大量的 GPU 时间来训练这个模型。预测是最先进的!太棒了。

但是现在呢?

当然是和全世界分享啦!它有如此巨大的潜力,以前没有人这样做过,你想让每个人都尝试一下!怎么会?你问。

在本教程中,我将向您介绍一种部署训练有素的机器学习模型的经济而灵活的方法。我将带你走完这一过程中的每一步,希望在读完这篇文章后,你在向世界部署你的“下一个大东西(模型)”时不会有任何问题。

如何训练(和输出)你的龙(模型)

Image from https://www.facebook.com/HowToTrainYourDragon/

首先,你需要训练你的模型,并导出它。在本文中,我们将使用 Fast.ai 的库来展示它是如何完成的。你可能想参考我的关于如何收集数据和训练一个中国书法分类器模型的两篇文章或者你也可以使用你自己的模型。出于本文的目的,我将假设您已经训练了模型并达到了您想要的准确率。

Fast.ai 使用一个learn对象来训练模型,为了导出你的模型,使用方法learn.export()将你训练好的模型导出并保存到一个export.pkl文件中(上面 链接 我的模型导出文件大约是 100MB* )。保存这个文件,我们以后会用到它。*

GitHub 驱动的网络开发

模型准备好了,下一步是 web 应用程序开发。我假设你是一个全栈的 web 开发人员,所以让我们直接进入编码。不,我只是在开玩笑。我们将使用 GitHub 上的样板 web 应用程序模板来快速准备好您的 web 应用程序。你只需要做一些小的调整,你就可以开始了。如果你不知道 GitHub 是什么,它是存放大量开源应用程序源代码的地方。我已经把一个现成的 web 应用程序的代码放在那里了,所以你可以很容易地下载和重用。

进入这个 GitHub 库,点击右边绿色大按钮克隆或者下载,如下图:

在弹出窗口中,复制链接,然后转到您的终端并键入:

git clone [https://github.com/wayofnumbers/fastai-vision-uvicorn-gunicorn-starlette-docker.git](https://github.com/wayofnumbers/fastai-vision-uvicorn-gunicorn-starlette-docker.git)
cd fastai-vision-uvicorn-gunicorn-starlette-docker

这些命令将把所有需要的代码克隆到你的本地机器上,在一个名为fastai-vision-uvicorn-gunicorn-starlette-docker的文件夹下,并进入那个文件夹。这是我们将要处理的主文件夹,其中有几个值得解释的内容:

app :这个app文件夹的结构如下:

template
|--app.html
main.py
export.pkl

这是您的 Starlette web 应用程序源代码所在的位置。它有一个非常简单的 Python 文件main.pyStarlette 是一个轻量级的 ASGI 框架/工具包,非常适合构建高性能的 asyncio 服务。

它还有保存的模型文件export.pkltemplate文件夹中有一个 HTML 模板文件app.html,它将作为你的 web 应用程序 UI。

还记得你保存的导出的export.pkl文件吗?把那个拿出来,替换掉这个app 文件夹里的那个。所以应用程序会使用你的模型。也欢迎您更新 app.html 文件以获得更好的 UI,但是就部署而言,这不是必需的。现在你的 web 应用程序的源代码已经准备好了,我们需要把它打包到一个 Docker 容器中,并做一些测试。我们使用 Dockerfile 作为配置文件。我们将在下一节中探索更多。

让我们把它记录下来!

我们将使用 Docker 创建一个运行我们 web 应用程序的容器。如果你不知道 Docker 是什么,只知道它是一种迷你虚拟机,安装了所有必要的库和依赖项,因此应用程序可以平稳运行。它比真正的虚拟机更小、更灵活,并且可以非常容易地创建和部署。

首先,你需要安装 Docker。这里是一个非常全面的指南,供你参考。安装后,如果您运行的是 Ubuntu,那么运行以下命令会有所帮助:

sudo groupadd docker
sudo usermod -aG docker $USER

这将消除每次输入 docker 命令时使用sudo的需要。重新启动,现在 docker 应该安装正确。

app文件夹和Dockerfile所在的同一个目录中,我们需要创建一个 docker 映像,其中包含这个文件夹中的所有源代码,这样我们就可以进行测试了。输入以下命令(不要忘记“.”结尾):

docker build -t test_app .

这将根据Dockerfile启动一个 docker 映像构建过程。这需要一段时间,所以让我们简单看看Dockerfile里面有什么:

#1 FROM tiangolo/uvicorn-gunicorn-starlette:python3.7
#2 RUN pip install fastai aiohttp 
#3 RUN pip install jinja2 
#4 RUN pip install starlette 
#5 COPY ./app /app 
#6 WORKDIR /app 
#7 EXPOSE 80

这是不言自明的:

第 1 行:指定我们将从哪个起始映像构建 docker 映像。我们用tiangolo/uvicorn-gunicorn-starlette:python3.7。你可以在这里找到它的 GitHub 链接,在这里找到 Docker Hub 链接。

2、3、4 行:安装 fast.ai 库、jinja 模板框架、Starlette 框架等实用工具。

第 5 行:把你的应用文件夹复制到 docker 镜像中,这样我们的应用就可以在 docker 容器中运行了。

第 6、7 行:将工作目录分配给app文件夹,将端口 80 暴露给外部,这样我们就可以通过端口 80(HTTP)访问 web app。

一旦创建了 docker 图像,运行docker images进行检查。您会发现类似这样的内容:

REPOSITORY    TAG    IMAGE ID    CREATED        SIZE
test_app      latest xxxxxxxxx   1 minutes ago  4.05GB

现在,我们可以从创建的映像启动 docker 容器,并在本地测试您的应用程序:

docker run -p 80:80 \-v ./absolute/path/to/export.pkl:/app/export.pkl \-e TITLE="Chinese Calligraphy Classifier" \-e SUBTITLE="Can disambiguate Chinese calligraphy styles like KaiShu, LiShu, XiaoZhuan" test_app

在上面的 docker 命令中,我们将端口指定为 80。我们将两个环境变量转移到容器中,TITLESUBTITLE,它们将用于显示我们的 web 应用程序 UI 标题。最后,我们指定了 docker 图像名:test_app。请注意,对于export.pkl文件,需要使用绝对路径,否则 Docker 将无法找到。

如果您没有看到任何错误,您的 docker 容器现在应该已经启动并运行了。走向你的浏览器,输入127.0.0.1并点击回车,瞧!你应该看看网络应用。给它一个'楷书'、'隶书'或'小篆'的书法形象,打'分门别类【T27',你应该看到这样的东西:

Very rough web app UI

你可以看到 app 把这个归类为‘凯叔’,没错。现在你的应用已经在本地机器上运行了,我们已经完成了 80%。剩下的就是部署到云上了。接下来让我们向云进发吧!

下一步,云!

对于云托管服务,我们将使用数字海洋。与亚马逊 AWS、GCP 或 Azure 等现有公司相比,它对开发者更友好,也更便宜。你可以按照这篇写得很好的简明教程来创建一个你自己的账户和‘Droplet’。(“Droplet”是一个由 Digital Ocean 运行的虚拟机,你可以在其中安装你的应用程序,很像一个 AWS 实例。)如果您愿意,您可以使用此链接创建您的帐户,并免费获得 50 美元的信用点数,这足以让您入门。使用以下配置作为参考:

建议您创建至少有 4G 内存的 Droplets,因为安装 PyTorch 需要大量内存。以后你可以把它缩小到 2G。

您可以选择默认的“数据中心”并设置您的身份验证方法。使用 SSH 密钥或密码,无论哪种方式您都觉得更舒服。我个人比较喜欢 SSH 键,按键少,更安全。一旦创建了 Droplet,SSH 进入它,我们就为最后的部署做好了准备!

部署!部署!部署!

现在你应该能够以root的身份 SSH 到你的服务器。建议创建一个拥有sudo权限的普通用户,可以按照本教程进行操作。一旦创建了一个普通用户,注销您的root用户,用您的普通用户帐户通过 SSH 重新登录到服务器。最终的部署与我们已经在本地机器上完成的非常相似,只是这次我们是在远程 droplet 服务器上完成的。首先,让 git 克隆我们的 repo,这样我们就有了源代码:

git clone [https://github.com/wayofnumbers/fastai-vision-uvicorn-gunicorn-starlette-docker.git](https://github.com/wayofnumbers/fastai-vision-uvicorn-gunicorn-starlette-docker.git)
cd fastai-vision-uvicorn-gunicorn-starlette-docker 

不要忘记复制你的export.pkl文件来替换app文件夹中的内容。(如果您不知道如何操作,请点击此链接

如果没有安装 docker,请安装 docker。然后使用下面的命令构建 docker 映像。同样,如果由于内存不足而导致映像构建失败,请调高内存大小,稍后您可以调低内存大小,而不会增加太多成本。

# make it so that you don't need sudo for running docker command
sudo groupadd docker
sudo usermod -aG docker $USER# build the image
docker build -t test_app .

一旦构建了映像,启动 docker 容器:

docker run -p 80:80 \-v ./absolute/path/to/export.pkl:/app/export.pkl \-e TITLE="Chinese Calligraphy Classifier" \-e SUBTITLE="Can disambiguate Chinese calligraphy styles like KaiShu, LiShu, XiaoZhuan" test_app

一旦 docker 容器启动并运行,进入你的浏览器,输入你的 Droplet 的 IP 地址,点击回车。恭喜你!你已经成功地将你的深度学习模型部署到互联网上了!

结论

没那么难吧。使用标准 DigitalOcean Droplet 进行部署提供了很多灵活性。你可以对你的 Droplets 做任何你想做的事情,因为你有 root 权限。你可以在上面运行多个应用程序,只需支付很少的费用(5-10 美元应该足够了)。如果你的应用获得了一些牵引力,需要更多的资源,你可以很容易地扩大规模。

我希望这篇教程对你部署你的 AI 应用有所帮助。如果您有任何问题或想要分享您的部署经验,请在下面写下回复。部署愉快!

更新:我已经在这里部署了 web 应用。我使用 DigitaOcean 上的 web 应用程序作为 API 后端服务器,并将另一个基于 ReactJS 的 web 应用程序托管在 GitHub 页面上作为前端。由于 React 应用程序需要访问“http”URL,一些浏览器会显示“混合内容错误”,只需启用它,您应该可以自己尝试一下。也欢迎大家查看回购中的 React app 源代码。

欢迎任何反馈或建设性的批评。你可以在 Twitter @lymenlee 或者我的博客网站wayofnumbers.com上找到我。

如何使用 Heroku 将您的网站部署到自定义域

原文:https://towardsdatascience.com/how-to-deploy-your-website-to-a-custom-domain-8cb23063c1ff?source=collection_archive---------12-----------------------

这篇博客记录了使用 Heroku 和 NameCheap 将一个用 Python 和 Flask 框架编写的网站部署到一个定制域所需的步骤。Flask 是一个微框架,它允许我们在后端使用 Python 与 HTML/CSS 或 Javascript 中的前端代码进行交互,以构建网站。人们也为此使用其他框架,比如 Django,但是我最喜欢的是 Flask,因为它很容易上手。

Having your website can help you stand out

一个小 Flask 网站可以通过创建一个新的 repo 来创建,通过创建一个 Python 文件,如 this :

# app.py 
from flask import Flask
app = Flask(__name__)@app.route("/")
def hello():return "Hello World!"**if** __name__ == **"__main__"**:app.run(port=5000)

一个典型的 Flask 应用程序有文件夹static存放所有的 CSS 和 JS 文件以及图片等。和一个用于 HTML 文件的templates文件夹。我不会在这里说太多细节,但是在米格尔·格林伯格的教程中可以找到关于这方面的精彩信息。

当运行上面的文件python app.py时,它会在本地打开网站,显示“Hello World!”用 HTML 写的。

我们如何将这个网站部署到一个自定义域,让每个人都可以看到?

1.创建一个 Heroku 帐户

去 Heroku 网站注册一个账号。Heroku 将允许我们将网站部署到以herokuapp.com结尾的域中。我们将使用这个网站,并部署到自定义域。我们本可以使用亚马逊网络服务来部署网站,但是我发现这比使用像 Heroku 这样的解决方案要复杂得多。AWS 是基础设施即服务(IaaS),Heroku 是平台即服务(PaaS)。因此,我们不需要担心 Heroku 的具体基础设施细节!这使得它更容易使用。

现在,到这个链接并下载命令行的heroku。如果您的机器上有自制软件,您可以使用brew install heroku/brew/heroku将其安装到您的机器上。下次运行heroku login输入您的 Heroku 凭证。

Heroku is used to deploy our local website to cloud

2.将您的应用部署到 Heroku

a)制作一个 Procfile:
要将你的 app 部署到 Heroku,首先创建一个Procfile,保存在与app.py相同的文件夹中。请注意,Procfile 的没有任何扩展名,如txt等。该 Procfile 将包含内容web: gunicorn app:app该语句将允许 Heroku 运行 gunicorn 作为该应用程序的 web 服务器。确保你的虚拟环境中安装了gunicorn

b)制作 requirements.txt:
还有,用pip freeze > requirements.txt把这个项目的所有需求写成一个文件。Heroku 将使用它在云中安装所有必要的软件包来运行您的应用程序。

c)【可选】Make runtime.txt:
如果你想指定 Heroku 应该在云端使用哪个 Python 版本来运行你的 app,在这个文件里就提为python-3.6.6就可以了。

d)部署到 Heroku: 运行heroku create <app-name>其中<app-name>是你喜欢的名字。如果你的应用程序名称是calm-river,那么 Heroku 会将你的网站部署到calm-river.herokuapp.com。确保git安装在你的命令行上。
运行git init将当前文件夹初始化为 git 存储库。接下来,运行git add .,然后运行git commit -m "first commit",将所有文件提交给git。最后运行git push heroku master将你的应用部署到 Heroku~
如果一切顺利,你可以在<app-name>.herokuapp.com访问你的网站

3。链接到 Heroku 上的自定义域名:

接下来,我们需要从 NameCheap 或 GoDaddy 购买一个自定义域名。假设您购买了域名,example.com
接下来,运行heroku domains:add [w](http://www.calm-river.com)ww.example.com将这个自定义域名添加到您的 Heroku 应用程序中。它会给你一个 DNS 目标类型和 DNS 目标名称。这个目标类型应该是CNAME。我们需要将这个CNAME记录链接到你域名的设置控制台。

4.将 CNAME 记录添加到您的自定义域:

进入 Namecheap 设置控制台,然后进入Advanced DNS。将CNAME记录添加到主机目标,其中TypeCNAME,Hostwww,Value为您将域添加到 Heroku 时收到的 DNS 目标名称。

5.将 URL 重定向记录添加到您的自定义域:

添加 CNAME 记录后,添加URL Redirect record,主机为@,设置Unmasked[http://www.example.com](http://www.example.com)

允许 30 分钟来传播这些设置,您的网站应该在您的自定义域上运行!希望这些步骤对你寻求与世界分享你的工作有用。更多细节可以在 Heroku 网站上找到这些步骤。
希望能看到你的网站转转!

附注:我正在创建一个名为
“查询理解技术概述”
的新课程。
本课程将涵盖信息检索技术、文本挖掘、查询理解技巧和诀窍、提高精确度、召回率和用户点击量的方法。有兴趣的请在这里报名!这种兴趣展示将允许我优先考虑和建立课程。

My new course: Overview of Query Understanding Techniques

如果你有任何问题,请给我的 LinkedIn 个人资料留言,或者给我发电子邮件到 sanket@omnilence.com。感谢阅读!

如何利用机器学习检测恶意推文

原文:https://towardsdatascience.com/how-to-detect-mean-tweets-with-machine-learning-deaa9dc6a8a8?source=collection_archive---------18-----------------------

因为现在一切都是令人讨厌的…

Don’t give me that attitude

我想我不需要提醒你们所有人,尽管互联网有很多好处,但它也可能是消极的温床。只要看看 Reddit 或 YouTube 或 eelslap.com,你就会明白我的意思。

Twitter 一直是一个平台,人们可以在这里公开世界上和生活中发生的一切。我们的总统极其善于利用这个平台表达自己的意见,甚至调节美国公众的普遍看法。你可以想象,鉴于 Twitter 每天有 1.26 亿用户,不幸的是,有些人在说出自己的想法时没有过滤器。缺乏过滤器的人导致非常不合适的推文,从而导致不可避免的争论和痛苦。

今天我们要找点乐子,看看我们能否自动过滤掉哪些推文是冒犯性的,哪些不是。

议程

  1. 数据预处理
  2. 数据清理
  3. 标记化
  4. 堵塞物
  5. 数据可视化
  6. 提取特征
  7. 模型结构
  8. 需要改进的地方
  9. 资源

如果你想更深入地了解这个项目,或者如果你想添加代码,可以查看一下 GitHub 库

数据预处理

像往常一样,在我们开始实际的细节之前,我们需要在做任何有趣的事情之前准备好我们的数据。所有必要的数据都在 GitHub 存储库中。

我们有两个文件,一个训练文件和一个测试文件。在火车文件中,我们有各种推文的随机分类。有三个特性,一个唯一的 id、一个标签和实际的 tweet 文本。如果推文是非冒犯性的(非种族主义或性别歧视等),标签为“0”。)而标签是‘1’如果推文很冒犯的话。

首先,我们将导入一大堆库。

现在我们将使用熊猫来读取测试和训练文件。

让我们用熊猫来看看我们的数据是什么样的。

我将使用一些更好的数据符号,只显示那些被标记为攻击性的推文。

现在我们已经加载了数据,我们可以通过清理数据来最大限度地提高机器学习的效率。

数据清理

对于数据清理,我们将采取三个步骤:

  1. 移除 Twitter 句柄
  2. 删除标点、数字和特殊字符
  3. 删除那些没有太大价值的小词

为了节省时间,我们将组合我们的训练和测试数据帧,并在两者上进行所有的数据清理。

现在,我们将创建一个正则表达式,允许我们从我们的推文中找出并删除 Twitter 句柄。

现在我们的组合数据框架应该不再有 Twitter 句柄了。我们可以用一个简单的脚本删除特殊字符、数字和标点符号。

然后我们将删除没有增加价值的短词。

让我们看看现在合并后的数据帧是什么样子。

Nice work!

标记化

真正的乐趣开始了!因为机器学习算法不能像我们一样找到模式和见解(它们不能只是阅读一整串文本,所以它们必须接受单个单词),我们需要一种方法来保留每条推文的【本质】,同时让算法尽可能容易地了解什么使推文具有攻击性或不具有攻击性。

幸运的是,我们有这种有用的预处理形式,叫做记号化,它基本上是把你所有的文本分割成最基本的单元。

这是一个看起来像什么的例子。

New York is indeed special

标记化实际上非常简单。你所要做的就是把你的文本分成独立的部分。

嘣!我们结束了!

堵塞物

既然我们已经完成了标记化,我们需要继续下一步的预处理步骤,称为词干,本质上是将每个标记化的单词转换成它的词根形式和时态。例如,对“创建”一词进行词干化会产生“创建”一词,而“寄售”一词会变成“寄售”。

让我们来看看我们的词干推文。

数据可视化

在我们进入机器学习之前,对我们的数据进行一些直觉是一个很好的实践。数据可视化是我们实际探索和理解数据的一种很好的方式。

我们想回答的一些问题是:

  • 数据集中最常见的词是什么?
  • 负面和正面推文最常用的词是什么?
  • 一条推文中有多少标签?
  • 相关的趋势有哪些?

常用词

为了看到我们推文中的常用词,我们可以创建一个词云来真正看到它们。

正面推文中的单词

负面推文中的词语

(警告:这个词云中的词绝对是 NSFW)

标签

我们故意不删除标签,因为它们可以携带大量有用的信息。我们将提取标签,看看哪些是最常出现的。

现在让我们画出最常见的标签。

Positive hashtags

Negative hashtags

提取特征

现在我们已经完成了所有必要的步骤,是时候真正开始机器学习了。

我们将使用逻辑回归机器学习算法来训练我们的预测模型。在我们实际训练我们的模型之前,我们必须将文本数据转换成算法实际可以读取的格式。

我们可以使用两种方法,词袋和 TF-IDF(术语频率-逆文档频率)。我不会详细介绍这些特征提取模型实际上是如何工作的,但是可以通过我放在本文底部的参考资料来了解更多信息。

首先我们将提取单词袋。

然后我们用 TF-IDF 提取。

现在,我们可以使用这些提取的数据框架来训练我们的逻辑回归模型。

模型结构

是时候建立我们的模型了。

首先,我们将建立单词袋数据框架。

现在让我们看看我们预测准确度的结果。

现在,我们将使用 TF-IDF 数据框架构建模型。

看来我们的模型还有很多需要改进的地方。尽管这是一个开始。

需要改进的地方

感谢您花时间通读这篇文章!请随意查看我的作品集网站或我的 GitHub 。

1.使用不同的 Twitter 数据。

2.尝试不同的自然语言处理方法

3.使用不同的机器学习算法

4.调整超参数

资源

  1. 熊猫
  2. 正则表达式
  3. 自然语言处理
  4. 逻辑回归
  5. 文字袋
  6. TF-IDF

如何检测人脸登录时的张嘴

原文:https://towardsdatascience.com/how-to-detect-mouth-open-for-face-login-84ca834dff3b?source=collection_archive---------9-----------------------

你用过银行/支付 app 人脸登录,被要求张嘴、点头或转头吗?这种方法非常流行,特别是在中国,以防止使用静态人脸图像或 3D 打印进行欺骗/黑客攻击。我花了大约两天时间,终于想出了一个非常简单的方法,利用来自人脸识别项目的特征输出来检测嘴巴张开。

下面是将该算法应用于实时网络摄像头视频时的效果。

人脸识别项目

face_recognition 是一个基于 dlib 的非常棒的人脸识别开源项目,正如它自己所描述的:

世界上最简单的用于 Python 和命令行的面部识别 api

通过几行 Python 代码,您可以检测到一张脸,识别出是谁,并输出脸部特征,如下巴、眼睛、鼻子和嘴唇。

例如,对一张奥巴马图片运行示例find _ face _ features _ in _ picture . py(只有 40 行代码),可以得到如下所示的所有面部特征。

Source image

Facial features drawn in the image

您还将在标准输出中获得面部特征细节,包括上唇和下唇。每个特征都是位置点的列表。

Facial feature outputs

面部识别装置

你可以按照 github 上的 face_recognition 项目中的步骤,或者直接下载预配置的 VM (强烈推荐)。

检测嘴张开的算法

face_recognition 提供了用于静态图形分析的 API,但它不会告诉你像张嘴或点头这样的面部动作。然而,我们可以通过特征输出来检测这些运动,即,在这种情况下嘴张开/闭合。

上唇和下唇特征输出都包含 12 个位置点的列表,但顺序不同。

top_lip points: [(181, 359), (192, 339), (211, 332), (225, 336), (243, 333), (271, 342), (291, 364), (282, 363), (242, 346), (225, 347), (211, 345), (188, 358)]
bottom_lip points: [(291, 364), (270, 389), (243, 401), (223, 403), (207, 399), (190, 383), (181, 359), (188, 358), (210, 377), (225, 381), (243, 380), (282, 363)]

使用 matplotlib 绘制唇点,可以清楚地看到点的顺序,如下所示。感兴趣的话,点击查看剧情脚本。

Algorithm Illustration

我的算法很简单:

如果嘴巴张开高度大于嘴唇高度*比率,则嘴巴张开。

  • 比率:可调,定义开口的大小。你可以简单地把 ratio = 1,也就是说嘴张开的程度大于唇高。
  • 唇高:三对点距离的平均值如下:
2–10
3–9
4–8

这些对对于顶部和底部唇点都是相同的。

  • 口高:三对点距离的平均值,如下:
Top lip 8–10 Bottom lip
Top lip 9–9  Bottom lip
Top lip 10–8 Bottom lip

算法代码

唇高功能:

如果你把每个点对的指数加起来,你会发现总和总是 12。所以如果 i 是一个点,另一个点就是 12-i.

两点(x1,y1)和(x2,y2)的距离定义如下。

因此我们得到下面的嘴唇高度函数。

口高功能:

将各口穴对的指数相加,总和为 18。

检查口开启功能:

使用唇高和嘴高功能,我们可以定义检查嘴张开功能如下。

我选择上嘴唇高度和下嘴唇高度的最小值作为嘴唇高度。或者可以用平均值。

而我挑一个比值为 0.5,就不用张大嘴测试了😄。

mouth_open_algorithm_part3.py

好了,一切都准备好了。让我们来测试一下。

mouth_open_algorithm_test.py

产出:

top_lip height: 12.35
bottom_lip height: 21.76
mouth height: 33.34
Is mouth open: True

真实世界的例子

结合 face_recognition 和嘴部张开检测算法,我们可以开发一个网络摄像头实时人脸识别应用程序,具有检测嘴部张开/闭合的能力,正如你在本文开头的视频中看到的那样。它只有 80 行代码,你可以从 github 这里克隆。注意,你需要先安装 face_recognition 包。

git clone [https://github.com/peterjpxie/detect_mouth_open.git](https://github.com/peterjpxie/detect_mouth_open.git)cd detect_mouth_openpython facerec_from_webcam_mouth_open.py

笔记

这只是检测嘴巴张开的一种方式。你肯定会从其他来源找到其他类似或不类似的方法,或者你可以找到自己的方法。在寻找答案之前,自己想出一个方法是有趣和令人兴奋的。

感谢阅读。

如何确定你的机器学习模型是否已经可以部署了?

原文:https://towardsdatascience.com/how-to-determine-if-your-machine-learning-model-is-ready-for-deployment-c84e32ba260a?source=collection_archive---------30-----------------------

它足够“准确”吗?

如果你已经为现实世界的产品建立了机器学习模型,你就会知道弄清楚一个模型何时准备好被部署是多么困难。数据科学家很乐意对这个问题进行迭代,也许是无限地迭代,以不断提高模型的准确性。但是你如何确定它是否好到可以发布呢?有四种方法可以为可部署的模型设置精度目标:

Image by rawpixel from Pixabay

基于基线:

机器学习中的基线是解决问题的简单/启发式方法。您可以将预测模型的精度目标设置为比基线方法的精度提高一定的百分比。当您迭代您的模型时,您可以将每个部署的模型版本的准确性视为更新的基准,它需要在您的模型的后续版本中进行维护或改进。

例子:你的模型预测了用户对一部电影的评价。基线方法可以是使用基于所有其他用户评级的同一电影的平均/中间评级作为对该用户的预测。基于这一计算,您可以评估您的模型与基线相比的表现如何,并设定一个目标,即您的预测模型在相关指标方面必须比基线方法好 5%,才能准备好进行部署。

基于使用:

模型的准确性会影响产品的用户。建立准确度目标的一种方法是根据用户工作流程确定可接受的误差对用户的影响。

示例:您的模型决定了一个事件建议应用程序一天中发送给用户的建议的理想数量。现在要为模型设置一个准确性目标,您可以确定一个阈值,该阈值对于用户来说是可接受的,可以认为建议是有效的,并且不会给用户带来通知疲劳。这样,根据您的产品类型,您可以执行用户工作流研究和产品测试,以确定可接受的误差阈值,从而为您的模型准确性设定目标。

业务基础:

每个产品都解决一个商业问题。基于您的目标业务 KPI,您可以估计模型的准确性目标,以满足业务目标。

举例:你的产品声称通过基于机器学习模型的更有针对性的广告获得了更高的广告点击率。你宣称的目标是每天每显示 500 个广告获得 15 次点击,即 3%的点击率。为了能够达到这个目标,您可以计算您的模型需要有多精确,当模型精确时,考虑预期的用户可操作性。

基于安全:

根据行业和模型应用的不同,您的产品可能必须遵循特定的安全指南才能上市。在这种情况下,您可以根据安全准则和阈值为您的模型准确性建立目标。

示例:医疗保健等行业的各种产品。需要通过管理机构制定的指导方针,才能被认为可以安全使用。您可以利用这些特定的指南来估计您的模型的目标精度阈值。这些因行业、产品类型、地区等因素而异。

通过使用上述方法之一,您可以建立一个为您的模型设置目标的系统方法,而不是听起来不错但实际上无法实现或与您的产品目标不一致的任意目标。

如何发展成为一名数据科学家

原文:https://towardsdatascience.com/how-to-develop-as-a-data-scientist-1966a1540cec?source=collection_archive---------17-----------------------

本文向您展示了如何提高您的数据科学技能。特别是,这可能适用于希望转换角色的数据科学家或进入该领域的其他人。请将此视为一个灵活的框架,以指导您在数据科学职业生涯中的下一步。这是我通常使用的方法,我认为它在你想要的和保持真实(市场想要的)之间取得了很好的平衡。首先,我们将讨论您想对数据科学做些什么。第二,我们会了解市场的需求。第三,我们将讨论软技能——与人打交道。最后,我们将结束我对就业市场竞争的小演讲。我们开始吧!

详细说明

数据科学有很多应用方式。获得优势的一个方法是将您的数据科学技能集专门化于特定的专业领域。找到你的目标行业是一个好的开始,因为它不会把你束缚得太深。例如,我自己的专业领域是金融数据科学,也称为定量分析师。另一方面,我有几个同事在医疗保健领域应用了他们的数据科学技能。

在每个专业子集中,你可以自己创造有利可图的副业,并在简历中展示。在金融领域,这方面的例子包括信用评级或欺诈检测。当然,对于金融来说,还有一个试图预测股票价格的著名例子。在医疗保健领域,每年都会出现一些公开的竞赛。例如,我记得我的一个熟人告诉我一些健康数据科学竞赛的奖金超过 50 万美元+!

需求

一旦您有了想要进入的领域,您就应该查看该领域的一些数据科学家职位发布。具体来说,我们会看市场需求。每个工作和领域都有特定的要求或工作要求,这些要求或要求往往是相似的。例如,在金融领域,你可能需要 NLP(自然语言处理)方面的专业知识来理解任何给定资产的市场情绪,或者,在医疗保健领域,你可能需要预测特定蛋白质如何折叠。但作为浏览招聘信息的一般基准,你至少应该知道 SQL 和 Python 或 r。对于应用大数据的公司,你需要学习 Hadoop 和 Spark。

影响

在发展您的数据科学职业中获得优势的另一种方法是建立关系网。看看招聘经理那边,他们有数百名合格的申请人。他们的工作就是筛选出他们认为适合这个角色的人。你不觉得如果你亲自去见了招聘经理,并且能够满足那个职位的需求,你会更有可能得到面试机会吗?你当然会!此外,用你的专业技能给人留下一个好印象也会在以后有所收获。例如,你现在遇到的一个人可能现在没有在招人,但是以后他们可能需要你的技能,或者知道谁需要。

人际关系网的另一个好处是,在你出名的过程中,你会遇到其他有趣的人,这些人会激励你去做一些有趣的项目。在这些有趣的项目中,你永远不知道哪一个会变成潜在的合作,比如创业或自由职业。例如,我最近去了一家初创公司的聚会,只是为了四处看看,并得到了兼职机会。

竞争

最终,任何工作申请都只允许一个职位空缺。当然,也有一些例外(例如,公司组建团队),但假设只有一个位置更安全。记住,在申请职位时,赢家通吃。换句话说,第二名或以下没有奖励。在这种情况下,你最好的策略是,用卡尔·纽波特的话说,“好到他们不能忽视你。”

但是不要让表面上的坏运气阻止你实现目标。我们的生活中都有消极的人。有些人可能会说你没有这个,不能做那个,等等。呆的时间足够长,一些消极情绪就会开始影响到你。放手去做,超越竞争对手。

没有一个 X 技能(用任何技能代替 X)?出去想办法。每天采取任何行动。这是你发展优势的地方,这将转化为你可以推动更大进步的竞争优势。例如,我有一些我从未想过要效仿的榜样。我只是每天研究和实践我的发现。在几个月的时间里,我最终获得了这些技能,并提高了那些伴随我而来的技能。这里有一个你们可能不知道的小提示:

没有人在 100%的时间里发展自己。总有一天,学习曲线会变平,他们会去度假,生活会发生变化,等等。这给你留下了上升的机会。

关键是到达目标的攀登总是可以到达的。你只需要愿意足智多谋,并付出努力去实现它。

结论

在任何领域,尤其是科技领域,由于日新月异的变化,优秀的人会不断地学习和提高自己。作为一名数据科学家,你的目标是通过数据驱动的洞察力解决其他人无法解决的问题。有了 idea,你必须具备计算机科学、统计学和领域的专业知识才能玩这个游戏。要被录用,你必须是最优秀的。当然,一个人不可能无所不知,这就是为什么公司会为专家支付额外费用。一旦你选择了你的行业,学习该领域流行的技术和技能,并解决该领域的相关问题,以增加你的项目组合。数据科学领域的招聘经理真正强调的是你解决问题的能力,以及理解你为什么会有你的解决方案。所以,作为一个实用的提示,记得解释你的每个项目是如何解决一个问题的,你做了什么,为什么这么做,以及结果。

发展技能和创造市场回报的东西需要时间。一路上有许多挫折。但是请记住:

如果你想要你从未拥有过的东西,你必须愿意去做你从未做过的事情。——托马斯·杰斐逊

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

如何开发数据产品而不死尝试

原文:https://towardsdatascience.com/how-to-develop-data-products-and-not-die-trying-762c8878d05c?source=collection_archive---------11-----------------------

作者:
大卫·弗洛雷斯·费尔南德斯 、数据与 AI 解决方案架构师@微软 巴勃罗·帕丽丝 、数字架构师@微软

公司努力通过分析项目发展壮大

在当今数据积累的时代,全球渴望人工智能在各个层面的创新和商业应用。也许是时候停下来反思一下那种到处使用 AI 的燃烧欲望,并考虑一下“乐器定律”:“如果你只有一把锤子,那么一切看起来都像钉子”。

TL;DR:通过最后 10 个问题来评估你在构建数据产品方面有多擅长。

有许多报告警告公司在业务中实施或采用人工智能时遇到的问题。Gartner 指出 60%的分析和 BI 项目失败了,后来认识到实际情况更糟。根据 Gartner 分析师 Nick Heudecker 的说法,Gartner 对 60%的估计“过于保守”。真正的失败率接近 85%。".因此,如果你正面临任何困难,请认为你并不孤独,如果你不是,请认为你可能错过了一次现实检查。根据我们与不同行业和国家的客户打交道的经验,公司最常遇到的情况可以总结如下:听起来耳熟吗?

1.没有预算经验:投资大,兴趣大,但没有开发高级数据和人工智能项目的经验,这意味着在取得任何结果之前都会浪费大量时间。

2.不支持:没有业务支持的公司。许多好的想法由于缺乏合适的利益相关者的暗示而被搁置。

3.目标明确但效率低下的团队发展:团队努力工作却一事无成,或者结果令公司失望。

4.雄心勃勃的公司:有预算,有时有无限的资源,但不担心技术限制。当试图将解决方案应用于大规模问题时,这种情况可能会导致挫折。

5.缺少数据:数据不完整或完全孤立。这些类型的公司需要首先投资建立和准备他们的数据系统,以便能够进入高级分析。我们还可以在这里包括数据质量的问题。这不是一个小问题。

6.理论上的:公司拥有优秀的分析团队,但不了解敏捷方法或数据科学,难以扩大规模或将模型投入生产。

7.天真:相信 ML 有魔力的公司。祝你好运!

我们如何避免主要的陷阱?

本文的目的是作为讨论的种子,并提出一种不同的方法来执行和理解高级分析在企业架构中的正确位置。

想想看,很多时候这些项目的完成方式基本上是使用一个目标很少与公司的优先事项一致的供应商。我们可以在多大程度上外包数据产品的开发?供应商试图开发最准确或最适合的模型,而不关注工作的潜在和最终目的,这种情况并不罕见,当然,这是有用的。他们有没有搞清楚准确率和 ROI 之间的关系?相关吗?部署了一个非常好的模型,但没有人能够将其转化为金钱、新收入或成本节约,这种情况并不少见。那么,我们是否部署了一个非常好的模型,但却毫无用处?或者相反,我们是否部署了一个非常糟糕的模型,它并不比特定数据集的随机模型好多少?一旦模型被部署,谁来照看它们?问题太多…

总结一下,这些是公司必须集中精力的基本部分:使用和适用性。一家公司计划使用数据和人工智能构建的任何东西都必须遵循开发产品的理念。公司必须像为客户创造新产品一样痴迷于他们的开发过程。要么让它盈利,要么抛弃它。

此外,一个为了 PoC 而参与 PoC 的公司,仅仅关注技术组件往往是一种不完整的努力,也可能导致失败,不仅因为模型或数据不好,还因为失去了业务方向。这就是为什么我们在这篇文章中提出的不是孤立的工作,而是以敏捷的方式开发一个产品的完整版本,虽然功能有限,但是需要所有利益相关者的参与。软件世界中没有什么新东西,但显然还没有深入到那些创造数据驱动解决方案或产品的人的头脑中

为了构建一个数据产品,你需要什么?

希望在这个阶段,经验告诉我们的事情已经很清楚了:团队、方法和责任的清晰定义不应该被低估。这就是我们提出数据产品开发隔离策略的原因。在我们的下一篇文章中,我们将对此进行更深入的探讨。例如,每个工作流必须如何独立工作,以及所有团队如何在不造成混乱的情况下协作。同时,这是我们对团队、重点领域以及成员的建议:

Main team members and focus areas

同时,关于哪种方法更好还有很多可以讨论的,但是我们建议不要在选择完美的方法上浪费太多时间。应用的交付方法可以是你公司规定的任何方法:敏捷、团队数据科学过程、设计架构会议、设计思维、UX 设计,这里仅举几个例子。重要的一点是选择一种与您团队的技能相一致的方法,并关注最终的业务成果。

为了说明不同团队之间关系的复杂性,请参见下图,其中我们描述了实现完整 PoC 或功能发布的主要里程碑和依赖关系。

Workstrems involved in Data Product development

结论

我们只是触及了可能阻碍或减缓您的数据项目的表面原因,我们承认许多公司正在努力使他们的数据项目盈利或仅仅是有用,我们已经提出了一种组织不同工作流的方法。下一步是什么?

为什么不开始思考之前提到的五个主题以及你的公司是如何解决它们的:

1.方法学

2.数据

3.组

4.技术

5.商业导向

并向您的团队提出以下问题:

1.你的团队有能力在短时间内展示切实的成果吗?

2.这些结果与您的团队最初试图解决的业务问题直接相关吗?

3.与问题直接相关的业务人员能够建议参数配置吗?

4.技术在某种程度上影响了你的决定吗?例如,“我的团队觉得使用 SAS 很舒服,我们没有大数据,所以除此之外我们不需要任何其他技术。”

5.你的团队意识到你的模型的准确性和货币影响之间的关系了吗?例如,您的模型中 1%的准确性对您的业务目标有任何意义吗?

6.你能使用 3 个月前你尝试过的完全相同的数据集重新创建你的实验并比较结果吗?

7.你的团队使用任何源代码控制工具吗?有测试工具吗?除了笔记本之外还有其他工具吗?有人为你的团队写的代码做代码评审吗?

8.你能解释一下你的算法的结果吗,以防在现实世界中出错?例如,在给出信用的假阳性的情况下,你能向风险部门解释为什么吗?

9.你有将模型引入生产的流程吗?您能执行负载测试吗?性能测试?不停止服务就部署?

10.你的公司里有道德顾问的角色吗?法律部门了解您的数据产品吗?

如果你对这篇文章的内容感兴趣,请花几分钟时间回答这个表格,让我们知道你如何看待自己在开发数据产品。这是绝对匿名和保密的。

链接到表单

参考资料:

https://www . techrepublic . com/article/85-of-big-data-projects-fail-but-your-developers-can-help-yours-success/

https://cdn . oreillystatic . com/en/assets/1/event/278/Agile % 20 for % 20 data % 20 science % 20 teams % 20 presentation . pdf

https://hbr.org/2018/10/how-to-build-great-data-products

如何用人工智能发现 Spotify 上的新音乐

原文:https://towardsdatascience.com/how-to-discover-new-music-on-spotify-with-artificial-intelligence-b2110af6a611?source=collection_archive---------7-----------------------

Photo by author

寻找你可能从未听说过的艺术家的类似音乐

更新:自己试试这里,这里

[## deej-a . I .-Google Play 上的应用程序

使用人工智能发现新音乐,根据音乐的声音自动生成播放列表…

play.google.com](https://play.google.com/store/apps/details?id=online.deejai.www)

或者这里:

https://apps.apple.com/us/app/deej-a-i/id1529860910?mt=8

作为一名 DJ,我最讨厌的问题是“你有什么[在此插入完全不合适的艺术家]?”“你听哪种音乐?”。在我看来,一旦你把音乐放进一个流派的盒子里,它就会被它的限制所束缚。但是,如果不贴上标签,如何分享和组织音乐呢?

Spotify 能够根据特定曲目创建播放列表(或“电台”)。它非常擅长选择相似艺术家的音乐,但是不可避免地,它倾向于播放你可能已经熟悉的音乐。也许这就是你想要的,但是如果你想要一些你从未听过的音乐的推荐呢?在 MP3 发明之前的美好时光里,我会去伦敦皮卡迪利大街的果酱唱片店。奥利会知道我到底在找什么样的东西,而我会在听了几秒钟后就立刻知道我是否喜欢一首曲子……这么说吧,一大笔钱转手了。

毫无疑问,有大量的音乐是我不知道的,但是没有像奥利这样的人来帮助我,我怎么能找到它呢?我不想把音乐按类别分类,而是想出一种连续的方式来组织和探索它。我不是通过关于艺术家或歌曲的信息来寻找,而是通过歌曲听起来的方式来寻找相关的东西。如果你对我如何编写一个名为 Deej-A.I .的程序的技术细节感兴趣,在不使用任何标签或任何未公开可用的数据的情况下做到这一点,那么看看这篇文章。

我在所有 Spotify 曲目上运行了我的程序,这些曲目(a)在播放列表中至少出现 10 次(截至 2018 年 10 月),并且(b)可以以 30 秒 MP3 样本的形式下载。这给了我两种关联 Spotify 歌曲的方法:一种是根据它们在播放列表中出现的接近程度,另一种是根据它们听起来的相似程度。第一种方式倾向于将相似艺术家的歌曲分组,而第二种方式将具有相似能量、情绪、节奏或乐器的歌曲放在一起。从技术上讲,这些被称为多维空间中的嵌入,其中一个轨道与另一个轨道的接近程度表示它们彼此有多相似。有趣的是:我们可以混合这两种关联音轨的方式,从而控制我们对发现类似音乐的开放程度,这些音乐可能来自我们从未听说过的艺术家。我将把这个混音参数称为创意,其中 0 表示由相似的艺术家创作,1 表示由相似的声音创作。

例如,如果我们让 Deej-A.I .根据 Luis Fonsi 的“ Despacito ”的声音生成一个播放列表(我应该说这是而不是我听的那种音乐:-),那么我们会得到以下结果。

有趣的是,我们最终得到了一堆听起来非常相似的歌曲(自动调音的人声,毁灭的节奏等等),但它们来自世界各地,使用各种不同的语言。也许这是你的事,我没资格评判。

随着新航的"吊灯"它挑选出一些惊人相似的声音歌曲,包括新航自己的一首。请记住,当创造力设置为 100%时,除了音乐听起来如何之外,没有什么可以继续。

如果我们给它一些更有挑战性的东西呢?顾名思义,“比蚊子的高音喇叭还恐怖”并不是妮娜·西蒙的典型特征。以下是 Spotify 给出的结果。

另一方面,Deej-A.I .因为它实际上是在听音乐,掌握时髦的非洲节奏,并提供更加连贯的播放列表。在这种情况下,我选择了 50%的创造力,以便获得类似艺术家的类似声音推荐。

将点连接起来

生成播放列表最明显的方法是添加与刚刚播放过的歌曲最接近的歌曲。正如你所看到的,这可以产生一个有趣但曲折的路径通过嵌入空间。如果你走得够久,你永远无法确定你会在哪里结束。

另一种方法是我称之为“连点”(这个术语是我从 DJ 吉勒斯·彼得森那里借来的)。您选择第一首和最后一首曲目,以及沿途您想要访问的任何其他曲目,播放列表将从最接近沿连接这些曲目的线等间距点的曲目中生成。换句话说,我们在尽可能接近的选定轨迹之间进行线性插值。这可能会导致一些有趣的结果,因为嵌入空间中的不同方向可能会以某种方式编码音乐的某些方面,如能量、人声的存在和速度等。当然,如果你计划举办一个聚会,你可以用它来开始一些放松的东西,然后通过一些众所周知的最爱,最后以室内音乐结束…

如果我们要求它制作一个播放列表,从的《权力的游戏》的主题音乐开始,到的《维京人》的主题音乐结束,我们看看它会得到什么。

如果我们尝试一些不同的流派呢?这是我之前做的一个播放列表,从迪斯科屋到电子乐,有 50%的创意。

如果你有灵感(并且有一个谷歌账户),你可以自己试一试。只需点击下面的链接,在“沙盒模式”下打开,连接到一台机器,然后按下播放按钮。

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/github/teticio/Deej-A.I./blob/master/Spotify_Discovery.ipynb)

如果你想出了一个有趣的播放列表,请在评论中加入链接。快乐聆听!

如何在 BigQuery 中直接批量预测张量流模型

原文:https://towardsdatascience.com/how-to-do-batch-predictions-of-tensorflow-models-directly-in-bigquery-ffa843ebdba6?source=collection_archive---------23-----------------------

BigQuery ML 现在支持 TensorFlow SavedModel

如果您已经在 TensorFlow 中训练了一个模型,并将其导出为 SavedModel,那么您现在可以使用 ML。BigQuery 中的 PREDICT SQL 函数进行预测。如果您想要进行批量预测(例如,对过去一小时收集的所有数据进行预测),这非常有用,因为任何 SQL 查询都可以在 BigQuery 中调度。

步骤:

  • 在 TensorFlow 中训练和导出保存的模型
  • 在 BigQuery 中,创建一个模型,传递保存的模型的位置
  • 用 ML。评估,ML。预测等。就像在 BigQuery 中使用其他(内置)模型类型训练模型一样。

注意:该功能目前处于公开测试阶段。联系您的 GCP 代表获得白名单。

1.在 TensorFlow/Keras 中训练和导出保存的模型

我将使用我在这篇博文中描述的文本分类模型进行演示,其 Keras 代码在 GitHub 上。我在 Cloud ML 引擎上训练模型,但你可以在任何地方以任何方式训练它。重要的一点是将模型作为保存的模型导出到 Google 云存储中:

exporter = tf.estimator.LatestExporter('exporter', serving_input_fn)

2.创建模型

在 BigQuery 中创建模型只需指定一个不同的 model_type,并将其指向导出 SavedModel 的 model_path(注意末尾的通配符,用于选择资产、词汇等)。):

CREATE OR REPLACE MODEL advdata.txtclass_tf
OPTIONS (**model_type='tensorflow',****model_path=**'gs://cloud-training-demos/txtclass/export/exporter/1549825580/*')

我已经将上面的 bucket 设置为 public,所以您可以按原样尝试上面的查询(首先创建一个名为 advdata 的数据集)。这将在 BigQuery 中创建一个模型,其工作方式类似于任何内置模型:

特别是,该模式指出模型所需的输入称为“输入”,并且是一个字符串。

3.用模型预测

用模型预测非常简单。例如,我们可以从 BigQuery 表中提取一些数据,并确保在 select 中,我们根据 TensorFlow 的要求来命名列。在这种情况下,我的 TensorFlow 模型的 serving_input_fn 指定该模型需要一个名为“input”的输入字符串。

鉴于此,我们现在可以做一个预测:

WITH extracted AS (
SELECT source, REGEXP_REPLACE(LOWER(REGEXP_REPLACE(title, '[^a-zA-Z0-9 $.-]', ' ')), "  ", " ") AS title FROM(SELECTARRAY_REVERSE(SPLIT(REGEXP_EXTRACT(url, '.*://(.[^/]+)/'), '.'))[OFFSET(1)] AS source,titleFROM`bigquery-public-data.hacker_news.stories`WHEREREGEXP_CONTAINS(REGEXP_EXTRACT(url, '.*://(.[^/]+)/'), '.com$')AND LENGTH(title) > 10)
)
, input_data AS (SELECT title AS input FROM extracted limit 5
)SELECT *
FROM ML.PREDICT(MODEL advdata.txtclass_tf, (SELECT * FROM input_data))

这提供了结果:

知道了实际的标签,我们可以使实际的查询更好:

SELECTinput,(SELECT AS STRUCT(p, ['github', 'nytimes', 'techcrunch'][ORDINAL(s)]) prediction FROM(SELECT p, ROW_NUMBER() OVER() AS s FROM(SELECT * FROM UNNEST(dense_1) AS p)) ORDER BY p DESC LIMIT 1).*FROM ML.PREDICT(MODEL advdata.txtclass_tf,
(
SELECT 'Unlikely Partnership in House Gives Lawmakers Hope for Border Deal' AS input
UNION ALL SELECT "Fitbit\'s newest fitness tracker is just for employees and health insurance members"
UNION ALL SELECT "Show HN: Hello, a CLI tool for managing social media"
))

请注意,这个函数直接在 SQL 中提供值。结果是:

就是这样!

如何在黑盒模型上进行贝叶斯超参数调整

原文:https://towardsdatascience.com/how-to-do-bayesian-hyper-parameter-tuning-on-a-blackbox-model-882009552c6d?source=collection_archive---------16-----------------------

云 ML 引擎上任意函数的优化

谷歌云 ML 引擎提供了一个使用贝叶斯方法的超参数调整服务。它不限于 TensorFlow 或 scikit-learn。事实上,它甚至不仅限于机器学习。您可以使用贝叶斯方法来调整几乎任何黑盒模型。

为了进行演示,我将调整一个流量模型,以找到能使给定流的延迟最小的流量配置。

I’ll demonstrate the hyper-parameter tuning on a traffic model. Photo by Denys Nevozhai on Unsplash

1.调用要优化的黑盒函数

为了简单起见,我将在 Python 本身中实现“黑盒函数”(它改编自几个数值软件包中使用的一个例子)。在现实生活中,您可以调用任何可执行文件,因此您不局限于 Python。只要确保得到一个与您想要最小化或最大化的东西(在这个例子中是延迟)相对应的浮点值。

def compute_delay(flow, x12, x32):# traffic on other roads, assuming all traffic that arrives# at an intersection has to leave itx13 = flow - x12x24 = x12 + x32x34 = x13 - x32 # travel time on each road segmentt12 = 5 + .1 * x12 / (1\. - x12 / 10.);t13 = x13 / (1\. - x13 / 30.);t32 = 1\. + x32 / (1\. - x32 / 10.);t24 = x24 / (1\. - x24 / 30.);t34 = 5 + .1 * x34 / (1\. - x34 / 10.);# total delayf = t12*x12 + t13*x13 + t32*x32 + t24*x24 + t34*x34;return(f);

给定节点间的交通流量和我们期望的车辆/小时总流量,上面的模型计算道路网络中的总交通延迟。

我们需要为某个流量值找到 x12 和 x32 的最佳值。

2.创建命令行参数

确保每个可优化的参数都是命令行参数:

 parser = argparse.ArgumentParser()parser.add_argument('--x12', type=float, required=True)**parser.add_argument('--x32', type=float, required=True)**

3.调用 hypertune 软件包

然后,写出我们希望使用 hypertune 软件包优化的指标:

 hpt = hypertune.HyperTune()**hpt.report_hyperparameter_tuning_metric**(**hyperparameter_metric_tag='delay'**,metric_value=delay,global_step=1)

4.编写 hyperparam.yaml 文件

编写一个配置文件。该文件应该包含要在其上运行代码的机器的类型、要优化的指标的名称以及要优化的每个参数的约束条件:

trainingInput:scaleTier: CUSTOM**masterType: standard  # machine-type**hyperparameters:goal: MINIMIZEmaxTrials: 10maxParallelTrials: 2**hyperparameterMetricTag: delay**params:- parameterName: x12type: DOUBLEminValue: 0maxValue: 10scaleType: UNIT_LINEAR_SCALE**- parameterName: x32type: DOUBLEminValue: 0maxValue: 10scaleType: UNIT_LINEAR_SCALE**

5.将超参数调整作业提交给 ML 引擎

您可以使用 REST API 或 Python,但最简单的方法是从命令行使用 gcloud:

#!/bin/bash
BUCKET=<yourbuckethere>
JOBNAME=hparam_$(date -u +%y%m%d_%H%M%S)
REGION=us-central1
gcloud ml-engine jobs **submit training** $JOBNAME \--region=$REGION \--module-name=**trainer.flow** \--package-path=$(pwd)/trainer \--job-dir=gs://$BUCKET/hparam/ \**--config=hyperparam.yaml** \-- \--flow=5

6.在 GCP 控制台上查看结果

等待作业完成,并在 GCP 控制台上查看结果。我有:

 {"trialId": "8","hyperparameters": {**"x12": "0.70135653339854276","x32": "0.018214831148084532"**},"finalMetric": {"trainingStep": "1",**"objectiveValue": 50.2831830645**}},

这种道路配置的实际最佳值是 40.3 的延迟;即使搜索空间很大并且问题是非线性的,我们在 10 次尝试中还是得到了相对接近的结果。

后续步骤:

  1. 试试看。的完整代码在 GitHub 上。
  2. 阅读关于超参数调整的 ML 引擎文档。
  3. 阅读可用的机器类型的 ML 引擎文件。

如何使用 DataOps 提高数据质量

原文:https://towardsdatascience.com/how-to-do-data-quality-with-dataops-90c1ab94e626?source=collection_archive---------16-----------------------

利用数据测试和安全环境使数据质量成为接触数据的每个人的日常活动

Image Source: Pixbay

坏数据的代价

数据质量差的成本如此之高,以至于许多人难以相信这些统计数据。Gartner 估计,由于数据质量差,平均每个组织每年都会损失1500 万美元。对于一些组织来说,这甚至是致命的。我经常想起我的数据科学创新峰会共同主持人、来自多米诺数据实验室的丹·恩托文讲的一个故事,关于一家高频交易公司骑士资本,他们在没有测试其效果的情况下部署了一个错误的算法更新。一天之内,该公司就自动取走了几乎所有的资本,并不得不策划向另一家公司的紧急出售。

他还提到一家信用卡公司未能验证来自第三方提供商的 FICO 信用评分字段。当该公司后来更换提供商时,新的提供商显示“无信用”,非法值为 999 (850 是最高合法值)。因为没有适当的数据质量检查,他们的自动批准算法开始批准这些具有巨大信贷限额的申请,导致重大损失。

DataOps 确保保持数据质量

在之前的一篇文章中,我讨论了向数据操作的深刻转变,这将改变数据管理的方式。就在最近,我们获得了大规模重复版本和复制数据的能力,这将使我们能够从应用于数据系统的流程和控制(即控制委员会会议)转向系统内的保证。将受到影响的数据治理的关键要素之一是数据质量管理,它将从分配给试图在数据被破坏后“清理”数据的数据管理员的任务转移到产生数据的组织内所有开发活动的一部分。

首先是几个定义,这样我们就在同一页上了:

在我们开始之前,最好给出一些将在本文中使用的定义(因为我们正在讨论数据质量,所以最好是精确的):

数据源 —随着时间的推移生成数据并使该数据作为数据实体可供消费的任何东西。可能是运营应用程序、精细数据仓库、第三方 API、传感器等。

数据产品 —满足特定需求的数据实体,通常通过转换和组合来自数据源的数据而产生

数据管道 —一系列的转换,在这些转换中,数据从数据源流入,从数据源流出,进入数据产品

数据定义 —描述特定数据实体的元数据。该定义应该使数据消费者能够在没有额外输入的情况下使用数据实体。它通常包括实体的位置、模式和格式,以及每个字段的描述和约束。

数据质量是每个人工作的一部分

同步的另一个重要定义是您组织中使用数据产生见解的广泛人群。我称他们为数据产品创造者。他们可能来自各种背景,通常拥有数据分析师、数据工程师或数据科学家的头衔。每一个都将遵循稍微不同的开发过程,并且可能使用不同的工具集。然而,他们都应该有责任维护和提高数据质量。

The 3 types of Data Product Creators all have data quality responsibilities

为了将数据质量从事后数据管家操作转移到日常生活中,所有接触数据的角色都必须参与到保持测试最新的过程中,以保持数据的整洁。这意味着所有创建数据产品的角色都必须考虑通常分配给数据管理员的任务。这并不意味着数据管理员的角色应该完全消失,因为组织中仍然有大量的数据源和数据集没有进行积极的开发。

数据操作和测试驱动的开发

编译器需要比它们编译的代码更健壮。鉴于数据管道代码实际上只是将数据编译成数据产品,并且在编写代码时数据本身不受您的控制,您的数据管道代码应该足够健壮以处理任何可能的数据场景。当构建库代码时,软件开发人员通常利用像微软 Intellitest 这样的工具来生成考虑到所有可能的输入场景的测试输入。

“我们希望管道所有者将模式视为与源代码同等的生产资产,并采用最佳实践来审查、版本化和维护模式。”—谷歌数据工程

在 DataOps 中,当开发使用数据作为输入的新代码(即数据管道代码)时,数据定义(即可能值的模式和规则集)必须准确表示输入数据的预期约束。为了引导这个过程,像 Great Expectations 这样的库可以用来从示例数据中生成数据定义的约束。从那里,数据工程师或分析师可以修改和添加额外的约束。接下来,一个数据模糊库,比如谷歌的 LibFuzz 结构化模糊库或 Faker ,可以用来基于数据定义中的约束生成潜在的数据输入。基于这些测试产生的失败,输入有助于强化处理代码和数据定义。关于谷歌使用的实践的更多细节可以在本文中找到。大多数情况下,这种能力揭示了使数据定义更清楚地了解什么是可能的所需的更新,但有时它也揭示了可能破坏数据管道的代码错误。

数据测试和代码测试有许多共同的特点。这些测试被提交到源代码控制中,并且可以作为持续集成过程的一部分运行,使用像 Jenkins 或 Circle CI 这样的工具,测试的覆盖率可以根据样本数据集进行测量。然而,数据测试在一个重要方面有所不同:如果它们失败了,就会留下坏数据需要清理。在传统的数据开发架构中,确保数据管道真正工作的唯一方法。因此,在创建测试以评估数据质量时,数据产品创建者应该在安全的开发环境中工作,使用 DataKitchen 所谓的修复架构的权利。这允许他们创建或修改数据产品,而不会将坏数据引入生产中。

在许多情况下,测试变得更加困难,因为交付的数据产品只是生成它们的数据输入的表示(例如填充仪表板的图表和图形)。在这种情况下,很难编写基于代码的单元测试来为数据集指定完整的约束集。因此,这组测试通常确保管道不会以意外的方式中断,但不能保证数据是高质量的。这与编译器不检查代码中的业务逻辑缺陷非常相似。在敏捷软件开发中,编码人员必须与产品负责人一起工作,为要接受的特性定义测试。在数据产品开发中,数据所有者应该能够指定他们在数据中期望的条件,而不需要太复杂的编码。

数据定义和持续集成

这样,数据质量的定义就成为数据定义的内在内容:

  1. 数据定义被视为一级代码:版本化、测试和发布
  2. 在合并或混合多个输入的流水线步骤中,输入被指定为一个组,允许为输入数据之间的关系编写测试。
  3. 当数据加载到生产中的数据平台时,会根据数据定义对数据进行检查。这些检查可用于将统计过程控制应用于运行平台。

通过结合这些原则,团队可以保证在接收时捕获数据问题。

The data validation procedure in use at Google, from: Data validation for machine learning

调试问题和根本原因自动化

在任何系统中,最终用户都会发现一些问题。在自助服务的世界里,我们希望数据消费者能够快速、轻松地报告他们正在利用的数据产品的问题。仅仅能够报告问题,并为其他数据消费者记录这些问题并不能建立信任。对于数据所有者来说,快速确定根本原因并解决问题非常重要。然而,众所周知,诊断数据问题既困难又耗时。出现的问题是:

  1. What :问题是由代码中的错误还是来源处的错误输入数据引起的?
  2. 哪里:如果是一个代码错误,这个问题是在管道的哪个阶段引入的?
  3. 如何:如果是源问题,我们对源数据的理解是否正确?
  4. 谁:如果是源问题,用户是否贡献了其他不良数据?
  5. 多大:还有哪些数据产品使用同样的不良输入数据(因此也是不正确的)?
  6. When :在哪个时间点引入了数据问题(存在多少其他类似的坏数据)?

有了数据和管道代码版本控制,以及针对管道中的数据持续运行的测试,我们可以更快地回答这些问题。

有了 DataOps 基础,就可以系统地获得上述根本原因(什么、哪里和如何)问题的答案。详细的数据沿袭允许我们利用以下过程:

  1. 与数据消费者合作,了解他们的期望
  2. 更新数据产品定义以包含这些期望
  3. 产生一个违背期望的数据测试(潜在地利用模糊测试工具来帮助这个过程)
  4. 确定导致测试失败的特定数据输入,并确定它们是否保证数据定义更新,因为它们是不现实的
  5. 如果数据输入是真实的,返回到管道中的前一阶段,并为新的输出预期添加测试
  6. 继续向后移动并添加测试,直到您发现输出中的问题与一组特定的输入无关。在这种情况下,有问题的管道阶段是问题的根本原因。
  7. 如果到达了管道的数据源,那么源数据就是问题所在,您需要适当地丢弃管道中的数据。

由此,可以使用数据分析来确定数据问题是何时出现的。源数据上的元数据可用于确定谁导致了问题,而谱系图可以通过从数据问题的来源到其他受影响的数据产品来回答问题有多严重。

数据问题文档和解决方案

数据谱系图还为我们提供了通知受检测到的数据问题影响的数据产品的所有消费者的能力。考虑下面的高等教育注册场景,其中有多个数据管道来利用注册指标来帮助进行预算和营销。基于各种中间数据产品之间的谱系图,一旦在管道中检测到问题,系统就可以自动警告下游消费者。类似的警报模式可用于多种类型的问题(该图显示了作业失败和运行缓慢的作业中的 3 个示例问题)。这些警报允许数据消费者确定他们是否应该使用受影响的数据产品(仪表板、应用程序等)。),或者等待修复。

此外,谱系图可用于在系统中传播数据质量文档。当检测到上面显示的任何数据质量问题时,它可以自动添加为数据目录中数据定义的注释。然后,质量问题可以传播到所有下游数据产品,允许任何其他数据产品创建者了解他们正在使用的数据源中存在的数据质量问题。

这种质量问题的延续也会在没有应用校正代码的记录的元数据中记录下来。然后,当在数据管道内应用修复来纠正坏的源数据时,该修复可以传播到元数据,并且可以从源和受影响的数据定义中移除数据质量注释。

如何做 Java 的深度学习?

原文:https://towardsdatascience.com/how-to-do-deep-learning-for-java-on-the-valohai-platform-eec8ba9f71d8?source=collection_archive---------17-----------------------

Image source (unsplash) via Praveen Thotagamuwa

介绍

不久前,我偶然发现了这款名为 Valohai 的生命周期管理工具(或云服务),它的用户界面以及简单的设计和布局给我留下了深刻的印象。我和 Valohai 的一名成员就当时的服务聊得很开心,并得到了一个演示。在此之前,我已经使用 GNU Parallel 、JavaScript、Python 和 Bash 编写了一个简单的管道——另外一个完全使用了 GNU Parallel 和 Bash。我也想过用现成的任务/工作流管理工具(如 Jenkins X、Jenkins Pipeline、Concourse 或 Airflow)替换移动部件,但由于各种原因,我没有继续这个想法。

回到我们最初的对话,我注意到许多关于 Valohai 的例子和文档都是基于 Python、R 以及各自的框架和库。缺乏基于 Java/JVM 的例子或文档。所以我借此机会做了些事情。

Valohai 鼓励我使用著名的 Java 库DL4J——Java 的深度学习来实现一些东西。

在了解了 Valohai 的设计、布局和工作流程后,我对它的初步体验已经给了我很好的印象。它是开发者友好的,并且制作者已经考虑了开发者和基础设施工作流程的各个方面。在我们的世界中,后者主要由开发人员或系统运行团队运行,我们知道其中的细微差别和棘手问题。你可以从网站的功能区找到更多关于它的功能。

Achtung!只是想让你知道,从这里开始,这篇文章将更具技术性,可能包含代码片段,并提到深度学习/机器学习和基础设施相关的术语。

我们需要什么,如何需要?

对于任何机器学习或深度学习项目或倡议,目前两个重要的组件(从高级别角度来看)是代码,它们将创建并服务于整个生命周期将在其中执行的模型和基础设施。

当然,在上述之前、期间和之后都需要一些步骤和组件,但是为了简单起见,我们假设需要代码和基础设施。

代码

对于代码,我选择了一个使用 DL4J 的修改示例,它是一个 MNist 项目,有 60,000 个图像的训练集和 10,000 个手写数字图像的测试集。这个数据集可以通过 DL4J 库获得(就像 Keras 提供了它们的库存一样)。在 DL4J Cheatsheet 中的 DatasetIterators 下查找 MnistDataSetIterator ,以获得关于该特定数据集的更多详细信息。

在开始之前看看我们将使用的源代码,主要的 Java 类叫做 org.deeplearning4j .前馈. mnist . mlpmnissinglerayerrunner。

基础设施

现在很明显,我们已经决定使用 Valohai 作为我们运行实验(模型的训练和评估)的基础设施来测试 Java 示例。 Valohai 识别 git 库并直接挂钩到它们,允许执行我们的代码,而不管平台或语言如何——我们将看到这是如何工作的。这也意味着,如果你是 GitOps 或基础设施即代码的坚定支持者,你会喜欢这个工作流。

为此,我们只需要一个在 Valohai 上的账户,我们可以利用一个自由层账户,当我们注册时,可以访问各种配置的几个实例。更多详细信息,请参见计划和定价下的自由层和对比图表。对于我们想做的,免费层是绰绰有余了。

Java 和 Valohai 的深度学习

正如我们所同意的,我们将使用这两种技术来实现我们的目标,即训练一个单层模型并对其进行评估,以及查看在 Valohai 上的端到端体验。

我们将把必要的构建和运行时依赖项捆绑到 Docker 映像中,并使用它来构建我们的 Java 应用程序,训练一个模型,并通过一个简单的 valohai.yaml 文件在 Valohai 平台上对其进行评估,该文件位于项目存储库的根文件夹中。

面向 Java 的深度学习:DL4J

简单的部分是,我们在这里不需要做太多,只需构建 jar 并将数据集下载到 Docker 容器中。我们有一个预构建的 Docker 映像,其中包含构建 Java 应用程序所需的所有依赖项。我们已经将此图像推送到 Docker Hub ,您可以通过搜索dl4j-mnist-single-layer找到它(我们将使用 YAML 文件中定义的特定标签)。我们已经选择使用 GraalVM 19.1.1 作为这个项目的 Java 构建和运行时,因此它被嵌入到 Docker 映像中(关于 Docker 映像的定义,请参见 Dockerfile )。要了解更多关于 GraalVM 的信息,请查看 graalvm.org 官方网站的资源。

编排

当从命令行调用 uber jar 时,我们进入MLPMnistSingleLayerRunner类,该类根据传入的参数将我们导向预期的操作:

传递给 uber jar 的参数由该类接收,并由execute()方法处理。

我们可以通过--action train参数创建一个模型,并通过分别传递给 Java 应用程序(uber jar)的--action evaluate参数评估创建的模型。

完成这项工作的 Java 应用程序的主要部分可以在下面提到的两个 Java 类中找到。

训练一个模型

可以通过以下方式从命令行调用:

这将在由执行开始时传入的--output-dir指定的文件夹中创建名为mlpmnist-single-layer.pb的模型(当成功时,在执行结束时)。从 Valohai 的角度来看,应该是放入我们做的${VH_OUTPUTS_DIR}中(见 valohai.yaml 文件)。

有关源代码,请参见类MLPMNistSingleLayerTrain.java。

评估模型

可以通过以下方式从命令行调用:

这期望一个名为mlpmnist-single-layer.pb的模型(由训练步骤创建)出现在调用应用程序时由传入的--input-dir指定的文件夹中。

有关源代码,请参见 MLPMNistSingleLayerEvaluate.java 类。

我希望这个简短的插图能够清楚地说明训练和评估模型的 Java 应用程序一般是如何工作的。

这就是我们所需要的,但是请随意使用其余的源(以及 README.md 和 bash 脚本)来满足您的好奇心和理解这是如何完成的!关于如何使用 DL4J 的更多资源已在帖子末尾的资源部分提供。

瓦罗海

作为一个平台,Valohai 允许我们松散地耦合我们的运行时环境、代码和数据集,正如你从下面 YAML 文件的结构中看到的。这样,不同的组件可以独立发展,而不会互相妨碍或依赖。因此,我们的 Docker 容器只包含构建和运行时组件。在执行时,我们在 Docker 容器中构建 uber jar,将其上传到一些内部或外部存储,然后通过另一个执行步骤从存储(或另一个位置)下载 uber jar 和数据集来运行训练。这样,两个执行步骤是分离的;例如,我们可以构建一次 jar,然后在同一个 jar 上运行数百个训练步骤。由于构建和运行时环境不应该经常改变,我们可以缓存它们,代码、数据集和模型源可以在执行时动态可用。

valohai.yaml

将我们的 Java 项目与 Valohai 基础设施集成的核心是定义执行项目文件夹根目录下 valohai.yaml 文件中的步骤的步骤。我们的 valohai.yaml 长这样:

Build-dl4j-mnist-单层-java-app 步骤说明

从 YAML 文件中,我们可以看到,我们首先使用 Docker 映像来定义这一步,然后运行构建脚本来构建 uber jar。我们的 docker 映像具有构建环境依赖项设置(即 GraalVM JDK、Maven 等)来构建 Java 应用程序。我们不指定任何输入或参数,因为这是构建步骤。一旦构建成功,我们希望将名为MLPMnist-1.0.0-bin.jar(原始名称)的 uber jar 复制到/valohai/outputs文件夹(由${VH_OUTPUTS_DIR}表示)。该文件夹中的所有内容都会自动保存在项目的存储中,例如 AWS S3 存储桶。最后,我们定义要在 AWS 环境中运行的作业。

注意:valo hai自由层不能从 Docker 容器内部进行网络访问(默认情况下这是禁用的),请联系支持人员启用此选项(我也必须这样做),否则我们将无法在构建期间下载 Maven 和其他依赖项。**

步骤运行-dl4j-mnist-单层列车-模型的说明

定义的语义与上一步类似,只是我们指定了两个输入,一个用于 uber jar ( MLPMnist-1.0.0.jar),另一个用于 dataset(将被解压到${HOME}/.deeplearning4j文件夹中)。我们将传递两个参数--action train--output-dir /valohai/outputs。从该步骤创建的模型被收集到/valohai/outputs/model文件夹中(由${VH_OUTPUTS_DIR}/model表示)。

注意:在 Valohai Web UI 的 Executions 选项卡的输入字段中,除了使用 datum://或 http:// URLs 之外,我们还可以使用执行编号,即* *#1* *#2* 来选择以前执行的输出。键入文件名的几个字母也有助于搜索整个列表。*

步骤运行-dl4j-mnist-单层评估-模型的说明

同样,这一步类似于上一步,除了我们将传入两个参数--action evaluate--input-dir /valohai/inputs/model。此外,我们再次指定了在 YAML 文件中定义的两个inputs:部分,称为dl4j-java-appmodel,它们都没有设置default。这将允许我们使用 web 界面选择 uber jar 和我们希望评估的模型——它是通过步骤Run-dl4j-mnist-single-layer-train-model创建的。

希望这解释了上述定义文件中的步骤,但如果您需要进一步的帮助,请不要犹豫,看看文档和教程。

一旦我们有了一个帐户,我们就可以登录并继续创建一个名为mlpmnist-single-layer的项目,将 git repohttps://github.com/valohai/mlpmnist-dl4j-example链接到该项目并保存该项目,快速浏览教程以了解如何使用 web 界面创建项目。

现在您可以执行一个步骤,看看结果如何!

构建 DL4J Java 应用程序步骤

转到 web 界面中的执行选项卡,使用【创建执行】按钮复制一个现有的或创建一个新的执行,所有必要的默认选项将被填充,选择步骤Build-dl4j-mnist-single-layer-Java-app。

对于环境,我将选择 AWS eu-west-1 g2.2xlarge ,并单击页面底部的【创建执行】按钮,以查看执行开始。

训练模型步骤

进入 web 界面的执行页签,与上一步相同,选择步骤运行-dl4j-mnist-单层-列车-模型。您必须选择在上一步中构建的 Java 应用程序(只需在字段中键入 jar ),数据集已经通过 valohai.yaml 文件预先填充:

点击【创建执行】开始此步骤。

您将在日志控制台中看到模型摘要:

在执行期间和结束时,可以在执行主选项卡的输出子选项卡下找到创建的模型:

您可能已经注意到了输出子选项卡中的几个工件。这是因为我们在每个时期结束时都会保存一个检查点!在执行日志中注意这些:

检查点 zip 包含模型训练在该点的状态,保存在以下三个文件中:

训练模型>元数据

您可能已经注意到这些符号在执行日志中飞快地闪过:

这些符号触发 Valohai 拾取这些值(以 JSON 格式),用于绘制执行指标,在执行期间和执行之后,可以在执行主选项卡中的元数据子选项卡下看到这些值:

我们能够通过将一个监听器类(名为 ValohaiMetadataCreator )挂接到模型中来做到这一点,这样在训练期间,注意力会在每次迭代结束时传递给这个监听器类。在这个类的例子中,我们打印了历元计数迭代计数分数(损失函数值),下面是这个类的代码片段:

评估模型步骤

一旦通过前面的步骤成功地创建了模型,我们就可以开始评估它了。我们像前面一样创建一个新的执行,但是这次选择Run-dl4j-mnist-single-layer-evaluate-model步骤。在开始执行之前,我们需要再次选择 Java 应用程序( MLPMnist-1.0.0.jar )和创建的模型(MLPMnist-single-layer . Pb)(如下所示):

选择所需的模型作为输入后,点击【创建执行】按钮。这是一个比前一个更快的执行步骤,我们将看到以下输出:

模型分析后的评估指标混淆矩阵将显示在控制台日志中。

我们可以看到,我们的培训活动已经产生了基于测试数据集的接近 97% 准确度的模型。混淆矩阵有助于指出一个数字被错误地预测为另一个数字的情况。也许这对模型的创建者和数据集的维护者来说是一个很好的反馈,可以做一些进一步的研究。**

问题依然存在(不在本文讨论范围之内)——当面对真实世界的数据时,模型有多好?

CLI 工具很容易安装和使用,参见命令行用法。

如果您还没有克隆 git 存储库,那么应该这样做:

*$ git clone [https://github.com/valohai/mlpmnist-dl4j-example](https://github.com/valohai/mlpmnist-dl4j-example)*

然后,我们需要将通过上一节中的 web 界面创建的 Valohai 项目链接到存储在本地机器上的项目(我们刚刚克隆的项目)。为此,请运行以下命令:

您将看到类似这样的内容:

选择 1(或适合您的选项),您应该会看到以下消息:

😁 Success! Linked /path/to/mlpmnist-dl4j-example to mlpmnist-single-layer.

使用 CLI 工具了解所有 CLI 选项的最快方法是:

*$ vh — help*

还有一件事,在继续之前,确保你的 Valohai 项目与最新的 git 项目同步,通过这样做:

*$ vh project fetch*

(在 web 界面的右上方,显示有两个指向彼此的箭头图标)。

现在,我们可以使用以下命令从 CLI 执行这些步骤:

*$ vh exec run Build-dl4j-mnist-single-layer-java-app*

一旦执行开始,我们可以通过以下方式检查和监控它:

我们还可以同时通过 web 界面看到上述更新。

关于如何使用 Valohai 的更多资源已在本文末尾的参考资料部分提供,还有一些关于如何使用 CLI 工具的博客文章,请参见【1】|【2】。

结论

如你所见,DL4J 和 T21 单独或组合使用都很容易上手。此外,我们可以在组成我们实验的不同组件上进行开发,即构建/运行时环境、代码和数据集,并以松散耦合的方式将它们集成到执行中。

本文中使用的模板示例是开始构建更复杂项目的好方法。您可以使用 web 界面或 CLI 通过 Valohai 完成您的工作!使用 CLI,您还可以将其与您的设置和脚本集成(甚至与 CRON 或 CI/CD 作业集成)。

此外,很明显,如果我在从事一个 AI/ML/DL 相关的项目,我就不需要关心创建和维护一个端到端的管道(过去许多其他人和我不得不这么做)——这要感谢 Valohai 的人们所做的出色工作。

感谢sky mind(背后的启动DL4J,用于创建、维护和保持免费)和valo hai让这个工具和云服务可以免费和商业使用。

请在下面的评论中留言或者发微博告诉我这是否有帮助,我也欢迎反馈。

资源

  • mlpmnist-dl4j-GitHub 上的示例项目
  • 牛逼的 AI/ML/DL 资源
  • Java AI/ML/DL 资源
  • 深度学习和 DL4J 资源

其他 DL4J 资源

损失函数

  • DL4J 的损失功能接口
  • 所有机器学习者都应该知道的 5 个回归损失函数

估价

  • https://deep learning 4j . org/docs/latest/deep learning 4j-nn-evaluation

瓦罗海资源

  • 瓦罗海 | 文档 | 博客 | GitHub | 视频 | 展柜 | 关于瓦罗海 | 懈怠|@瓦罗海
  • 关于如何使用 CLI 工具的博文:【1】|【2】

其他资源

  • 牛逼的 Graal|graalvm.org

最初发表于 https://blog.valohai.com。

如何用图卷积网络在图上做深度学习

原文:https://towardsdatascience.com/how-to-do-deep-learning-on-graphs-with-graph-convolutional-networks-62acf5b143d0?source=collection_archive---------1-----------------------

第 2 部分:谱图卷积的半监督学习

图的机器学习是一项困难的任务,因为图的结构非常复杂,但也能提供丰富的信息。本文是关于如何使用图形卷积网络(GCNs)对图形进行深度学习的系列文章中的第二篇,GCNs 是一种强大的神经网络,旨在直接对图形进行处理并利用其结构信息。我将对上一篇文章做一个简要的回顾,但是你可以在这里找到这个系列的其他部分:

  1. 图卷积网络的高级介绍
  2. 谱图卷积的半监督学习(this)

在上一篇文章中,我对 GCNs 进行了高层次的介绍,并展示了如何根据相邻节点的表示来更新节点的表示。在这篇文章中,我们首先深入了解在上一篇文章中讨论的相当简单的图卷积中执行的聚合。然后我们继续讨论最近发布的图卷积传播规则,我展示了如何在小型社交网络 Zachary's 空手道俱乐部的社区预测任务中实现和使用它进行半监督学习。如下所示,GCN 能够学习每个节点的潜在特征表示,该潜在特征表示将两个社区分成两个合理内聚和分离的聚类,尽管每个社区仅使用一个训练示例。

Latent node representations of Zachary’s Karate Club in a GCN at each training epoch.

简要回顾

在我上一篇关于 GCNs 的文章中,我们看到了一个简单的数学框架来表达 GCNs 中的传播。简而言之,给定一个 N × F⁰ 特征矩阵t5】x和一个图结构的矩阵表示,例如 GN × N 邻接矩阵 A ,GCN 中的每一个隐层可以表示为hⁱ= f(【t24) a)其中h⁰=xf 是一个传播规则。 每层 Hⁱ 对应一个n×f特征矩阵,其中每一行都是一个节点的特征表示。**

我们看到了以下形式的传播规则

  1. f(hⁱa)=σ(ahⁱwⁱ),
  2. f(a)=σ(dâhⁱwⁱ)

这些规则在通过应用权重【wⁱ和激活函数 σ 进行变换之前,将节点的特征表示计算为其邻居 的特征表示的集合。我们可以通过将上面的传播规则 1 和 2 表示为f(hⁱa)= transform(aggregate(【a,hⁱ),wⁱ)其中 **)=【σ】(mwⁱ)合计()=**ahⁱ********

正如我们在上一篇文章中所讨论的,规则 1 中的聚合将结点表示为其相邻要素表示的总和,这有两个明显的缺点:

  • 节点的聚集表示不包括它自己的特征,并且
  • 度数较大的结点在其要素制图表达中将具有较大的值,而度数较小的结点将具有较小的值,这可能会导致梯度爆炸的问题,并使得使用对要素缩放敏感的随机梯度下降等算法进行训练变得更加困难。

为了解决这两个问题,规则 2 首先通过将单位矩阵添加到来实施自循环,并使用转换后的邻接矩阵= A+I进行聚合。接下来,通过与逆度矩阵d相乘来归一化特征表示,将集合变成平均值,其中集合的特征表示的比例对于节点度是不变的。

在下文中,我将把规则 1 称为求和规则,把规则 2 称为平均规则。

光谱图卷积

Kipf 和 Welling 最近的一篇论文提出了使用光谱传播规则的快速近似光谱图卷积[1]:

与上一篇文章中讨论的求和规则和均值规则相比,谱规则的不同之处仅在于聚合函数的选择。虽然它有点类似于均值规则,因为它使用度数矩阵 D 的负幂来标准化聚集,但是标准化是不对称的。让我们试一试,看看它能做什么。

作为加权和的聚合

我们可以将我到目前为止介绍的聚合函数理解为加权和,其中每个聚合规则的不同之处仅在于它们对权重的选择。在继续讨论谱规则之前,我们首先来看看如何将相对简单的和与平均规则表达为加权和。

求和规则 为了了解如何使用求和规则计算第 i 个节点的集合特征表示,我们来看看如何计算集合中的第 i 行。

The Sum Rule as a Weighted Sum

如以上等式 1a 所示,我们可以将第 i 个节点的集合特征表示计算为向量矩阵乘积。我们可以将这个向量矩阵乘积公式化为一个简单的加权和,如等式 1b 所示,其中我们对 X 中的 N 行中的每一行求和。

等式 1b 中聚集的第 j 个节点的贡献由第 A 的第 i 行的第 j 列的值确定。由于是邻接矩阵,如果第 j 个节点是第 i 个节点的邻居,则该值为 1,否则为 0。因此,等式 1b 对应于对第 i 个节点的邻居的特征表示求和。这证实了前一篇文章中的非正式观察。

总之,每个邻居的贡献仅取决于由邻接矩阵定义的邻居。

平均值规则 为了查看平均值规则如何聚合节点表示,我们再次查看如何计算聚合中的第 i 行,现在使用平均值规则。为了简单起见,我们只考虑“原始”邻接矩阵上的平均规则,而不考虑和单位矩阵 I 之间的加法,这简单地对应于将自循环添加到图中。

The Mean Rule as a Weighted Sum

从上面的等式中可以看出,现在求导的时间稍微长了一点。在等式 2a 中,我们现在首先通过将邻接矩阵 A 乘以度矩阵 D 的逆矩阵来对其进行变换。这个计算在等式 2b 中变得更加清楚。逆度矩阵是一个对角矩阵,其中沿对角线的值是逆节点度 s.t .位置( i,i) 的值是第 i 个节点的逆度。因此,我们可以去掉求和符号之一,得到等式 2c。方程 2c 可以进一步简化,得到方程 2d 和 2e。

如等式 2e 所示,我们现在再次对邻接矩阵中的 N 行中的每一行求和。正如在讨论求和规则时提到的,这对应于对每个第 i 个节点的邻居求和。然而,等式 2e 中的加权和中的权重现在被保证用第 i 个节点的度求和为 1。因此,等式 2e 对应于第 i 个节点的邻居的特征表示的平均值。

求和规则仅依赖于由邻接矩阵定义的邻域,而平均值规则也依赖于节点度数。

光谱规则我们现在有了一个有用的框架来分析光谱规则。让我们看看它会把我们带到哪里!

The Spectral Rule as a Weighted Sum

与均值规则一样,我们使用度矩阵 d 来变换邻接矩阵 A。然而,如等式 3a 所示,我们将度矩阵提升到-0.5 的幂,并将其乘以 A 的每一侧。该操作可以分解为等式 3b 所示。再次回忆,度矩阵(及其幂)是对角。因此,我们可以进一步简化方程 3b,直到得到方程 3d 中的表达式。

等式 3e 显示了一些非常有趣的东西。当计算第 I 个节点的聚集特征表示时,我们不仅考虑第 I 个节点的度,还考虑第 j 个节点的度。

与平均值规则类似,光谱规则对聚合 s.t .进行归一化。聚合要素制图表达与输入要素保持大致相同的比例。但是,谱规则在加权和中对低度数邻居的权重较高,对高度数邻居的权重较低。当低度相邻比高度相邻提供更多有用信息时,这可能是有用的。

基于 GCNs 的半监督分类

除了谱规则,Kipf 和 Welling 还演示了 GCNs 如何用于半监督分类[1]。在半监督学习中,我们希望利用有标签和无标签的例子。到目前为止,我们已经隐含地假设整个图是可用的,也就是说,我们处于转导设置中。换句话说,我们知道所有的节点,但不知道所有的节点标签。

在我们看到的所有规则中,我们在结点邻域上进行聚合,因此共享相邻结点的结点往往具有相似的要素表示。如果图表现出同质性,即连接的节点倾向于相似(例如具有相同的标签),则该属性非常有用。同向性存在于许多现实网络中,尤其是社交网络表现出强烈的同向性。

正如我们在上一篇中看到的,即使是一个随机初始化的 GCN 仅仅通过使用图结构就可以实现同形图中节点的特征表示之间的良好分离。我们可以通过在标记的节点上训练 GCN 来更进一步,通过更新在所有节点上共享的权重矩阵来有效地将节点标记信息传播到未标记的节点。这可以按如下方式完成[1]:

  1. 通过 GCN 执行前向传播。
  2. 在 GCN 的最后一层按行应用 sigmoid 函数。
  3. 计算已知节点标签的交叉熵损失。
  4. 反向传播损失并更新每层中的权重矩阵 W。

扎卡里空手道俱乐部中的社区预测

让我们看看谱规则如何使用半监督学习将节点标签信息传播到未标签节点。正如在上一篇中一样,我们将以扎卡里的空手道俱乐部为例。

如果您想继续学习,您可以在 Jupyter 笔记本上找到数据集,其中包含训练和评估 GCN 的代码,请点击这里

扎卡里空手道俱乐部

简而言之, Zachary 的空手道俱乐部是一个小型社交网络,在这里,空手道俱乐部的管理员和教练之间发生了冲突。任务是预测空手道俱乐部的每个成员选择冲突的哪一方。网络的图示如下所示。每个节点代表一个空手道俱乐部的成员,成员之间的链接表明他们在俱乐部之外进行互动。管理员和讲师分别标有 A 和 I。

Zachary’s Karate Club

MXNet 中的谱图卷积

我在 MXNet 中实现了谱法则,这是一个易用且高效的深度学习框架。实现如下:

**class SpectralRule(HybridBlock):def __init__(self,A, in_units, out_units,activation, **kwargs):super().__init__(**kwargs) I = nd.eye(*A.shape)A_hat = A.copy() + I D = nd.sum(A_hat, axis=0)D_inv = D**-0.5D_inv = nd.diag(D_inv) A_hat = D_inv * A_hat * D_invself.in_units, self.out_units = in_units, out_unitswith self.name_scope():self.A_hat = self.params.get_constant('A_hat', A_hat)self.W = self.params.get('W', shape=(self.in_units, self.out_units))if activation == 'ident':self.activation = lambda X: Xelse:self.activation = Activation(activation) def hybrid_forward(self, F, X, A_hat, W):aggregate = F.dot(A_hat, X)propagate = self.activation(F.dot(aggregate, W))return propagate**

__init__将邻接矩阵A以及来自图卷积层的每个节点的特征表示的输入和输出维度作为输入;分别为in_unitsout_units。通过与单位矩阵I相加,将自循环添加到邻接矩阵A中,计算度矩阵D,并将邻接矩阵A转换为谱规则指定的A_hat。这种变换不是严格必需的,但是在计算上更有效,因为否则变换将在层的每次向前传递期间执行。

最后,在__init__with子句中,我们存储了两个模型参数— A_hat存储为常量,权重矩阵W存储为可训练参数。

奇迹就发生在这里。在前向传递中,我们使用以下输入执行该方法:X,前一层的输出,以及我们在构造函数__init__中定义的参数A_hatW

构建图形卷积网络

现在我们有了光谱规则的实现,我们可以将这样的层堆叠在彼此之上。我们使用类似于上一篇文章中的两层架构,其中第一个隐藏层有 4 个单元,第二个隐藏层有 2 个单元。这种体系结构可以很容易地将产生的二维嵌入可视化。它与前一篇文章中的架构有三点不同:

  • 我们使用光谱法则而不是平均值法则。
  • 我们使用不同的激活函数:在第一层中使用 tanh 激活函数,因为否则死亡神经元的概率会非常高,并且第二层使用同一性函数,因为我们使用最后一层来分类节点。

最后,我们在 GCN 之上添加一个逻辑回归层用于节点分类。

上述架构的 Python 实现如下。

**def build_model(A, X):model = HybridSequential() with model.name_scope():features = build_features(A, X)model.add(features) classifier = LogisticRegressor()model.add(classifier) model.initialize(Uniform(1)) return model, features**

我已经将包含图卷积层的网络的特征学习部分分成了一个features组件,将分类部分分成了classifier组件。独立的features组件使得稍后可视化这些层的激活更加容易。LogisticRegressor作为分类层,通过对最后一个图形卷积层提供的每个节点的特征求和并对该和应用 sigmoid 函数来执行逻辑回归。

你可以在 中找到构造 *features* 组件的代码和 *LogisticRegressor* 组件的代码。

训练 GCN

用于训练 GCN 模型的代码如下所示。简而言之,我初始化一个二元交叉熵损失函数cross_entropy和一个 SGD 优化器trainer来学习网络参数。然后,该模型被训练特定数量的时期,其中为每个训练示例计算loss,并且使用loss.backward()反向传播误差。然后调用trainer.step来更新模型参数。在每个时期之后,由 GCN 层构建的特征表示被存储在feature_representations列表中,我们将很快对此进行检查。

**def train(model, features, X, X_train, y_train, epochs):cross_entropy = SigmoidBinaryCrossEntropyLoss(from_sigmoid=True)trainer = Trainer(model.collect_params(), 'sgd',{'learning_rate': 0.001, 'momentum': 1}) feature_representations = [features(X).asnumpy()] for e in range(1, epochs + 1):for i, x in enumerate(X_train):y = array(y_train)[i]with autograd.record():pred = model(X)[x] # Get prediction for sample xloss = cross_entropy(pred, y)loss.backward()trainer.step(1) feature_representations.append(features(X).asnumpy()) return feature_representations**

至关重要的是,只有教师和管理员的标签被标记,网络中的其余节点是已知的,但未被标记!GCN 可以在图卷积期间找到标记和未标记节点的表示,并且可以在训练期间利用这两种信息源来执行半监督学习。

具体来说,半监督学习发生在 GCN 中,因为它通过聚集节点的标记和未标记邻居来产生节点的潜在特征表示。在训练期间,我们然后反向传播监督的二进制交叉熵损失,以更新所有节点共享的权重。然而,这种损失取决于标记节点的潜在特征表示,而潜在特征表示又取决于标记节点和未标记节点。因此,学习变成半监督的。

可视化特征

如上所述,存储每个时期的特征表示,这允许我们看到特征表示在训练期间如何变化。在下文中,我考虑两种输入特征表示。

表示 1 在第一种表示中,我们简单地用稀疏的 34 × 34 单位矩阵, I 作为特征矩阵X,即对图中每个节点的一键编码。这种表示的优点在于,它可以用于任何图中,但是导致网络中每个节点的输入参数,这需要大量的存储器和计算能力用于大型网络上的训练,并且可能导致过拟合。谢天谢地,空手道俱乐部网络相当小。使用这种表示对网络进行 5000 个时期的训练。**

Classification Errors in the Karate Club using Representation 1

通过对网络中的所有节点进行集体分类,我们得到了网络中的误差分布,如上图所示。这里,黑色表示分类错误。尽管有将近一半(41%)的节点被错误分类,但是与管理员或教师(但不是两者)都有密切联系的节点。)倾向于正确分类。

Changes in Feature Representation during Training using Representation 1

在左侧,我已经说明了特征表示在训练过程中是如何变化的。节点最初紧密地聚集在一起,但是随着训练的进行,教师和管理员被拉开,拖着一些节点。

尽管管理员和教师被给予完全不同的表示,但是他们所拖动的节点不一定属于他们的社区。这是因为图卷积在特征空间中将共享邻居的节点紧密地嵌入在一起,但是共享邻居的两个节点可能不平等地连接到管理员和教师。特别地,使用单位矩阵作为特征矩阵导致每个节点的高度局部表示,即,属于图的相同区域的节点可能紧密地嵌入在一起。这使得网络难以以归纳的方式在遥远的区域之间共享公共知识。

表示 2
我们将通过添加两个不特定于网络的任何节点或区域的特征来改进表示 1,这两个特征测量与管理员和教师的连通性。为此,我们计算从网络中的每个节点到管理员和教师的最短路径距离,并将这两个特征连接到之前的表示。

On 可能会认为这是一种欺骗,因为我们注入了关于图中每个节点位置的全局信息;应该(理想地)由features组件中的图形卷积层捕获的信息。然而,图卷积层总是具有局部视角,并且捕获这种信息的能力有限。尽管如此,它仍然是理解 gcn 的有用工具。

Classification Errors in the Karate Club using Representation 1

如前所述,我们对网络中的所有节点进行分类,并绘制网络中的误差分布图,如上图所示。这一次,只有四个节点被错误分类;相对于表示 1 的显著改进!根据对特征矩阵的更仔细的检查,这些节点或者与教师和管理员等距(在最短路径意义上),或者更靠近管理员但属于教师团体。使用表示 2 对 GCN 进行 250 个时期的训练。

Changes in Feature Representation during Training using Representation 2

如左图所示,节点最初还是非常紧密地聚集在一起,但是在训练开始之前就已经分成了几个社区!随着训练的进行,社区之间的距离增加了。

下一步是什么?

在这篇文章中,我已经深入解释了 gcn 中的聚合是如何执行的,并以均值、求和以及谱规则为例,展示了如何将其表示为加权和。我真诚的希望你会发现这个框架对于考虑在你自己的图卷积网络中聚合时你可能想要的权重是有用的。

我还展示了如何在 MXNet 中实现和训练一个 GCN,使用谱图卷积在图上执行半监督分类,并以 Zachary 的空手道俱乐部作为一个简单的示例网络。我们看到了仅使用两个带标签的节点,GCN 仍有可能在表示空间中实现两个网络社区之间的高度分离。

虽然还有很多关于图卷积网络的知识需要学习,我希望将来有时间与你分享,但这是(目前)这个系列的最后一篇文章。如果你对进一步阅读感兴趣,我想以下列我认为相当有趣的论文作为结束:

  1. 大型图上的归纳表示学习
    在这篇论文中,Hamilton 等人提出了几个新的聚合函数,例如,使用 max/mean pooling 或多层感知器。此外,他们还提出了一种简单的方法对 GCNs 进行小批量训练,大大提高了训练速度。
  2. 陈等人。al 提出了他们的 FastGCN 方法,该方法通过独立地执行图卷积层的批量训练来解决这个缺点。
  3. N-GCN:用于半监督节点分类的多尺度图卷积
    其中 FastGCN 解决了训练递归图卷积网络的问题,N-GCN 挑战了 GCNs 完全需要递归的前提!相反,Abu-El-Haija 等人提出了一种具有多个(N 个)gcn 的扁平架构,其输出被连接在一起。每个 GCN 在不同的距离捕获邻域(基于随机行走语义),从而避免递归聚集。感谢 Binny Mathew 让我注意到这一点。

喜欢你读的书吗?考虑在 Twitter 上关注我,在那里,除了我自己的帖子之外,我还分享与数据科学和机器学习的实践、理论和伦理相关的论文、视频和文章。

如需专业咨询,请在LinkedIn上联系我,或在Twitter上直接留言。**

参考

[1] 论文名为带有图卷积网络的半监督分类作者 Thomas Kipf 和 Max Welling。

如何进行误差分析以使你所有的模型更好

原文:https://towardsdatascience.com/how-to-do-error-analysis-to-make-all-of-your-models-better-a13c4ca643a?source=collection_archive---------2-----------------------

循序渐进的指南

From Pexels

介绍

有很多方法可以改进开箱即用的机器学习模型。您可以对模型和数据做一些事情,以获得比标准 scikit-learn 版本的模型更好的结果。有特征工程、超参数调整和选择正确的成本函数。如果我们进入深度学习,那么我们接近网络架构、迁移学习和许多其他的想法。作为一名数据科学家,这些是你学习建模的第一步,也是最重要的一步。像随机搜索和网格搜索这样的工具应该在每个数据科学家的工具箱中,以帮助优化这一过程,并建立可能的最佳模型。

当你在一个项目中工作时,大多数人做了我上面提到的所有事情,然后,通过交叉验证或训练测试分割,获得一些评估指标。重复这些步骤,直到获得可能的最佳度量分数,并且认为该模型值得使用。这绝不是一条糟糕的道路。它通常会产生优秀的模型,以它们应该的方式提供价值。然而,只要付出一点额外的努力,你就能让你构建的每一个模型都变得更好。我们可以通过误差分析来实现这一点。

误差分析

这是什么?

当建立一个模型时,你可以随机地或者有意识地去做。建立模型的随机方法很容易被采用。它需要更少的努力,但仍然会带来结果。一种随机的方法是,在一个模型的每次迭代之后,你决定尝试一些新的东西来使它变得更好,而不去想为什么。很简单:一个可能会提高 F1 分数的想法突然出现在你的脑海中,为什么不试试呢?这很简单,也很有效。

https://imgs.xkcd.com/comics/machine_learning.png

建立模型的有意方法是使用误差分析。错误分析要求您在每次迭代后深入研究模型的结果。你在观察的层面上观察数据和预测,并形成假设,解释为什么你的模型在某些预测上失败了。然后,您通过以可能修复错误的方式更改模型来测试您的假设,并开始下一次迭代。随着误差分析的进行,建模的每一次迭代都变得更加耗时,但是最终的结果会更好,并且可能会更快到达。

进行误差分析的正确方法

没有一种固定的方法可以让你进行错误分析。它是探索性的,需要一些创造力和领域知识。也就是说,我会给你我通常喜欢采取的步骤。希望这能给你一个起点,让你从挖掘模型的错误中找到深刻的见解。

误差分析过程

对于模型的每一次迭代,我都从这些步骤的开头开始,并遍历它们,直到我找到应该修复的东西。我提出我的假设,改变我的模型,重新开始这个过程,直到我满意为止。在这一节中,我将向您介绍我采取的步骤,一些您可能会发现错误的地方,以及一些可能的修复方法。我们将从最高级别的数据到最低级别的数据,一路寻找错误。

数据级错误

这可能是最常见的错误分析类型,大多数人都这样做。我喜欢从观察所有数据的模型误差开始。

过拟合/欠拟合

检查你的模型是否过度或不足。我最喜欢的方法是使用学习曲线,如下图所示。

Learning Curve from Scikit-Learn

一般来说,我在实践中发现,最好是先过度拟合,然后使用调节技术将模型带回到一个好的位置。

潜在修复:

  • 如果过度拟合,则 L1 或 L2 正则化或更多数据
  • 如果拟合不足,则需要更复杂的模型或更多的特征

预测分布

确保数据的分布看起来与预测的分布有些相似。如果它们看起来不相似,那我们就有问题了。

潜在修复:

  • 从数据中移除异常值
  • 使用不同的成本函数

组级错误

一旦数据级别的错误得到处理,我们就可以按组查看错误。这部分误差分析的目的是识别模型表现差的组。在决定如何创建组时,一些领域知识会有所帮助。我建议从数据中已经存在的明显的群体开始,然后根据直觉创建群体。例如,我可能会先通过分类变量来查看预测误差,然后再将数字变量拆分到多个箱中进行检查。在观察群体时,我总是会留意一些具体的事情。

预测过高/过低

查看是否有任何特定的组,该模型在很长时间内高估或低估了这些组。如果一个模型总是过度预测某个群体,这似乎是我们可以教它解决的问题。如果表现不佳的小组缺乏数据,也要注意。

潜在修复:

  • 惩罚对该组过度预测
  • 缺少数据时的过采样方法
  • 如果缺少数据,则收集数据

平均误差大

查看是否有任何组比所有其他组对总误差的贡献更大。出于多种原因,这一点很重要。首先,我们显然想知道哪里出了问题,以便能够修复。第二,它关系到模型的可解释性和应用。如果一个模型在除了一个组之外的所有组上都表现良好,如果它不能被修复,您可能只想将该模型用于除该组之外的所有事情。

潜在修复:

  • k-分层交叉验证,以确保每次分裂的群体观察
  • 缺少数据时的过采样方法
  • 数据收集缺乏数据

个别错误

现在我们开始讨论实质问题。一旦我们完成了所有更高层次的误差分析,是时候深入每个观察的误差了。我喜欢通过查看我预测的前 20 个错误来做到这一点。与更高层次的分析不同,我对您可能会发现的常见错误没有任何建议。你应该仔细观察,查看数据和预测,并确定预测是否有效。有时模型做出了很好的预测,而观察的目标却不可靠。这些是我们可以忍受的错误。如果你认为这个观察似乎不合理,问问自己为什么。模型遗漏了哪些本应帮助它做出更好预测的信息?通过多次观察寻找可能导致错误的模式。你可能会发现一些你以前忽略的东西,你可以修复。你可能会发现,有时候你的模型就是搞砸了,你找不到原因。从这一点出发,你要么继续调整你的模型,决定去获取更多的数据,要么称你的模型是好的。

实施它

错误分析需要时间,也需要大量的思考。花时间搜索和检查模型性能差的原因。好的错误分析模式是这样的:

  • 查找错误
  • 创建一个可以修复错误的假设
  • 测试假设
  • 重复

遵循这些步骤,加上一点创造力和耐心,将有助于您构建一个比单独进行一些超参数调整更好的模型。

如果你有任何关于如何进行有效的错误分析的问题,请在下面给我留言,我会回答的!

如何使用 Python 对 Pandas Dataframe 列进行模糊匹配?

原文:https://towardsdatascience.com/how-to-do-fuzzy-matching-in-python-pandas-dataframe-6ce3025834a6?source=collection_archive---------0-----------------------

熊猫和 FuzzyWuzzy 的模糊字符串匹配

模糊字符串匹配或搜索是近似匹配特定模式的字符串的过程。这是一个非常受欢迎的 Excel 附件。它给出了一个近似的匹配,并不能保证字符串是精确的,但是,有时字符串会精确地匹配模式。字符串与给定匹配的接近程度由编辑距离来衡量。FuzzyWuzzy 使用 Levenshtein 距离 来计算编辑距离。

如何安装 FuzzyWuzzy 包

要安装 FuzzyWuzzy,您可以使用如下的 pip 命令

Pip install fuzzywuzzy
Pip install python-Levenshtein

人们也可以使用 conda 来安装 FuzzyWuzzy。以下命令将安装该库。

**conda install -c conda-forge fuzzywuzzy
conda install -c conda-forge python-levenshtein**

现在让我们导入这些包,因为我们已经成功地安装了上面提到的库。

from **fuzzywuzzy** import **fuzz**
from **fuzzywuzzy** import **process**

现在,让我告诉你如何使用它。

In[1]:fuzz.ratio(“Sankarshana Kadambari”,”Sankarsh Kadambari”)
Out[1]:92
In[2]:fuzz.partial_ratio("Sankarshana Kadambari","Sankarsh   Kadambari")
Out[2]:83

Fuzz 有各种方法可以比较字符串,比如 ratio()、partial_ratio()、Token_Sort_Ratio()、Token_Set_Ratio()。现在下一个问题是什么时候使用哪个模糊函数。你可以在这里阅读这些场景都有很好的解释。此外,我将在最后提供参考,在那里它将与代码一起被进一步详细解释。

现在博客的议程如何用这个在熊猫两栏之间的数据框然后导出到 excel?

import pandas as pd 
from fuzzywuzzy import fuzz 
from fuzzywuzzy import processdef checker(wrong_options,correct_options):names_array=[]ratio_array=[]    for wrong_option in wrong_options:if wrong_option in correct_options:names_array.append(wrong_option)ratio_array.append(‘100’)else:   x=process.
extractOne(wrong_option,correct_options,scorer=fuzz.token_set_ratio)names_array.append(x[0])ratio_array.append(x[1])return names_array,ratio_array

在上面的代码片段中,我使用了 token_set_ratio,因为它符合我的要求。我还添加了一个 if 块,通过检查第二列中的名称来减少迭代次数,因为有时出现的可能性很大。你可以在 scorer 参数中尝试各种其他方法,我在底部分享了源代码,在那里可以详细研究剩余模糊方法的工作。

我不会说这是实现模糊逻辑的唯一方法,但是您也可以自己尝试如何在减少执行时间的同时增加代码的可伸缩性。

现在让我们传递方法中的参数,并创建一个包含结果的输出 excel 文件。

df_Original_List=pd.read_excel(“Original_list.xlsx”,sheet_name=’Sheet1',usecols=[“Original Name Column”])df_To_beMatched=pd.read_excel("To be matched.xlsx",sheet_name='Sheet1',usecols=["To be Matched Column"])

为了避免错误,在将列传递给函数之前,清理列是非常重要的。主要的运行时错误是由列中的 NAN 值创建的。我用以下方式处理它们。

str2Match = df_To_beMatched[‘To be Matched Column’].fillna(‘######’).tolist()
strOptions =df_Original_List[‘Original Name Column’].fillna(‘######’).tolist()

现在让我们传递方法中的参数。

name_match,ratio_match=checker(str2Match,strOptions)df1 = pd.DataFrame()
df1[‘old_names’]=pd.Series(str2Match)
df1[‘correct_names’]=pd.Series(name_match)
df1[‘correct_ratio’]=pd.Series(ratio_match)
df1.to_excel(‘matched_names.xlsx’, engine=’xlsxwriter’)

瞧,就是这样。我希望这篇文章在你各自的领域对你有用。这是一个在 excel 中使用的非常强大的函数,但现在它也可以在 python 中用于文本分析或分析。

您可以在其他资源中找到已实现的剩余方法及其各自的工作方式。

  1. https://medium . com/@ categitau/fuzzy-string-matching-in-python-68f 240d 910 Fe
  2. https://www.geeksforgeeks.org/fuzzywuzzy-python-library/
  3. https://www . data camp . com/community/tutorials/fuzzy-string-python
  4. https://towardsdatascience . com/natural-language-processing-for-fuzzy-string-matching-with-python-6632 b 7824 c 49
  5. https://galaxydatatech . com/2017/12/31/fuzzy-string-matching-pandas-fuzzywuzzy/

如何对 BigQuery ML 模型进行超参数调优

原文:https://towardsdatascience.com/how-to-do-hyperparameter-tuning-of-a-bigquery-ml-model-29ba273a6563?source=collection_archive---------28-----------------------

使用云 AI 平台的贝叶斯优化或使用脚本的网格搜索

注意:超参数调优 现在已经内置到 BigQuery ML 中,对于简单的调优需求,您可以简单地指定一个 hparam_range。使用本文中的方法进行更复杂的超参数调优。

在进行机器学习时,有许多参数我们选择得相当随意。这些包括诸如学习速率、L2 正则化的水平、神经网络中的层数和节点数、提升树的最大深度、矩阵分解模型的因子数等因素。通常情况下,为这些值选择不同的值可能会产生更好的模型(通过保留的评估数据集上的误差来衡量)。为这些参数选择一个好的值称为超参数调整。

下面是 GitHub 中示例的完整代码。它来自我们即将出版的关于 BigQuery 的书。

The code here is from Chapter 9 of our new book on BigQuery. You can read it in early access on Safari.

使用脚本调整超参数

以 K 均值聚类模型为例。BigQuery 云控制台中的 evaluation 选项卡(以及 SELECT * from ML。EVALUATE)显示了 Davies-Bouldin 指数,该指数有助于确定数据支持的最佳分类数(数字越小,分类越好)。

例如,下面是一个尝试改变聚类数量的脚本:

DECLARE NUM_CLUSTERS INT64 DEFAULT 3;
DECLARE MIN_ERROR FLOAT64 DEFAULT 1000.0;
DECLARE BEST_NUM_CLUSTERS INT64 DEFAULT -1;
DECLARE MODEL_NAME STRING;
DECLARE error FLOAT64 DEFAULT 0;WHILE NUM_CLUSTERS < 8 DOSET MODEL_NAME = CONCAT('ch09eu.london_station_clusters_', CAST(NUM_CLUSTERS AS STRING));EXECUTE IMMEDIATE format("""CREATE OR REPLACE MODEL %sOPTIONS(model_type='kmeans', num_clusters=%d, standardize_features = true) ASSELECT * except(station_name)from ch09eu.stationstats;""", MODEL_NAME, NUM_CLUSTERS);EXECUTE IMMEDIATE format("""SELECT davies_bouldin_index FROM ML.EVALUATE(MODEL %s);""", MODEL_NAME) INTO error;IF error < MIN_ERROR THENSET MIN_ERROR = error;SET BEST_NUM_CLUSTERS = NUM_CLUSTERS;END IF;SET NUM_CLUSTERS = NUM_CLUSTERS + 1;END WHILE

它使用动态 SQL(立即执行)为每个尝试的 num_clusters 创建单独的模型名称。

Python 中超参数调优

或者,我们可以使用 Python 及其多线程功能来限制并发查询的数量:

def train_and_evaluate(num_clusters: Range, max_concurrent=3):# grid search means to try all possible values in rangeparams = []for k in num_clusters.values():params.append(Params(k))# run all the jobsprint('Grid search of {} possible parameters'.format(len(params)))pool = ThreadPool(max_concurrent)results = pool.map(lambda p: p.run(), params)# sort in ascending orderreturn sorted(results, key=lambda p: p._error)

其中 Params 类的 run()方法调用适当的训练和评估查询:

class Params:def __init__(self, num_clusters):self._num_clusters = num_clustersself._model_name = 'ch09eu.london_station_clusters_{}'.format(num_clusters)self._train_query = """CREATE OR REPLACE MODEL {}OPTIONS(model_type='kmeans', num_clusters={}, standardize_features = true) ASSELECT * except(station_name)from ch09eu.stationstats""".format(self._model_name, self._num_clusters)self._eval_query = """SELECT davies_bouldin_index AS errorFROM ML.EVALUATE(MODEL {});""".format(self._model_name)self._error = Nonedef run(self):bq = bigquery.Client(project=PROJECT)job = bq.query(self._train_query, location='EU')job.result() # wait for job to finishevaldf = bq.query(self._eval_query, location='EU').to_dataframe()self._error = evaldf['error'][0]return self

当在范围[3,9]中搜索时,我们发现误差最小的聚类数是 7。

使用人工智能平台的超参数调谐

在迄今为止考虑的两种超参数调优方法中,我们尝试了一个范围内参数的每个可能值。随着可能参数数量的增加,网格搜索变得越来越浪费。最好使用更有效的搜索算法,这就是云人工智能平台的超参数调整可以发挥作用的地方。超参数调优服务可以用于任何模型(不仅仅是 TensorFlow)。让我们应用于调整 DNN 模型的特征工程和节点数量。

首先,我们创建一个配置文件,指定每个参数的范围、并发查询的数量以及试验的总数:

trainingInput:scaleTier: CUSTOMmasterType: standard   # See: [https://cloud.google.com/ml-engine/docs/tensorflow/machine-types](https://cloud.google.com/ml-engine/docs/tensorflow/machine-types)hyperparameters:goal: MINIMIZE** maxTrials: 50**maxParallelTrials: 2hyperparameterMetricTag: mean_absolute_errorparams:- parameterName: afternoon_starttype: INTEGERminValue: 9maxValue: 12scaleType: UNIT_LINEAR_SCALE- parameterName: afternoon_endtype: INTEGERminValue: 15maxValue: 19scaleType: UNIT_LINEAR_SCALE- parameterName: num_nodes_0type: INTEGERminValue: 10maxValue: 100scaleType: UNIT_LOG_SCALE- parameterName: num_nodes_1type: INTEGERminValue: 3maxValue: 10scaleType: UNIT_LINEAR_SCALE

请注意,我们已经为每个参数和要最小化的度量(平均绝对误差)指定了最小值和最大值。我们要求优化只需要 50 次尝试,而网格搜索需要尝试 4x4x90x7 或超过 10,000 个选项!因此,使用 AI 平台超参数调整服务可以节省 200 倍的成本!

然后,我们创建一个 Python 程序,该程序调用 BigQuery 来训练和评估给定一组参数的模型:

def train_and_evaluate(args):        model_name = "ch09eu.bicycle_model_dnn_{}_{}_{}_{}".format(args.afternoon_start, args.afternoon_end, args.num_nodes_0, args.num_nodes_1)train_query = """CREATE OR REPLACE MODEL {}TRANSFORM(* EXCEPT(start_date), IF(EXTRACT(dayofweek FROM start_date) BETWEEN 2 and 6, 'weekday', 'weekend') as dayofweek, ML.BUCKETIZE(EXTRACT(HOUR FROM start_date), [5, {}, {}]) AS hourofday)OPTIONS(input_label_cols=['duration'], model_type='dnn_regressor',hidden_units=[{}, {}])ASSELECT duration, start_station_name, start_dateFROM `bigquery-public-data`.london_bicycles.cycle_hire""".format(model_name, args.afternoon_start, args.afternoon_end,args.num_nodes_0,args.num_nodes_1)logging.info(train_query)bq = bigquery.Client(project=args.project, location=args.location, credentials=get_credentials())job = bq.query(train_query)job.result() # wait for job to finisheval_query = """SELECT mean_absolute_error FROM ML.EVALUATE(MODEL {})""".format(model_name)logging.info(eval_info)evaldf = bq.query(eval_query).to_dataframe()return evaldf['mean_absolute_error'][0]

请注意,上面的代码为每个可调参数使用了一个特定的值,并返回平均绝对误差,这是被最小化的度量。

然后写出该错误值:

hpt.report_hyperparameter_tuning_metric(hyperparameter_metric_tag='mean_absolute_error',metric_value=error,global_step=1)

培训计划提交给 AI 平台培训服务:

gcloud ai-platform jobs submit training $JOBNAME \--runtime-version=1.13 \--python-version=3.5 \--region=$REGION \--module-name=trainer.train_and_eval \--package-path=$(pwd)/trainer \--job-dir=gs://$BUCKET/hparam/ \--config=hyperparam.yaml \-- \--project=$PROJECT --location=EU

在 AI 平台控制台中显示的结果输出包含最佳参数。

尽情享受吧!

如何用 gKnit 在 Ruby 中进行可重复的研究

原文:https://towardsdatascience.com/how-to-do-reproducible-research-in-ruby-with-gknit-c26d2684d64e?source=collection_archive---------23-----------------------

罗德里戈·博塔弗戈和丹尼尔·莫斯

[编辑:]从 gala az 0 . 4 . 10 版本开始,gKnit 将允许代码块之间的局部变量,感谢 Benoit 的评论和建议。

介绍

“有文化的编程”的概念是由 Donald Knuth 在 20 世纪 80 年代首次提出的(Knuth 1984)。这种方法的主要目的是开发在文档中散布宏代码片段、传统源代码和自然语言(如英语)的软件,该文档可以被编译成可执行代码,同时易于人类开发人员阅读。根据 Knuth 的说法,“有文化的编程实践者可以被认为是一个散文家,他主要关心的是阐述和优秀的风格。”

文字编程的想法演变成了可复制研究的想法,所有的数据、软件代码、文档、图形等等。需要复制的研究及其报告可以包含在单个文档或一组文档中,当分发给同行时,可以重新运行这些文档,生成相同的输出和报告。

R 社区在可重复的研究上投入了大量的努力。2002 年,Sweave 被引入,它允许混合 R 代码和 Latex 生成高质量的 PDF 文档。Sweave 文档可以包括代码、执行代码的结果、图形和文本,这样它就包含了再现研究的全部叙述。2012 年,RStudio 的 Yihui Xie 开发的 Knitr 发布,取代了 Sweave,并将 Sweave 所需的许多扩展和附加包整合到一个软件包中。

对于 Knitr, R markdown 也被开发出来,它是 markdown 格式的扩展。使用 R markdown 和 Knitr,可以生成多种格式的报告,如 HTML、markdown、Latex、PDF、dvi 等。 R markdown 还允许使用多种编程语言,如 R、Ruby、Python 等。在同一份文件中。

R markdown 中,文本与可以执行的代码块穿插在一起,代码及其结果都可以成为最终报告的一部分。虽然 R markdown 允许在同一个文档中使用多种编程语言,但是只有 R 和 Python(带有 reticulate 包)可以在块之间持久化变量。对于其他语言,比如 Ruby,每个块都将启动一个新的进程,因此所有数据都会在块之间丢失,除非它以某种方式存储在下一个块读取的数据文件中。

能够在块之间持久存储数据对于有文化的编程来说是至关重要的,否则叙事的流程会因为必须保存数据然后重新加载数据而丢失。虽然这看起来有点麻烦,但是不能在块之间持久化数据是一个大问题。例如,让我们看看下面这个简单的例子,在这个例子中我们想展示如何创建一个列表并使用它。让我们首先假设数据不能在块之间持久化。在下一个块中,我们创建一个列表,然后我们需要将它保存到文件中,但是为了保存它,我们需要以某种方式将数据整理成二进制格式:

lst = R.list(a: 1, b: 2, c: 3)
lst.saveRDS("lst.rds")

然后,在下一个使用变量' lst '的块中,我们需要读回它的值

lst = R.readRDS("lst.rds")
puts lst## $a
## [1] 1
## 
## $b
## [1] 2
## 
## $c
## [1] 3

现在,任何单个代码都有几十个变量,我们可能希望在块之间使用和重用这些变量。显然,这种方法很快变得难以控制。大概就是因为这个问题,在 Ruby 社区很少看到任何 R markdown 文档。

当变量可以跨块使用时,就不需要开销:

@lst = R.list(a: 1, b: 2, c: 3)
*# any other code can be added here*puts @lst## $a
## [1] 1
## 
## $b
## [1] 2
## 
## $c
## [1] 3

在 Python 社区中,在 2000 年的第一个十年左右,开始了将代码和文本集成到一个集成环境中的努力。2006 年,iPython 0.7.2 发布。2014 年,费尔南多·佩雷斯将 iPython 的 Jupyter 项目剥离出来,创建了一个基于网络的交互式计算环境。Jupyter 现在可以用于许多语言,包括带有 iruby gem 的 Ruby(【https://github.com/SciRuby/iruby】T2)。为了在 Jupyter 笔记本中拥有多种语言,SoS 内核被开发出来(【https://vatlab.github.io/sos-docs/】T4)。

编织文件

本文档描述了 gKnit。gKnit 基于 knitr 和 R markdown ,可以编织一个用 Ruby 和/或 R 编写的文档,并以 R markdown 的任何可用格式输出。gKnit 允许 ruby 开发人员在单个文档、文本和代码中进行有文化的编程和可重复的研究。

gKnit 运行在 GraalVM 和 gala az(Ruby 和 R 之间的集成库——见下文)之上。在 gKnit 中,Ruby 变量在块之间持久化,这使得它成为用这种语言进行文化编程的理想解决方案。此外,由于它是基于 Galaaz 的,Ruby 块可以访问 R 变量,用 Ruby 和 R 进行多语言编程是非常自然的。

Galaaz 已经在下面的帖子中描述过了:

  • https://towardsdatascience . com/ruby-plotting-with-gala az-a-example of-tight-coupling-ruby-and-r-in-graalvm-520 b 69 e 21021。
  • https://medium . freecodecamp . org/how-to-make-beautiful-ruby-plots-with-gala az-320848058857

这不是一篇关于 R markdown 的博文,感兴趣的用户可以通过下面的链接获得关于其功能和使用的详细信息。

  • 【https://rmarkdown.rstudio.com/】T4 或者
  • https://bookdown.org/yihui/rmarkdown/

在这篇文章中,我们将只描述 R markdown 的主要方面,这样用户就可以快速开始 gKnitting Ruby 和 R 文档。

Yaml 标头

一个 R markdown 文档应该以一个 Yaml 头开始,并保存在一个带有'的文件中。Rmd '扩展。这个文档有下面的标题,用来打包一个 HTML 文档。

---
title: "How to do reproducible research in Ruby with gKnit"
author: - "Rodrigo Botafogo"- "Daniel Mossé - University of Pittsburgh"
tags: [Tech, Data Science, Ruby, R, GraalVM]
date: "20/02/2019"
output:html_document:self_contained: truekeep_md: truepdf_document:includes:in_header: ["../../sty/galaaz.sty"]number_sections: yes
---

有关 Yaml 标题中选项的更多信息,请查看https://bookdown.org/yihui/rmarkdown/html-document.html。

r 降价格式

文档格式可以通过简单的标记来完成,例如:

头球

# Header 1## Header 2### Header 3

列表

Unordered lists:* Item 1
* Item 2+ Item 2a+ Item 2bOrdered Lists1\. Item 1
2\. Item 2
3\. Item 3+ Item 3a+ Item 3b

更多 R 减价格式,请转到https://rmarkdown.rstudio.com/authoring_basics.html。

r 组块

运行和执行 Ruby 和 R 代码实际上是我们真正感兴趣的是这个博客。

插入代码块的方法是将代码添加到由三个反勾号分隔的块中,后接左大括号(' { '),后接引擎名(r、ruby、rb、include、…)、任何可选的 chunk_label 和选项,如下所示:

```{engine_name [chunk_label], [chunk_options]}

例如,让我们向标记为‘first _ R _ chunk’的文档添加一个 R chunk。这是一个非常简单的代码,只需创建一个变量并将其打印出来,如下所示:
vec <- c(1, 2, 3)
print(vec)

如果该块被添加到一个 **R 降价**文件中,结果将是:

vec <- c(1, 2, 3)
print(vec)## [1] 1 2 3


现在假设我们想在代码中做一些分析,但是只打印结果而不是代码本身。为此,我们需要添加选项“echo = FALSE”。
vec2 <- c(10, 20, 30)
vec3 <- vec * vec2
print(vec3)     

下面是这个块在文档中的显示方式。注意没有显示代码,我们只能在一个白色的框中看到执行结果

[1] 10 40 90


可用组块选项的描述可在[https://yihui.name/knitr/](https://yihui.name/knitr/)中找到。让我们添加另一个带有函数定义的 R 块。在本例中,创建了一个向量“r_vec ”,并定义了一个新函数“reduce_sum”。区块规范是
r_vec <- c(1, 2, 3, 4, 5)reduce_sum <- function(...) {Reduce(sum, as.list(...))
}

这是它执行后的样子。从现在开始,为了简洁起见,我们将不再展示组块定义。

r_vec <- c(1, 2, 3, 4, 5)reduce_sum <- function(...) {
Reduce(sum, as.list(...))
}


我们可以,可能在另一个块中,访问向量并如下调用函数:

print(r_vec)## [1] 1 2 3 4 5print(reduce_sum(r_vec))## [1] 15


# 带 ggplot 的 r 图形在下面的块中,我们使用 ggplot 在 R 中创建了一个气泡图,并将其包含在本文档中。请注意,代码中没有包含图像的指令,这是自动发生的。“mpg”数据帧对于 R 和 Galaaz 来说也是固有可用。对于不了解 ggplot 的读者,ggplot 是一个基于“图形语法”(Wilkinson 2005)的图形库。图形语法的思想是通过给情节添加层来构建图形。更多信息可以在[https://towardsdatascience . com/a-comprehensive-guide-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1 f 92 B4 ed 4149](/a-comprehensive-guide-to-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1f92b4ed4149)中找到。在下图中,使用了来自基数 R 的“mpg”数据集。数据涉及城市循环油耗,单位为英里/加仑,根据 3 个多值离散属性和 5 个连续属性进行预测(昆兰,1993 年)首先,过滤“mpg”数据集,仅从以下制造商提取汽车:奥迪、福特、本田和现代,并存储在“mpg_select”变量中。然后,选定的数据帧被传递到 ggplot 函数,该函数在美学方法(aes)中指定“位移”(disp)应绘制在“x”轴上,而“城市里程”应绘制在“y”轴上。在“实验室”层中,我们为情节传递“标题”和“副标题”。在基本图“g”中,增加了 geom_jitter,它用相同的颜色(col=manufactures)绘制来自相同制造商的汽车,汽车点的大小等于其高速公路消耗(size = hwy)。最后,最后一层是绘图仪,包含每个制造商的线性回归线(method = "lm ")。

# load package and data
library(ggplot2)
data(mpg, package="ggplot2")mpg_select <- mpg[mpg$manufacturer %in% c("audi", "ford", "honda", "hyundai"), ]# Scatterplot
theme_set(theme_bw()) # pre-set the bw theme.
g <- ggplot(mpg_select, aes(displ, cty)) +
labs(subtitle="mpg: Displacement vs City Mileage",
title="Bubble chart")g + geom_jitter(aes(col=manufacturer, size=hwy)) +
geom_smooth(aes(col=manufacturer), method="lm", se=F)


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/cff8699641c56d1f40111ab55a917d46.png)# 红宝石块在文档中包含一个 ruby 块就像包含一个 R 块一样简单:只需将引擎的名称改为“Ruby”。也可以将块选项传递给 Ruby 引擎;但是,这个版本不接受 R chunks 可用的所有选项。未来的版本将增加这些选项。

在这个例子中,ruby 块被称为‘first _ ruby _ chunk’。组块标签的一个重要方面是它们不能被复制。如果一个块标签被复制,gKnit 将会出错停止。Ruby 块的另一个要点是,它们是在一个名为 RubyChunk 的类的范围内进行计算的。为了确保变量在块之间可用,应该将它们作为 RubyChunk 类的实例变量。在下面的块中,变量' @a '、' @b '和' @c '是标准的 Ruby 变量,而' @vec '和' @vec2 '是通过调用 R 模块上的' c '方法创建的两个向量。在 Galaaz 中,R 模块允许我们透明地访问 R 函数。R 中的“c”函数是一个将其参数连接起来构成向量的函数。需要明确的是,gknit 中并没有要求调用或使用任何 R 函数。gKnit 会编织标准的 Ruby 代码,甚至是没有任何代码的一般文本。

@a = [1, 2, 3]
@b = "US$ 250.000"
@c = "The 'outputs' function"@vec = R.c(1, 2, 3)
@vec2 = R.c(10, 20, 30)


在下一个块中,使用并打印了变量' @a ',' @vec '和' @vec2 '。

puts @a
puts @vec * @vec2## [1, 2, 3]

[1] 10 40 90


注意,@a 是一个标准的 Ruby 数组,@vec 和@vec2 是相应的向量,其中乘法按预期工作。# 从 Ruby 访问 RGraalVM 上的 Galaaz 的一个优点是,可以很容易地从 Ruby 访问 R 中定义的变量和函数。下一个块从 R 中读取数据,并使用前面定义的“reduce_sum”函数。要从 Ruby 访问 R 变量,应该对代表 R 变量的 Ruby 符号应用' ~ '函数。因为 R 变量被称为“r_vec ”,所以在 Ruby 中,访问它的符号是“:r_vec ”,因此“~:r_vec”检索变量的值。

puts ~:r_vec## [1] 1 2 3 4 5


为了调用 R 函数,‘R .’模块的用法如下

puts R.reduce_sum(~:r_vec)## [1] 15


# 红宝石绘图我们已经看到了一个用 r 绘图的例子。用 Ruby 绘图与用 r 绘图没有任何不同。在下面的例子中,我们使用 r 中的“mtcars”数据框架绘制了一个发散条形图。该数据摘自 1974 年的《美国汽车趋势》杂志,包括 32 辆汽车(1973-74 年款)的油耗和汽车设计与性能的 10 个方面。这十个方面是:*   mpg:英里/(美国)加仑
*   cyl:气缸数量
*   disp:排量(立方英寸)
*   马力:总马力
*   drat:后桥传动比
*   重量:重量(1000 磅)
*   qsec: 1/4 英里时间
*   vs:发动机(0 = V 形,1 =直线)
*   am:变速器(0 =自动,1 =手动)
*   档位:前进档的数量
*   碳水化合物:化油器数量

# copy the R variable :mtcars to the Ruby mtcars variable
@mtcars = ~:mtcars# create a new column 'car_name' to store the car names so that it can be
# used for plotting. The 'rownames' of the data frame cannot be used as
# data for plotting
@mtcars.car_name = R.rownames(:mtcars)# compute normalized mpg and add it to a new column called mpg_z
# Note that the mean value for mpg can be obtained by calling the 'mean'
# function on the vector 'mtcars.mpg'. The same with the standard
# deviation 'sd'. The vector is then rounded to two digits with 'round 2'
@mtcars.mpg_z = ((@mtcars.mpg - @mtcars.mpg.mean)/@mtcars.mpg.sd).round 2# create a new column 'mpg_type'. Function 'ifelse' is a vectorized function
# that looks at every element of the mpg_z vector and if the value is below
# 0, returns 'below', otherwise returns 'above'
@mtcars.mpg_type = (@mtcars.mpg_z < 0).ifelse("below", "above")# order the mtcar data set by the mpg_z vector from smaler to larger values
@mtcars = @mtcars[@mtcars.mpg_z.order, :all]# convert the car_name column to a factor to retain sorted order in plot
@mtcars.car_name = @mtcars.car_name.factor levels: @mtcars.car_name# let's look at the first records of the final data frame
puts @mtcars.head


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/13dce29e773ef2c51f2106cda2b74b0e.png)

require 'ggplot'

puts @mtcars.ggplot(E.aes(x: :car_name, y: :mpg_z, label: :mpg_z)) +
R.geom_bar(E.aes(fill: :mpg_type), stat: 'identity', width: 0.5) +
R.scale_fill_manual(name: 'Mileage',
labels: R.c('Above Average',
'Below Average'),
values: R.c('above': '#00ba38',
'below': '#f8766d')) +
R.labs(subtitle: "Normalised mileage from 'mtcars'",
title: "Diverging Bars") +
R.coord_flip


![](https://gitcode.net/OpenDocCN/towardsdatascience-blog-zh-2019/-/raw/master/docs/img/2f52b3c80dff200c98a43460f4043851.png)# 内嵌 Ruby 代码当使用 Ruby 块时,代码和输出被格式化成块,如上所示。这种格式并不总是需要的。有时,我们希望把 Ruby 评估的结果放在一个短语的中间。gKnit 允许用“rb”引擎添加内联 Ruby 代码。以下块规范将创建并内联拼音文本:

This is some text with inline Ruby accessing variable @b which has value:

and is followed by some other text!


这是一些带有内联 Ruby 访问变量@b 的文本,该变量的值为:US$ 250.000,后面是一些其他文本!请注意,如果我们希望所有内容都在一行中,请不要在代码块之前或之后添加任何新行,这一点很重要,这会导致以下带有内联 Ruby 代码的句子。# “输出”功能他之前在 Ruby 块中使用了标准的“puts”方法来产生输出。“puts”的结果,如前面所有使用它的块中所见,被格式化在代码块后面的一个白盒中。然而,很多时候,我们希望在 Ruby 块中进行一些处理,并让这个处理的结果生成并输出到文档中,就像我们在 **R markdown** 文档中输入它一样。例如,假设我们想在文档中创建一个新的标题,但是标题短语是一些代码处理的结果:也许它是我们将要阅读的文件的第一行。方法“outputs”添加其输出,就像在 **R markdown** 文档中键入一样。现在看看变量' @c '(它在上面的前一个块中被定义为' @ c = ' outputs '函数)。“‘outputs’函数”实际上是这个部分的名称,它是使用 Ruby 块中的‘outputs’函数创建的。生成这个标题的 ruby 块是:
outputs "### #{@c}"

三个“###”是我们在 **R markdown** 中添加标题 3 的方式。# Ruby 块的 HTML 输出我们刚刚看到了使用方法‘outputs’向 **R markdown** 文档添加文本。这种技术也可以用于向文档中添加 HTML 代码。在 **R markdown** 中,任何直接在文档中键入的 html 代码都会被正确呈现。例如,下面是一个 HTML 格式的表定义及其在文档中的输出:
FirstnameLastname Age
JillSmith 50
EveJackson 94
```

first name lastnameagejillsmith 50 eve Jackson 94

但是,手动创建 HTML 输出并不总是容易或可取的,特别是如果我们希望文档以其他格式呈现,例如 Latex。还有,上表看起来很丑。“kableExtra”库是一个创建漂亮表格的好库。看看https://cran . r-project . org/web/packages/kable extra/vignettes/awesome _ table _ in _ html . html

在下一个块中,我们以一个格式良好的表输出 R 中的“mtcars”数据帧。注意,我们通过使用“~:mtcars”来检索 mtcars 数据帧。

R.install_and_loads('kableExtra')
outputs (~:mtcars).kable.kable_styling

在块中包含 Ruby 文件

r 是一种为统计学家使用起来简单快捷的语言。据我所知,它不是一种用于开发大型系统的语言。当然,R 中有大型系统和库,但是这种语言的重点是开发统计模型并将其分发给其他人。

另一方面,Ruby 是用于大型软件开发的语言。用 Ruby 编写的系统会有几十个、几百个甚至几千个文件。要用有文化的编程来记录一个大系统,我们不能期望开发人员在一个文件中添加所有的文件。Rmd '文件。gKnit 提供了“include”块引擎来包含一个 Ruby 文件,就像在。Rmd '文件。

要包含一个文件,应该创建下面的块,其中是要包含的文件的名称,而扩展名是。Rb’,不需要添加。如果不包括“relative”选项,则它被视为 TRUE。当“relative”为真时,ruby 的“require_relative”语义用于加载文件,当“relative”为假时,搜索 Ruby 的$LOAD_PATH 以找到文件,并且它是“require”d。

```{include <filename>, relative = <TRUE/FALSE>}

下面我们包括文件“model.rb”,它在这个博客的同一个目录中。这段代码使用 R 'caret '包来分割一个训练集和测试集中的数据集。“caret”软件包是一个非常重要的用于进行数据分析的有用的软件包,它有数百个函数用于数据分析工作流程的所有步骤。仅仅使用“插入符号”来分割数据集就像使用众所周知的大炮来杀死苍蝇一样。我们在这里使用它只是为了说明,对于 Galaaz 来说,集成 Ruby 和 R,甚至使用一个非常复杂的包作为‘caret’都是微不足道的。给你一个建议:‘caret’包有很多依赖项,在 Linux 系统中安装它是一个耗时的操作。如果软件包尚未安装,方法“R.install_and_loads”将安装该软件包,这可能需要一段时间。
```require 'galaaz'# Loads the R 'caret' package.  If not present, installs it 
R.install_and_loads 'caret'class Modelattr_reader :dataattr_reader :testattr_reader :train #==========================================================##==========================================================def initialize(data, percent_train:, seed: 123) R.set__seed(seed)@data = data@percent_train = percent_train@seed = seedend #==========================================================##========================================================== def partition(field) train_index =R.createDataPartition(@data.send(field), p: @percet_train,list: false, times: 1)@train = @data[train_index, :all]@test = @data[-train_index, :all]endendmtcars = ~:mtcars
model = Model.new(mtcars, percent_train: 0.8)
model.partition(:mpg)
puts model.train.head
puts model.test.head

记录宝石

gKnit 还允许开发人员记录和加载不在同一目录下的文件。Rmd '文件。

下面是一个从 TruffleRuby 加载“find.rb”文件的例子。在这个例子中,relative 被设置为 FALSE,所以 Ruby 将在它的$LOAD_PATH 中查找文件,用户不需要查找它的目录。

```{include find, relative = FALSE}
```# frozen_string_literal: true
#
# find.rb: the Find module for processing all files under a given directory.
##
# The +Find+ module supports the top-down traversal of a set of file paths.
#
# For example, to total the size of all files under your home directory,
# ignoring anything in a "dot" directory (e.g. $HOME/.ssh):
#
#   require 'find'
#
#   total_size = 0
#
#   Find.find(ENV["HOME"]) do |path|
#     if FileTest.directory?(path)
#       if File.basename(path)[0] == ?.
#         Find.prune       # Don't look any further into this directory.
#       else
#         next
#       end
#     else
#       total_size += FileTest.size(path)
#     end
#   end
#
module Find ## Calls the associated block with the name of every file and directory listed# as arguments, then recursively on their subdirectories, and so on.## Returns an enumerator if no block is given.## See the +Find+ module documentation for an example.#def find(*paths, ignore_error: true) # :yield: pathblock_given? or return enum_for(__method__, *paths, ignore_error: ignore_error) fs_encoding = Encoding.find("filesystem") paths.collect!{|d| raise Errno::ENOENT, d unless File.exist?(d); d.dup}.each do |path|path = path.to_path if path.respond_to? :to_pathenc = path.encoding == Encoding::US_ASCII ? fs_encoding : path.encodingps = [path]while file = ps.shiftcatch(:prune) doyield file.dup.taintbegins = File.lstat(file)rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONGraise unless ignore_errornextendif s.directory? thenbeginfs = Dir.children(file, encoding: enc)rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONGraise unless ignore_errornextendfs.sort!fs.reverse_each {|f|f = File.join(file, f)ps.unshift f.untaint}endendendendnilend ## Skips the current file or directory, restarting the loop with the next# entry. If the current file is a directory, that directory will not be# recursively entered. Meaningful only within the block associated with# Find::find.## See the +Find+ module documentation for an example.#def prunethrow :pruneend module_function :find, :prune
end

转换为 PDF

knitr 的一个优点是相同的输入可以转换成许多不同的输出。一种非常有用的格式,当然是 PDF。为了将一个 R markdown 文件转换成 PDF,需要在系统上安装 LaTeX。我们不会在这里解释如何安装 LaTeX,因为网上有大量的文档显示如何进行。

gKnit 附带了一个简单的 LaTeX 样式文件,用于将这个博客作为 PDF 文档进行 gKnit。下面是生成 PDF 格式而不是 HTML 格式的博客的 Yaml 头:

---
title: "gKnit - Ruby and R Knitting with Galaaz in GraalVM"
author: "Rodrigo Botafogo"
tags: [Galaaz, Ruby, R, TruffleRuby, FastR, GraalVM, knitr, gknit]
date: "29 October 2018"
output:pdf\_document:includes:in\_header: ["../../sty/galaaz.sty"]number\_sections: yes
---

PDF 文档可在以下网址查看:https://www . research gate . net/publication/332766270 _ How _ to _ do _ reproducible _ research _ in _ Ruby _ with _ gKnit

结论

为了进行可重复的研究,需要的主要基本工具之一是一个允许“文化编程”的系统,在该系统中,文本、代码和可能的一组文件可以被编译成一份报告,该报告可以容易地分发给同行。对等体应该能够通过获得完全相同的原始报告,使用相同的文件集来重新运行编译。gKnit 就是这样一个针对 Ruby 和 R 的系统,它使用 R Markdown 来集成文本和代码块,其中代码块可以是 R Markdwon 文件的一部分,也可以从系统中的文件导入。理想情况下,在可重复的研究中,重建报告所需的所有文件应该很容易地打包在一起(在同一个压缩目录中),并分发给同行以便重复执行。

Oracle GraalVM 的承诺之一是,用户/开发人员将能够使用最好的工具来完成手头的任务,而不依赖于编写该工具的编程语言。我们在 GraalVM 和 Truffle interop 消息的基础上开发和实现了 Galaaz,而用 R-gala az 包装 Ruby 或者用 gKnit 包装 Knitr 所花费的时间和精力只是实现原始工具所需时间的一小部分(一个人每天花费几个小时,大约需要六个月)。试图在 Ruby 中重新实现所有的 R 包需要付出与 Python 实现 NumPy、Pandas 和所有支持库同样的努力,这种努力不太可能实现。GraalVM 允许 Ruby“几乎免费”地从这些庞大的库和工具中获利,这些库和工具使 R 成为数据分析和机器学习中最常用的语言之一。

比用 Ruby 包装 R 库更有趣的是,Ruby 为 R 增加了价值,它允许开发人员使用强大的现代结构进行代码重用,而这并不是 R 的强项。正如在这篇博客中所示,R 和 Ruby 可以很容易地进行通信,R 可以以一种极大地扩展其功能和可读性的方式构造在类和模块中。

安装 gKnit

先决条件

  • GraalVM (>= rc15)
  • 松露红宝石
  • FastR

以下 R 包将在必要时自动安装,但如果需要,也可以在使用 gKnit 之前安装:

  • ggplot2
  • gridExtra
  • 针织工

R 包的安装需要一个开发环境,并且很耗时。在 Linux 中,gnu 编译器和工具应该足够了。我不确定苹果电脑需要什么。

准备

  • gem 安装 galaaz

使用

  • gknit

参考

唐纳德·克努特,1984 年。“识字编程。” Comput。第 27 卷第 2 期。英国牛津:牛津大学出版社:97–111。https://doi.org/10.1093/comjnl/27.2.97

威尔金森利兰。2005.图形的语法(统计与计算)。柏林,海德堡:施普林格出版社。

如何更好的做岭回归

原文:https://towardsdatascience.com/how-to-do-ridge-regression-better-34ecb6ee3b12?source=collection_archive---------25-----------------------

优化和机器学习

使用优化器来寻找性能最佳的正则化矩阵

Photo by Massimiliano Morosinotto on Unsplash

Xy 表示训练数据的样本,其中 X 是具有 n 行特征向量的矩阵,而 y 是 n 个对应目标值的向量。如果𝐱′是具有未知目标值 y’的样本外特征向量,那么我们可以拟合线性模型 ,目标是最小化预期样本外误差

一种拟合模型的方法,最小二乘法,选择 来最小化训练数据的误差平方和

虽然在给定足够的训练数据的情况下,这可能是一个很好的选择,但如果训练数据较少、噪声较多或预测器较弱的特征较多,它可能会过度拟合数据,从而使 更多地反映噪声,而不是潜在的统计关系。

岭回归修正了最小二乘法以最小化

利用合适的矩阵γ,岭回归可以收缩或者限制 的系数,以减少过拟合并提高样本外预测的性能。挑战在于正确选择γ

通常,γ仅限于形式

并且通过在训练数据的交叉验证上试验不同的值并挑选具有最佳分数的值来选择α。我会参考这个,或者其他类似这样的选择γ、的方法作为微调。调整的缺点是会导致额外的计算,并且除了最简单的γ的参数化之外,不能扩展到任何参数化。例如,如果我们希望每个变量都有一个单独的正则项

我们有很多变量,通过调整来设置γ是不可能的。

在这篇博文中,我将展示如何将某些交叉验证的性能最大化γ设置为适当的优化问题,其中我们计算一阶、二阶导数,并在优化器的帮助下有效地迭代到最佳性能参数。这将允许我们扩展到具有许多变量的参数化,并且经常会导致比调整方法更好的结果。

留一交叉验证

表示移除第 I 个条目的特征矩阵和目标向量

表示适合这些数据的回归量。我们将留一交叉验证 (LOOCV)定义为

并且使用有效的优化器来寻求相对于γ最小化该值。优化器通过对函数的导数进行局部逼近来工作。他们使用近似来采取连续的步骤来改进目标,直到达到局部最优。但是在我们计算 LOOCV 的导数以提供给优化器之前,我们需要为目标导出一个更易处理的形式。

观察

那么对于任何一个 z

使用

因此,我们可以将岭回归方程改写为

因为 zy 不依赖于 b ,并且 A 是正定,因此当

因此,

像这样为每个条目求解岭回归仍然是昂贵的,但幸运的是,我们可以进一步操纵方程来实现更有效的东西。注意到

根据谢尔曼-莫里森公式,我们有

因此,

然后自从

我们可以将第 I 个留一岭回归解改写为

将此代入 LOOCV 的第 I 项,我们得到

LOOCV 变成了

计算 LOOCV 梯度

我们可以用上一节的公式来推导导数的方程。设 α 表示γ的参数向量,定义 L( α )为给定参数的 LOOCV,其中 L _i 表示 LOOCV 求和的第 I 项。我假设γ由对角矩阵参数化

尽管这些方程可以容易地适用于其他参数化和单变量参数化

可以简单地计算为多变量偏导数的和。

那么第 I 个 LOOCV 项的导数就是

对于 ŷ 的偏导数,我们有

注意:在这里,我们已经利用这个公式来微分一个逆矩阵

同样,我们可以计算出 h 的偏导数

结合各项并求和,则全微分为

有了导数和值的有效公式,我们可以从任何初始猜测开始,使用优化程序,快速下降到最小化 LOOCV 的参数。

注意:为优化者提供 LOOCV 二阶导数的 hessian 矩阵也是有益的。这些方程更复杂,这篇博文只导出了一阶导数,但是它们可以用类似于梯度的方式计算。

模拟结果

让我们比较一下使用单个正则项的岭回归和对每个回归变量使用单独正则项的岭回归的性能。

我将使用模拟

对于模拟的每次试验,模型将适合于生成的具有独立同分布随机变量的 n×3 特征矩阵的训练数据,其中

目标值将由以下各项生成

随着

试验的结果就是预测误差

在样本外数据点𝐱′上,从与训练数据相同的分布中生成y′。误差是多次试运行的平均值,训练大小 n 是 varied⁴.比较的三个模型是

  • LS :最小二乘回归
  • RR-1 :单正则化的岭回归,由二阶优化器拟合,以最小化训练数据上的 LOOCV 误差。
  • RR-p :针对每个特征变量使用单独正则化器的岭回归,由二阶优化器拟合,以最小化训练数据上的 LOOCV 误差。

下图显示了每个 n 值的模型平均预测误差,以及代表平均值 95%置信区间的误差条(使用 t 统计)。

虽然结果对模拟参数敏感,但这表明,至少对于某些问题,单独的正则化子可以提供比单个正则化子更好的性能。

结论

我们展示了如何有效地计算岭回归的 LOOCV,并推导出其导数的方程。这允许我们使用优化器来找到最小化 LOOCV 误差的正则化参数。优化器消除了挑选和试验不同参数的工作;但最重要的是,它打开了使用正则化矩阵的更复杂的多变量参数化的大门。我们展示了一个这样的多变量参数化(对每个特征变量使用单独的正则化)如何在测试问题上产生更好的性能。

在下一期 文章 中,我将解释为什么留一法通常不是交叉验证的正确形式,并介绍我们应该使用的广义交叉验证。我还将在一个现实世界的问题上比较不同岭回归方法的性能。

如果您对自动调整正则化参数或使用多个正则化子感兴趣,请查看building block . ai**

脚注

[1]: sklearn.linear_model。RidgeCV (同样 sklearn.model_selection。例如,GridSearchCV )通过强力计算预先选择的参数列表的交叉验证,以找到得分最高的参数。

[2]:另请参见https://github . com/rn burn/ridge-regression-doc/blob/master/notebooks/loo cv-verify . ipynb以验证 loocv 方程

[3]:像这样推导导数方程很容易出错,但幸运的是,使用有限差分进行测试也很容易。参见https://github . com/rn burn/ridge-regression-doc/blob/master/notebooks/loo cv-gradient-verify . ipynb

[4]:完整模拟可作为笔记本:https://github . com/rn burn/ridge-regression-doc/blob/master/notebooks/loo cv-simulation . ipynb

用十行代码实现 BERT 和 Tensorflow 文本分类

原文:https://towardsdatascience.com/how-to-do-text-binary-classification-with-bert-f1348a25d905?source=collection_archive---------4-----------------------

免费试用 Google Colab 上最先进的语言建模技术!

需求

我们都知道 BERT 是一个引人注目的语言模型,已经被应用于各种下游任务,如情感分析问答 (QA)。在某些方面,它超越了人类!

有没有在文本二元分类上尝试过?

老实说,直到最近,我的答案仍然是

为什么不呢?

因为 BERT 官方 GitHub repo 上的示例代码不太用户友好

首先,我想要一个 IPython 笔记本,而不是 Python 脚本文件,因为我想在运行代码块时获得即时反馈。当然,谷歌 Colab 笔记本会更好,因为我可以通过免费的 GPU/TPU 立即使用代码。

其次,除了我在乎的人,我不想知道细节。我想控制有用的参数,比如时期数和批量大小。但是,我需要知道所有的“处理器”、“标志”和日志功能吗?

在我尝试了所有其他友好的框架之后,我是一个被宠坏的机器学习用户。

例如,在 Scikit-learn 中,如果你试图构建一个树分类器,这里(几乎)是你所有的代码。

from sklearn.datasets import load_iris
from sklearn import tree
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)

如果想在 fast.ai 中做图像分类,需要输入这几行。

!git clone https://github.com/wshuyi/demo-image-classification-fastai.git
from fastai.vision import *
path = Path("demo-image-classification-fastai/imgs/")
data = ImageDataBunch.from_folder(path, test='test', size=224)
learn = cnn_learner(data, models.resnet18, metrics=accuracy)
learn.fit_one_cycle(1)
interp = ClassificationInterpretation.from_learner(learn)
interp.plot_top_losses(9, figsize=(8, 8))

你不仅可以得到分类结果,还可以得到激活图。

为什么 Google 开发者不能给我们一个类似的界面来使用 BERT 进行文本分类呢?

周一发现这个 Colab 笔记本。这是预测影评情绪的一个例子。

我非常兴奋,因为我知道伯特现在已经加入了 Tensorflow 中心。

但是打开之后发现,对于一个只关心文本分类应用的用户来说,细节还是太多了。

所以我试着重构代码,我做到了。

然而,原来,笔记本里还有很多代码。

所以我让我的读者帮我打包。很快,华中科技大学计算机科学专业研究生孙岩就这么做了,并把它做成一个 PYPI 包,命名为[bert-text](https://github.com/SunYanCN/bert-text)

笔记本

请点击这个链接,你会在 github 上看到 IPynb 笔记本文件。

点按“在 Colab 中打开”按钮。Google Colab 会自动打开。

您需要点击“复制到驱动器”按钮,将副本保存到您自己的 Google Drive。

之后你只需要做四件事。

  1. 安装必要的软件包。
  2. 准备熊猫数据框格式的数据。我估计对大多数深度学习用户来说很容易。
  3. 如有必要,调整四个参数。
  4. 运行笔记本并显示您的结果。

让我们安装bert-text包并加载 API。

!pip install bert-text
from bert_text import run_on_dfs

我的例子是 IMDB 评论的样本数据集。它在训练集中包含 1000 个正样本和 1000 个负样本,而测试集包含 500 个正样本和 500 个负样本。

import pickle!wget https://github.com/wshuyi/info-5731-public/raw/master/imdb-sample.picklewith open("imdb-sample.pickle", 'rb') as f:train, test = pickle.load(f)

我在 UNT 大学的 INFO 5731 课堂上使用它,让学生比较 textblob 包、单词包模型、带有单词嵌入的简单 LSTM 和 ULMfit 的结果。

现在我终于可以把伯特加入名单了。

您需要运行下面一行来确保训练数据被正确地打乱。

train = train.sample(len(train))

您的数据集应存储在 Pandas 数据框中。应该有一个称为train的训练集和一个称为test的测试集。

它们都应该至少包含两列。一列用于文本,另一列用于二进制标签。强烈建议选择 0 和 1 作为标签值。

现在数据已经准备好了,可以设置参数了。

myparam = {"DATA_COLUMN": "text","LABEL_COLUMN": "sentiment","LEARNING_RATE": 2e-5,"NUM_TRAIN_EPOCHS":10}

前两个参数只是数据框的列名。您可以相应地更改它们。

第三个参数是学习率。你需要阅读原始论文,以找出如何明智地选择它。或者,您可以使用此默认设置。

最后一个参数是设置希望 BERT 运行多少个时期。我在这里选择 10,因为训练数据集非常小,我不想让它过拟合。

默认情况下,预先训练的语言模型是“bert_uncased_L-12_H-768_A-12”。它已经在英文维基百科和图书语料库上接受了训练。除此之外,现在还有五个选项可供你选择。

  • bert_multi_cased_L-12_H-768_A-12
  • bert_uncased_L-24_H-1024_A-16
  • bert_cased_L-12_H-768_A-12
  • bert_chinese_L-12_H-768_A-12
  • bert_cased_L-24_H-1024_A-16

如果您想换成另一个预先训练好的模型,比如处理法语或德语的多语言模型,请按如下方式更改myparam设置:

myparam = {"DATA_COLUMN": "comment","LABEL_COLUMN": "sentiment","LEARNING_RATE": 2e-5,"NUM_TRAIN_EPOCHS":3,"bert_model_hub":"https://tfhub.dev/google/bert_multi_cased_L-12_H-768_A-12/1"}

汉语是一个特例。您可能需要这样设置myparam:

myparam = {"DATA_COLUMN": "comment","LABEL_COLUMN": "sentiment","LEARNING_RATE": 2e-5,"NUM_TRAIN_EPOCHS":3,"bert_model_hub":"https://tfhub.dev/google/bert_chinese_L-12_H-768_A-12/1"}

如果您想看到整个输出(可选),您应该添加下面两行代码。

import tensorflow as tf
tf.logging.set_verbosity(tf.logging.INFO)

好吧。现在你可以跑伯特了!

result, estimator = run_on_dfs(train, test, **myparam)

警告!这一行花了你一些时间来运行。

完成后,您可以运行最后一行来获得您的分类模型的评估结果(在 BERT 上)。

result

对于这么小的训练集来说,我觉得结果还是挺不错的。

仅此而已。

现在你也可以使用最先进的语言建模技术来训练你的文本二进制分类器!

相关博客

如果你对这篇博客文章感兴趣,你可能也想看看下面几篇:

  • 如何用 Google Colab 练习 Python?
  • 如何用 Python 和递归神经网络预测严重的交通堵塞?
  • 使用 Python 和 fast.ai 进行深度学习,第 1 部分:使用预训练模型进行图像分类
  • 使用 Python 和 fast.ai 的深度学习,第 2 部分:使用迁移学习的 NLP 分类

如何制作动画“比赛”条形图

原文:https://towardsdatascience.com/how-to-do-that-animated-race-bar-chart-57f3a8ff27a8?source=collection_archive---------3-----------------------

探索英国足球有史以来最好的球队,并学习如何制作其中一个已经变得流行的比赛条形图

在本文中,我们将分析英国足球队自 1888 年联赛开始以来的历史表现,并使用该数据创建一个动画条形图,每年循环显示历史上前十名球队的总积分。我们还将使用标题栏来讲述这项运动在英格兰 130 年间的变化。这是成品,所有代码都在 Github 上:

The abbreviated history of English football

开始之前,让我们明确我们的目标。这是我们想要做的:

  1. 生成一个动画,循环播放从 1888 年到 2017 年的每个足球赛季,并显示截至该年每支球队的累计总积分,显示排名前 10 的球队。我们将只考虑在英格兰足球顶级联赛(现在被称为英超)中获得的积分。
  2. 偶尔在图表标题中加入仿真陈述,有助于讲述足球随时间的变化。

在这篇文章中,我不打算把重点放在样式和美观上,只讨论创建动画图形的基本功能。

准备数据

理想情况下,我们需要的是一个数据集,它能告诉我们通过历史获得的联赛积分,但我找不到那个数据集。相反,我发现了更详细、更棒的东西,这是自 1888 年以来每一场比赛的记录,以及结果和分数。我在这里发现它是以 R dataframe 对象的形式存在的——所以我们将在 R 中这样做。这是数据的快速快照。

这个数据集相当大,自 1888 年以来,每一级都有近 200,000 场比赛。首先,我们需要将每场比赛转换为给定球队的积分分配。主队和客队之间的积分分配如下:

  • 1981 赛季前冠军得 2 分。从 1981 年赛季开始,为了鼓励更多的进攻,比赛规则发生了变化,获胜者可以获得 3 分。
  • 败队得 0 分。
  • 如果比赛以平局结束,每人得 1 分。

因此,让我们加载我们的数据,并加载我们的tidyverse包进行标准的数据操作。我们将使用result列分配主场和客场积分,通过使用dplyr::mutate()创建两个新列,如下所示:

library(tidyverse)load("data/england.rda")# assign points to results (2 pts for a win up to 1980-81 season then 3 pts for a win afterwards)england <- england %>% dplyr::mutate(homepts = dplyr::case_when(Season <= 1980 & result == "H" ~ 2,Season > 1980 & result == "H" ~ 3,result == "D" ~ 1,result == "A" ~ 0),awaypts = dplyr::case_when(Season <= 1980 & result == "A" ~ 2,Season > 1980 & result == "A" ~ 3,result == "D" ~ 1,result == "H" ~ 0))

现在我们已经为每场比赛分配了积分,我们需要得到每支球队和每个赛季的主场和客场总积分,记住我们只对顶级比赛感兴趣:

# restrict to Tier 1 and assemble into total points per seasonhome_pts <- england %>%dplyr::filter(tier == 1) %>% dplyr::group_by(Season, home) %>% dplyr::summarize(pts = sum(homepts))away_pts <- england %>%dplyr::filter(tier == 1) %>% dplyr::group_by(Season, visitor) %>% dplyr::summarize(pts = sum(awaypts))

现在,我们可以将这两个数据框架绑定在一起,将主客场积分相加,得出每个赛季每个球队的总积分:

total_pts <- home_pts %>% dplyr::rename(Team = home) %>% dplyr::bind_rows(away_pts %>% dplyr::rename(Team = visitor)) %>% dplyr::group_by(Season, Team) %>% dplyr::summarise(pts = sum(pts))

现在我们有了一个数据框架,显示了每支球队在每个赛季获得的积分。我们想操纵这一点,以便每个赛季显示我们所有积分的总和,包括该赛季。我们可以通过一个快速的for循环来实现这一点:

# create rolling sumstable <- total_pts %>% dplyr::filter(Season == 1888) %>% dplyr::select(Season, Team, Points = pts)for (i in 1889:2017) {table <- total_pts %>% dplyr::filter(Season <= i) %>% dplyr::group_by(Team) %>% dplyr::summarise(Points = sum(pts, na.rm = TRUE)) %>% dplyr::mutate(Season = i) %>% dplyr::bind_rows(table)
}

我们已经做了足够的工作来获得目标 1 所需的数据。对于目标 2,我将编辑Season栏,加入一些关于英格兰足球联赛的重要史实。我会让每个事实显示大约三季,让它在动画中出现足够长的时间,让观众阅读。让我们称这个新编辑的专栏为SeasonLabel

# add some historic facts to seasonstable <- table %>% dplyr::mutate(SeasonLabel = dplyr::case_when(Season <= 1891 ~ paste(Season, "Football League is formed with 12 teams in 1888", sep = " - "),dplyr::between(Season, 1892, 1895) ~ paste(Season, "Second Division introduced in 1892", sep = " - "),dplyr::between(Season, 1914, 1918) ~ paste(Season, "League suspended during World War I", sep = " - "),dplyr::between(Season, 1920, 1924) ~ paste(Season, "Third Division North/South introduced in 1920/21", sep = " - "),dplyr::between(Season, 1925, 1928) ~ paste(Season, "New Offside Law introduced in 1925", sep = " - "),dplyr::between(Season, 1939, 1945) ~ paste(Season, "League suspended during World War II", sep = " - "),dplyr::between(Season, 1958, 1961) ~ paste(Season, "Regional Third Divisions amalgamated in 1958 to form Nationwide Third and Fourth Divisions", sep = " - "),dplyr::between(Season, 1965, 1968) ~ paste(Season, "Substitutes first allowed in 1965", sep = " - "),dplyr::between(Season, 1974, 1977) ~ paste(Season, "First match played on a Sunday in 1974", sep = " - "),dplyr::between(Season, 1981, 1984) ~ paste(Season, "Three points for a win introduced in 1981", sep = " - "),dplyr::between(Season, 1986, 1989) ~ paste(Season, "Play-offs introduced to decide some promotions", sep = " - "),dplyr::between(Season, 1992, 1995) ~ paste(Season, "Premier League formed in 1992, reducing Football League to three divisions", sep = " - "),dplyr::between(Season, 2004, 2007) ~ paste(Season, "Football League renames divisions in 2004 to Championship, League One and League Two", sep = " - "),dplyr::between(Season, 2013, 2016) ~ paste(Season, "Goal Line Technology introduced in Premier League in 2013", sep = " - "),1L == 1L ~ as.character(Season)))

现在让我们来看看我们的数据:

现在我们有了编码动画所需的一切。让我们使用save(table, 'data/table.RData')保存我们的数据集,这样我们就可以在一个新文件中打开它,我们将使用它来创建动画。

创建动画

在这个 StackOverflow 讨论的帮助下,我们将使用ggplot2包为这些数据设计一个静态条形图,然后我们将使用 awesome 包gganimate生成一个滚动动画,该动画通过每个SeasonLabel进行过渡并更新条形图。

让我们加载数据和一些我们需要的包。然后,首先,我们需要对每个赛季的每个球队进行排名,因为排名将决定柱线在“比赛”图中出现的顺序。我们还为每个团队创建了一个相对于排名靠前的团队的相对值,因为这将有助于衡量标准。最后,我们创建一个标签来从Points列中提取值。然后我们限制排名前 10 的队伍。

library(tidyverse)
library(ggplot2)
library(gganimate)
library(gifski)
ggplot2::theme_set(theme_classic())load("data/table.Rdata")# generate top n ranking by year groupanim_table <- table %>%dplyr::group_by(Season) %>%dplyr::mutate(rank = min_rank(-Points) * 1,Value_rel = Points / Points[rank == 1],Value_lbl = paste0(" ", Points)) %>%dplyr::filter(rank <= 10) %>%dplyr::ungroup()

现在我们已经拥有了绘制静态条形图所需的一切——这只需要一串相当基本的ggplot2命令。我不会详细讨论这些,但是如果你需要重新熟悉这些,我推荐你从 tidyverse.org 开始。这里的要点是,我们使用rank作为 x 美学,Points作为 y 美学,然后我们分配TeamPoints,然后我们翻转图表,使其水平而不是垂直。

# create static bar chartp <- ggplot2::ggplot(anim_table, aes(rank)) +ggplot2::geom_tile(aes(y = Points / 2,height = Points,width = 0.9,fill = "blue"), alpha = 0.8, color = NA) +ggplot2::geom_text(aes(y = 0, label = paste(Team, " ")), size = 12, vjust = 0.2, hjust = 1) +ggplot2::geom_text(aes(y = Points, label = Value_lbl, hjust = 0)) +ggplot2::coord_flip(clip = "off", expand = FALSE) +ggplot2::scale_y_continuous(labels = scales::comma) +ggplot2::scale_x_reverse() +ggplot2::guides(color = FALSE, fill = FALSE)

现在是动画的主要部分。我们给静态图的标题和轴加了标签,但其中一个标签是我们将用来给图加动画的标签——即SeasonLabel.这被称为过渡变量。所以我们告诉ggplot2我们希望标题打印当前的过渡状态——即SeasonLabel在动画中旋转时作为标题。最后,我们使用ease_aes()来定义值在转换过程中的变化方式——这里有许多您可以尝试的缓和函数,详情请参考帮助文件。

# set SeasonLabel as transition state and set to animatep <- ggplot2::labs(p,title = "{closest_state}", x = "", y = "Total Points",caption = "Source:  Github(jalapic/engsoccerdata) | Top tier points only, does not include mandatory points deductions | Plot generated by [@dr_keithmcnulty](http://twitter.com/dr_keithmcnulty)") +ggplot2::theme(plot.title = element_text(color = "darkblue", face = "bold", hjust = 0, size = 30),axis.ticks.y = element_blank(),axis.text.y = element_blank(),plot.margin = margin(2, 2, 1, 16, "cm")) +gganimate::transition_states(SeasonLabel, transition_length = 4, state_length = 1) +gganimate::ease_aes("cubic-in-out")

所以我们的动画情节现在作为对象p保存在环境中。我们现在需要做的就是把它作为一个输出文件。有许多设备可用于以各种格式呈现输出,但最常用的有:

  • gif输出——产生一个动画图像文件。这需要安装gifski包。
  • mp4视频输出——这需要在您的机器上安装ffmpeg

在我的例子中,我将按照之前显示的图像创建一个gif。您可以通过使用duration参数来调整 gif 的速度,也可以定制图像的大小和分辨率。

# save as preferred rendered formatgganimate::animate(p, nframes = 200, fps = 5, duration = 100, width = 2000, height = 1200, renderer = gifski_renderer("anim.gif"))

根据您在animate()函数中设置参数的方式,文件可能需要更长时间来渲染,但是您可以在控制台中查看进度。

继续教育

这是一个简短的实际案例研究。它只涵盖了 r 中很小一部分动画的可能性。我鼓励你多读一些关于gganimate的内容,然后尝试用它来制作一些你自己的数据动画。时间序列数据尤其适合制作好的动画。R 中的plotly包也增加了动画功能,值得一看。

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedInTwitter上找我。

如何主宰 MLS 幻想

原文:https://towardsdatascience.com/how-to-dominate-mls-fantasy-e60de8cae01d?source=collection_archive---------27-----------------------

编写 python 脚本来自动选择最佳 MLS 幻想阵容

Can algorithms really help when selecting a MLS Fantasy lineup?

你好,老朋友

所有非美国读者请注意,请原谅我把这项运动称为“英式足球”而不是“橄榄球”。尽情享受吧!

我在堪萨斯城长大,对和家人一起参加堪萨斯奇才队(现在是堪萨斯城体育队)的比赛有很多美好的回忆。作为一名足球运动员(请注意,不是很好),我喜欢看我最喜欢的运动员在球场上一决雌雄,无休止地寻找球网的背面。为了在比赛间隙消磨时间,我经常阅读花名册的宣传信息,尽可能地了解我偶像的一切。

随着年龄的增长,我的注意力转移到了海外联赛,但随着美国职业大联盟在过去几年的复苏,我现在渴望回到我小时候喜欢的联赛。

在我退出美国职业棒球大联盟十多年的时间里,体育产业发生了巨大的变化,最大的不同是梦幻体育的引入和主导地位。这些年来,梦幻体育产业的受欢迎程度绝对呈爆炸式增长,并帮助许多粉丝了解了一项新的运动或联盟,鼓励他们在没有理由或欲望的情况下关注比赛。由于梦幻体育的包容性,我决定求助于 MLS Fantasy 来帮助我重新了解球队和明星。作为一个数据呆子,我不会让纯粹的猜测支配我的幻想阵容,而是创建一个算法,为我确定一个最佳阵容。

At the mercy of the laws of the game. Photo by Noelle Otto from Pexels

制定家规

在我们深入研究我使用的算法和我取得的结果之前,我们需要定义 MLS Fantasy 的规则和约束。任何有经验的人都可以跳到下一部分,因为这只是一个回顾。

MLS Fantasy 的基本前提是在每个比赛周创建一个能返还最多积分的阵容。这些分数可以通过在球场上采取积极的行动来获得,例如进球,助攻,扑救,传球等等。对球队产生负面影响的行为也会被扣分,例如乌龙球、防守失误或收到裁判的黄牌或红牌。这些分数是根据他们对比赛的影响来衡量的,所以进球得分比成功传球得分高得多。

所有球队由 2 名守门员、5 名后卫、5 名中场和 3 名前锋组成。首发阵容必须包括 11 名球员,其中 1 名是守门员。MLS Fantasy 支持很多不同的阵型,比如 3–5–2(3 个后卫,5 个中场,2 个前锋),3–4–3,4–5–1,4–4–2,4–3–3,5–4–1,5–3–2。所有不在首发阵容中的球员都将被指定为替补(稍后会有更多)。

有趣的是,每支 MLS 梦幻球队都有 1 亿美元的比赛周预算来选择球队。每个球员都有一个基于他在联盟中相对表现的价格。例如,在撰写本文时,LAFC 的卡洛斯·贝拉是联盟中最贵的球员,身价 1180 万美元。一般来说,大多数球员的身价在 400 万美元到 1200 万美元之间。要使一个球队有效,名单上所有球员的总成本必须小于或等于 1 亿美元。低于 1 亿美元没有任何惩罚或奖励,所以建议获得一个尽可能接近最大预算的阵容,以优化团队的实力。

除了成本和位置限制之外,球队的最后一个主要限制是每支球队可以选择的球员数量。MLS Fantasy 限制同队球员的数量为 3 名,所以你不能从华盛顿联队选择超过 3 名球员。

替补队员给局面带来了一点麻烦。默认情况下,替补队员不会为你的周总成绩加分,不管他们在比赛中的个人表现如何。然而,如果你的首发球员在一周内一分钟都没有上场,替补就派上用场了。在这种情况下,你的第一个符合条件的替补名单将自动取代没有上场的球员。

一旦阵容确定,当每个玩家的游戏开始时,MLS Fantasy 将锁定你的名单,防止你在比赛开始后改变你的阵容。幻想游戏将跟踪每个玩家的表现,并计算他的分数。一旦某周的所有比赛结束,该队首发球员的所有得分之和就是你的球队的最终得分。这些分数可以与所有其他幻想玩家进行比较,赛季结束时得分最多的球队可以赢得奖品。

When in doubt, code it out! Photo by Clément H on Unsplash

构建算法

既然我们已经知道了 MLS Fantasy 的规则,让我们来讨论一下我们将用来生成最佳阵容的实际算法。由于我们希望在给定预算的情况下找到返回的最大点数,线性规划最大化算法似乎是最佳选择。这种算法让我们能够识别出在我们的限制范围内能够产生最高理论点数回报的玩家。幸运的是,Python 包PuLP让这变得很容易。为了达到我们期望的结果,我们需要采取以下步骤。

从 MLS API 提取数据

首先,我们需要从 MLS API 中提取数据,其中包含所有活跃的 MLS 玩家的信息,如本赛季的总幻想点数,玩家的资格(即。如果一个球员受伤或被禁赛,他就没有资格),获得该球员的当前价格,以及该球员状态的最近趋势。

根据资格过滤玩家

我们不希望包括任何受伤或停赛的球员,因为他们将在接下来的比赛周因未能参加比赛而给我们带来零分。一些球队偶尔也会有周末,不打比赛。虽然这些球队的球员在 API 中被技术上标记为合格,但我们不想将他们包括在内,因为他们在本周没有机会获得积分。

我们也应该删除那些在当前赛季中没有参加过任何比赛的球员,因为他们还没有被证实,并且可能在本周不会有太多的上场时间。任何属于上述类别之一的球员都应该从我们的名单中过滤掉,因为他们给我们的分数可能是最少的。

根据运动员最近的表现对他们进行分类

为了确定每个玩家产生大量幻想点数的潜力,我们需要根据玩家的总点数对他们进行分类。我选择看球员最近 5 场比赛的平均水平作为他们目前状态的基准。我认为总积分不能显示一个玩家在过去几场比赛中得分是多了还是少了。考虑到这一点,我们将 MLS 中每一个活跃的玩家按照他们在过去 5 场比赛中的平均得分进行排序,第一个玩家的平均得分最高。

按位置分隔玩家

拥有一个单一的球员排序列表并不能给我们带来太多好处,因为我们对每个位置可以包含的球员数量有限制。相反,我们将按照位置(守门员、后卫、中场和前锋)来划分我们的排序列表。由于我们分离了已经排序的列表,每个单独的位置列表仍将根据我们之前的算法进行排序。

设置我们的 LP 最大化模型

现在实际创建我们的模型。给定上面详述的 MLS Fantasy 的规则,我们的模型由以下定义:

  • 目标函数:我们希望通过只选择给我们最高回报的玩家来最大化可能的点数。Goalie1变量是一个二元变量,表示是否应该使用一个特定的守门员(按照我们之前排序的球员名单的顺序)。其他职位也是如此。Goalie1PtsGoalie1在过去 5 场比赛中的平均得分:
Score = Goalie1Pts * Goalie1 + Goalie2Pts * Goalie2 + ... \Def1Pts * Defender1 + Def2Pts * Defender2 + ... \Mid1Pts * Midfielder1 + Mid2Pts * Midfielder + ... \For1Pts * Forward1 + For2Pts * Forward2 + ... 
  • 预算约束:接下来,我们需要包括我们的约束。首先是预算限制。默认情况下,我们被允许在我们的阵容上花费 1 亿美元。这个约束可以用下面的等式来表示。Goalie1CostGoalie1的当前成本:
Budget = Goalie1Cost * Goalie1 + Goalie2Cost * Goalie2 + ... \Def1Cost * Defender1 + Def2Cost * Defender2 + ... \Mid1Cost * Midfielder1 + Mid2Cost * Midfielder2 + ... \For1Cost * Forward1 + For2Cost * Forward2 + ...
  • 位置约束:最后,我们有位置约束。目前,MLS Fantasy 认为,如果一个名单包括 2 名守门员,5 名后卫,5 名中场球员和 3 名前锋,则该名单符合条件:
Goalie1 + Goalie2 + ... == 2
Defender1 + Defender2 + ... == 5
Midfielder1 + Midfielder2 + ... == 5
Forward1 + Forward2 + ... == 3

运行模型

随着我们的模型的建立和所有约束的添加,是时候求解模型以找到最优解了。通过运行该模型,假设可以达到最优结果,达到最优结果所需的玩家被设置为值 1。

建立花名册

最后,我们需要打印每个位置的建议球员名单。首先,通过检查我们数据集中的每个玩家,我们识别二进制变量的值为 1 的任何玩家,并打印他的名字,因为这个玩家被建议在本周的幻想阵容中使用。

Will this algorithm gain traction on the leaderboard? Photo by Element5 Digital on Unsplash

检查结果

说到底,算法做得怎么样?请记住,由于国际比赛日的原因,在撰写本文时,许多球队和球员都没有参加比赛。考虑到可用的球员,算法选择了一个相当平衡的阵容,卡洛斯·贝拉作为我的队长,其余的球员虽然非常有天赋,在过去几周取得了令人印象深刻的回报,但并不完全是你可能期望的家喻户晓的名字。我还决定换出更便宜的替补球员,希望额外的预算可以为更强大的阵容提供更多的资金。我的完整阵容可以在下图中找到。

MLS Fantasy Lineup Game Week 4

缺少几个高水平球员的一个可能的理由是,当谈到幻想体育时,算法没有大多数人倾向于拥有的任何偏见。作为人类,我们通常选择有设计师名字的球员,这些名字每周都在联盟中闪耀。虽然这是一个聪明的举动,但它在预算中留下了很少的空间来填补阵容,迫使幻想玩家选择较弱的运动员来填补剩余的空缺。另一方面,计算机不关心运动员的遗产,也不关心他每周能得到多少报酬。他们只看到他们被展示的东西,而在我们的情况下,我们只是展示球场上的表现和幻想的价格标签。

说到底,尽管美国职业棒球大联盟因休息而平静了一周,但我的算法最终选择了一支竞争力强的球队,他们以 65 分的总成绩超过了全国 96%的人。它甚至是全国平均水平 31.5 的两倍。虽然我希望该算法将被证明是有用的,但我并不期望第一次迭代执行得如此之好,特别是考虑到我想从这里进行一些改进。

Plotting a course for the algorithm. Photo by Daniil Silantev on Unsplash

我们将何去何从?

由于该算法在第一周表现相对强劲,我计划在本赛季余下的比赛中使用它。由于我错过了游戏的前 3 周,我不指望在春季联赛中爬到排行榜的首位,或任何相对接近它的地方,但我计划利用秋季联赛,看看它在这段时间内表现如何。

由于这只是我使用的算法的第一次迭代,我仍然有很多想法让它更好地向前发展,并计划随着赛季的展开融入这些想法。以下只是其中的一些计划:

  • 分析不同的小队队形
  • 使用不同的方法来发现一个球员的潜力,而不仅仅是过去的 5 个平均水平
  • 比起那些只安排一场比赛的球员,更喜欢一周有两场比赛的球员
  • 确定在家或在路上打球的影响
  • 更喜欢与排名靠后的球队对抗的球员
  • 潜在地使用机器学习来预测玩家的预测得分

在接下来的几个月里,我计划半定期地更新算法的进展,以及它与其他算法相比表现如何。

这个结果是侥幸吗?我运气好吗?还是说国际比赛日给这个等式带来了一个在通常的比赛周不会出现的异常?所有这些问题的答案很可能都是“是”然而,由于 MLS Fantasy 的预算式设置,线性规划最大化算法似乎是为这个游戏量身定制的。

只有时间能证明我的计划会有多成功。对于一个完全基于数字的游戏来说,为什么不应该有一个可以利用这些数字的工具呢?

如何让您的 R&D 团队的生产力翻倍

原文:https://towardsdatascience.com/how-to-double-the-productivity-of-your-r-d-team-3b4b103f0fd7?source=collection_archive---------26-----------------------

一点点数学知识可以帮助你走很长的路

1919 年,英国面临大规模饥荒。虽然赢得了战争,但却破产了。几十年来,英国一直是粮食进口国,现在既不能自己生产足够的粮食,也不能从其他国家购买。债台高筑,经济混乱,政治家们希望科学家们能收拾残局。

他们求助于成立于 1843 年的农业研究站 Rothamsted。它的使命过去是(现在也是)使用科学方法来提高农业生产率。到 1919 年,它已经积累了大量的数据。

农业研究既高度复杂又极其缓慢。许多因素都会影响结果,有些在实验者的控制范围之内,有些则不然:天气、土壤、害虫、基因、肥料等等。更糟糕的是,实验既缓慢又昂贵——实验者不能加快季节的转换,而且可以工作的土地有限。

Winter brassica seedlings at Rothamsted Philip White / CC BY-SA 2.0

Rothamsted 的主任约翰·拉塞尔希望新的统计学能有助于加速事情的进展。他雇佣了正在开发遗传统计学的罗纳德·费雪,让他重新分析农作物数据,看看是否能学到更多东西并立即投入使用。

有可能。费希尔开发了一套技术,将从给定实验中提取的信息量增加了一倍,这是一项重大突破。

为了做到这一点,他忽视了科学探究的一条基本规则,这条规则可以追溯到弗朗西斯·培根,被认为是科学方法的关键。所有科学教育级别都教授的规则是:在每个实验中,你努力创造两个只有一个因素不同的场景。做到这一点,你就可以把不同场景之间的结果差异归因于那个因素。

Fisher 展示了如何在一个实验方案中同时分析多个变量。他的方法把噪音变成了数据。不受控制的因素,如天气或土壤,不一定会掩盖来自(例如)作物品种差异的信号。取而代之的是,多元分析提取了这些信号,并额外产生了关于其他因素影响的信息,包括它们之间的相互影响。

从这种事后分析中得到的教训被扩展到实验设计中。经过适当的随机化和考虑,最佳多因素设计每次运行产生的信息是单因素设计的两倍。

但是走进任何一个生物科学实验室,无论是学术的还是工业的,询问实验的统计设计,你得到的可能只是一个无言的眼神。

生物学家是热爱科学但讨厌数学的人。我们发现图片比数字更有说服力。我们为自己对实验系统如何工作有了一种感觉而自豪。任何关于我们不知道如何恰当地设计实验,或者我们应该用统计算法来代替我们来之不易的判断的建议都可能会遭到怀疑和敌意。

但这是真的。大多数科学家不知道如何设计实验来最大化信息回报。在这个过程中,他们在浪费你的时间和金钱。

一个杜撰的例子

原因如下。一次一个因素(OFAT)的实验设计只有在没有单个因素相互作用的情况下才有效。当他们这样做时,优化就变成了打地鼠游戏:解决一个问题,制造另一个问题。

假设你的团队正在优化一个酶促反应。他们知道(因为他们既聪明又有经验)pH 值和盐浓度等因素可能会影响反应速率。

他们运行一个 pH 系列,得到这样一条曲线:

现在知道了最佳 pH 值,他们在 pH8 下运行 NaCl 系列,并得到以下结果:

你现在知道最佳条件是 pH = 8 和 NaCl = 0.4。这是科学。

但是一些麻烦制造者对此表示怀疑。她熬夜观察酸碱度和盐分的每一种可能的组合。她所发现的令她震惊:

In biology, things interact.

事实证明,降低 pH 值也会降低最佳盐浓度。真正的最佳值实际上是 pH = 6.5 和 NaCl = 0.3。

太好了。但得到这个答案还是费了一番功夫。在六种 pH 水平和六种盐水平下,需要进行 36 次实验。如果她决定添加第三个变量,运行次数将会跳到 216;第四个,到 1296 年。有了更多的变量,你很快就会面临组合爆炸。

你不需要。费希尔和他的后继者表明,从优化设计中获得几乎与全因子实验(36 次运行)一样多的信息是可能的,这比 OFAT 方法(12 次运行)不需要更多的工作。

这里的关键概念是把每一个变量看作实验“空间”中的一个维度。好的实验设计在整个空间中最优地分布运行,对每个区域进行采样,并拾取由因素之间的相互作用引起的失真。对于一个有三个因素的实验,你可以把这个空间想象成一个立方体:

A central composite design for covering the experimental space among three factors. Own work.

像这样的统计设计确保您覆盖实验空间,并且(通过几次迭代)保证您找到一个最优值,不管您的系统行为有多复杂。

当然,像 salt vs pH 这样的简单系统并不是你需要高级设计算法的原因。任何半途而废的团队都可以在一些容易改变的因素中进行优化,即使他们的优化过程是不稳定和低效的。

但是生物科学正在从分子等简单的还原实体向复杂的细胞、组织和器官链转移。影响这些实体的因素的数量以及它们之间的相互作用导致了潜在响应的组合爆炸(通常是非线性的),这是 OFAT 方法所不能涵盖的。

现实世界的例子

我在 MicroPhage 的经历很能说明问题。我们的技术使用细菌病毒(噬菌体)来检测病原体金黄色葡萄球菌并确定其抗生素敏感性。噬菌体是用于诊断测试中非常复杂的实体。它们由数百种单独的蛋白质加上一个 DNA 基因组组成,为了产生信号,它们需要宿主细菌中几十种不同蛋白质的作用。该宿主(金黄色葡萄球菌)有数百种变异菌株,它们与噬菌体表现出不同的相互作用。更糟糕的是,样本基质(病人血液和培养液的混合物)本身就非常复杂多变。

Bacteriophage — a complex nanomachine for diagnostics. Pbroks13 (redraw) [CC BY-SA 2.5 (https://creativecommons.org/licenses/by-sa/2.5)]

当我接管 R&D 团队时,他们已经用 OFAT 的方法转了几年的轮子,优化了一个方面的性能,却发现另一个方面降级了。按顺序测试变量意味着将一些团队成员的想法排在其他人之前,这恰恰对人际关系动态产生了你所期望的影响。

我们梳理了科学文献(所有 100 年的文献),写下了每一个可能影响性能的合理因素,确保包括每个人最喜欢的想法。我相信这个列表大概有 42 个不同的变量。我们使用统计设计一次筛选出所有人。再过一周。每个人都有贡献,没有人的想法被冷落。

六个因素被证明是重要的,我们继续优化它们,使用一类被称为响应面的设计。以下是对其中两个因素的分析示例:

Non-linearity in action

我们系统地优化了各种测试条件下的性能,以确保我们的产品能够从实验室过渡到临床。最终结果是一项一流的测试,在 5 个小时内(而不是通常的 3 天)识别出金黄色葡萄球菌血流感染并确定其抗生素敏感性,准确率达到 98%。

我们花了大约 2000 万美元在 3 年内获得了 FDA 的批准。像我们这样的新诊断技术的通常数字更像是 5 年和 5000 万美元。但是有了像噬菌体这样的复杂实体作为关键成分,我非常怀疑我们使用 OFAT 的方法是否能成功。尽管噬菌体科学已有一百年的历史,但微噬菌体测试是第一个(也是唯一一个)FDA 批准的基于噬菌体的诊断方法。

虽然这是一次技术上的成功,但却是一次商业上的失败;先进的实验设计无法帮助营销工作。但是,如果你的技术包括相互作用的复杂组件,那么你肯定会发现自己被 OFAT 设计的局限性所困扰。实验的统计设计是你走出陷阱的方法。

如何从 IEX 下载所有历史日内 OHCL 数据:用 Python,异步,通过 API &免费。

原文:https://towardsdatascience.com/how-to-download-all-historic-intraday-ohcl-data-from-iex-with-python-asynchronously-via-api-b5b04a31b187?source=collection_archive---------4-----------------------

你正在寻找一种免费获取大量 1 分钟内股价数据的方法吗?回测你的交易算法并在本地训练你的模型?有一个非常好的方法来做到这一点,我将在下面向你展示。

Photo by grz3s from Pixabay

在这篇文章中,我将告诉你如何从 IEX 交易所下载免费的日内数据。请注意,IEX 是美国的一家证券交易所,每天交易的股票代码超过 8000 个。没听说过?点击了解更多信息。

重要的是,这篇文章将向你展示如何从 IEX 交易所有效地、定期地下载所有> 8K 票单的 OHCL 日内数据

为什么从 IEX 获取数据?

你应该从 IEX 获得日内数据有三个原因:

  1. 免费的。IEX 是唯一一个让你定期免费下载大量日内 OHCL(开盘价、最高价、收盘价、最低价)数据的平台。通常,如果您想要获得大型数据集,日内数据是昂贵的。
  2. IEX 的空气污染指数很高。IEX API有很好的文档记录,易于理解,最重要的是它完美地支持异步请求。
  3. 你可以在羊驼上进行纸张交易。 羊驼是我发现的算法交易最好的 API。他们为 IEX 股票代码提供免费、无限制的纸上交易。因此,你可以直接将你用 IEX 数据开发的策略付诸实践。

金融数据的替代 API 服务是什么?

让我提一下我测试过的其他三个服务,你可以考虑作为当天 OHCL 数据的替代来源。出于特殊的原因,所有这些都可能是有趣的。

  1. 世界交易数据 :如果你想从纳斯达克、纽约证券交易所以及非美国交易所收集当天的 OHCL 数据,这是一个非常便宜的选择。示例:通过 16 美元/月的计划,您可以获得 ca 的 2 分钟分辨率数据。50k 股票。然而,这将需要您频繁下载(每隔 2 周,每天 1 个会话,持续 2 周),并且您的下载将非常慢,因为根据我的经验,World Trading Data 不太支持异步请求。
  2. Tiingo : 如果你想收集 IEX 自大约。2017,Tiingo 是最便宜的选择。它只会花费你大约。总共 10 美元,因为 Tiingo 的 API 调用限制非常宽松。注:IEX API 不允许您访问过去超过 30 个日历日的日内数据。因此,如果您希望快速获得更长时间的历史数据,Tiingo 可能会很有意思。相比之下,IEX API 非常适合定期和完全免费的下载。
  3. Alphavantage:如果您希望定期收集纳斯达克、纽约证券交易所等其他交易所的当天 OHCL 数据,并且不需要大量的股票代码,那么 alpha vantage 可能足以免费获得这些数据。Alphavantage 涵盖了大量的报价机。然而,免费计划的 API 调用限制相当有限(每分钟 5 个 API 调用,每天 500 个调用)。

剧本的目的是什么?

下面介绍的脚本是我个人用来从 IEX 收集 1 分钟日内数据的。您可能希望根据自己的目的调整脚本。然而,也许这正是你想要的。我写这个剧本时有以下三个目的:

  1. 收集数据用于后续处理例如回测和训练机器学习模型。(不是:用数据喂饱你的生活算法)
  2. 将数据存储在本地例如,存储在您的电脑上,或者甚至存储在您电脑上的云存储文件夹中。(不是:将数据放入数据库)
  3. 使下载变得简单例如,我希望能够在任何时候用python download_IEX.py运行脚本(不是:必须传递任何参数或必须在特定日期进行下载)

脚本是如何工作的?

每当您用python download_IEX.py执行脚本时,您就开始了一个新的下载会话(对于过去有数据可用但尚未下载的所有日期)。每个下载会话的工作方式如下:

  1. 初始化日志:脚本为当前会话启动一个新的日志文件(见init_logging())。例如,如果您在 10 月 26 日进行培训,您将在script/log/20191026.log中找到相应的日志文件。实际上,每个日志文件都包含执行脚本时可以在终端中看到的打印输出。
  2. 获取日期:脚本获取所有必须完成下载的日期(参见get_dates())。为此,它检查output目录中的现有文件夹,并记下数据已经下载的日期。然后,所需的日期被计算为过去 30 天或更短时间内且尚未在output文件夹中的所有日期。
  3. 进行下载:然后,脚本为步骤 2 中提取的每个日期进行一个单独的异步下载会话。对于每个日期,准备一个异步下载会话(参见asyncio_prep(),例如,从 IEX API 获取所有可用的报价机。然后,使用函数download_tickers_asynchronous()执行该会话,该函数异步读取和写入各个报价机的数据(参见get_csv()write_csv())。

我如何设置脚本?

要设置脚本,您需要完成以下三个步骤。

  1. 将存储库下载到您的计算机上

你可以在这里找到 Github 库。转到Clone or download,然后点击Download zip,下载存储库。然后,将下载的文件IEX_historical-prices-master.zip放在计算机上您选择的文件夹中,并解压缩 zip 目录。

现在,您应该有一个包含以下文件的文件夹(使用您选择的名称):

2.从 IEX 获得免费的 API 密匙

去 IEX 云网站免费注册。然后在SECRET找到API Tokens下你的免费 API 令牌(见下面截图中的红色方块)。

3.建立你的 **script/config.json** 文件

在您选择的文本编辑器中打开一个新文件,例如Visual Studio Code。然后,将以下内容放入新文件的前三行,并用上一步中的SECRET令牌替换YOUR_TOKEN

{"TOKEN": "YOUR_TOKEN"}

现在,点击Save as,在script目录下保存名为config.json的新文件。您的文件夹现在应该看起来像这样:

我如何开始下载?

如上所述设置好脚本后,您可以在script文件夹中打开一个新的终端,并使用python download_IEX.py执行脚本。如果安装了所有需要的软件包(参见download_IEX.py开头的导入),脚本将开始下载 IEX 当天的数据。

在终端中,您将看到每个下载文件的以下内容:
时间戳、股票代码、股票代码的索引(在所有可用的 IEX 股票代码中)以及股票下载的日期:

我如何中断下载?

您可以通过中断正在执行的脚本来中断下载。(如果你在终端中执行这个脚本,control+c在 Mac 上也可以。)稍后,您可以通过使用python download_IEX.py重新启动来恢复脚本,但是您必须在中断脚本时重新开始下载当前正在下载的数据。

重要的是,默认情况下,脚本启动时不会删除任何文件或文件夹。因此,您可能想要手动删除未完成下载的日期的文件夹。这样,当您使用python download_IEX.py重新启动时,脚本将为提到的日期重新开始。

我应该多久下载一次?

如果您希望使用此脚本定期下载 IEX 数据,您将希望至少每四周运行一次。原因是根据文档,API 允许你下载“30 个连续日历日”的数据(参见 IEX 文档)。这意味着,如果您只进行一次下载会话,例如每八周一次,您将有几天缺少数据。

然而,我实际上能够获得超过 30 个连续日历日的数据。可能文件的意思是“30 个连续日历天”。无论如何,每四周执行一次脚本是安全的。

请注意,无论何时运行该脚本,您都不需要设置任何参数,因为它会自动检测哪些日期您已经下载了数据,哪些日期您可以从 IEX 下载数据。因此,您也可以每两周执行一次脚本,或者在下载会话之间有不规则的中断(有时两周,有时更长)。

我如何利用下载的文件?

您可以看到该脚本自动创建了一个按年份、ISO 日历周和日期的文件夹结构。对于每个日期,脚本都会执行一个单独的异步下载会话。这意味着每个交易日都有包含单独 csv 文件的文件夹:每个股票代码一个 csv 文件。

实际上,该脚本为您提供了来自 IEX 的原始数据。以后如何处理这些数据取决于您。例如,您可能希望为同一个跑马灯追加所有文件,以便为每个跑马灯符号获得一个单独的文件。

重要提示:

  • 当某一天的异步下载会话完成时,该天的文件夹会自动压缩以节省空间。因此,您可能希望在处理原始数据之前解压缩文件夹。
  • 每个日期文件夹包含三个数据文件夹DONEERRORNONE。您将需要使用文件夹DONE中的文件,因为这些文件包含有效股票代码的实际日内数据。文件夹ERROR中的文件大部分是来自 IEX 的测试 ticker(见本 GitHub 问题),文件夹NONE中的文件对应于当天没有任何交易的 ticker(见本 GitHub 问题)。

下载的数据会是什么样子?

在给定日期的DONE文件夹中,您会发现每个 ticker 都有一个 csv 文件:

并且这些文件中的每一个都包含相同的 OHCL 信息。以下是苹果公司(AAPL)的一个例子:

参考

  • Github 上的源代码
  • IEX 云文档
  • IEX 票据交易所的 API

感谢您的阅读,期待您的反馈!

如何通过机器学习从加密货币中获得洞察力

原文:https://towardsdatascience.com/how-to-draw-insights-from-cryptocurrencies-with-machine-learning-52ef318c4c1f?source=collection_archive---------31-----------------------

一个方便的教程,总结了你可以做些什么来加载,处理和制作加密货币数据集的有用模型。

Source: Pixabay

加密货币热潮催生了各种各样的用例以及大量有趣的数据。由于默认情况下,支持这些加密货币的许多区块链都是公开的,因此不同区块链之间会产生大量数据。由于每个数据点都创造了经济价值,因此有各种各样的项目和参与者在研究这项技术,从税务监管机构到那些希望预测未来加密货币价格的人。

我是第一批为 TechCrunch 和 VentureBeat 撰写新加密货币以及比特币在汇款支付中的使用的人之一。我对这个主题很熟悉,我也是一个数据科学爱好者,曾帮助跳板公司在的机器学习训练营工作,并有工作保障,所以我一直在寻找方法,将加密货币产生的大量数据与你可以在这些数据基础上建立的具有现实意义的机器学习项目结合起来。

幸运的是,谷歌大查询可以轻松地免费处理一些世界领先的基于比特币的加密货币的数据,从比特币到 Zcash。

谷歌能够建立一个简单的分类器,检测交易是否来自于矿池。你可以在 iPython 笔记本中导入一个库,并开始使用 SQL 查询这个庞大的数据集。让我们用一些样本数据查询来找点乐子,看看我们能用谷歌手头的比特币数据做些什么。

模式中有两个主要的表需要检查:一个“blocks”表和一个“transactions”表,它们是可连接的。

以下是块表的模式:

Source: Author screenshot

在这里,我们需要知道几个基本的定义。区块链由一系列包含交易数据的数据块组成,这些数据块在一段时间后按顺序确认。使用 block_id 查询,我们实际上可以缩小到区块链中的特定块。

让我们用这个探险家来玩转一下区块链的基本概念。查看第一块,我们看到第一块有 50 个比特币输出。区块高度(1)表示它是比特币 mainnet 区块链中挖掘和验证的第一个区块,这是比特币的生产版本,人们使用它在彼此之间进行金融价值交易(与测试网相反,测试网仅用于暂存目的)。

您可以使用 previous_block 变量查询区块链中的前一个 block_id。在这种情况下,块高度为 1,没有 previous_block 引用。但是,如果您查看块高度为 2 的块,那么 previous_block 将引用 genesis 块/块高度为 1 的块。

Merkle root 是一个块中所有散列事务的散列,它允许您以低得多的计算成本来验证整个块的完整性。

每个数据块还有一个时间戳,它有一个相对准确的度量标准,用于验证数据块的有效性,并作为一个额外的认证层来抵御区块链攻击者。每个区块中的难度目标是开采一个区块需要多少计算能力的度量:每 2016 个区块调整一次难度,以确保每 10 分钟开采一个区块的持续平衡速率。由于比特币是一个工作验证系统,挖掘区块是允许系统就其当前状态达成共识的东西,无论存在多少节点和交易。

每个块都有一个满足网络要求的随机数,这意味着该块可以被挖掘。有一个版本标记,讲的是比特币代码的核心配置的版本,可以作为一个区块是在什么条件和具体规则下被挖掘的标记。

Work_terahash 表示贡献和挖掘一个块需要多少计算能力。以现在的比特币为例,认真的矿工会运行 terahashes(万亿次尝试的比特币问题解决方案)——每秒高达 13 次。该度量可以作为挖掘一个块需要多少计算资源的代理(连同难度等级)。

您可以在 BigQuery explorer 上试验不同的查询来测试它们,尽管您会受到速度的限制,尤其是对于返回千兆字节数据的大型数据查询。这个限制很容易与丰富的区块链数据发生冲突。

Google BigQuery 有一个特殊的函数,在这个函数中,您需要使用反斜杠(`)将表名括起来,这样它也是一个有效的查询。

作为第一个查询,我们可以看看比特币中的第一块,也就是创世纪块。我们看到它的 Merkle 根是“0 E3 e 2357 e 806 b 6 CDB 1 f 70 b 54 c 3a 17 b 6714 ee 1 f 0 e 68 bebb 44 a 74 B1 EFD 512098”。为该 Merkle 根选择 block_id 将得到 genesis 块的 block_id,00000000839 A8 e 6886 ab 5951d 76 f 411475428 AFC 90947 ee 320161 bb f18 EB 6048。当我们检查区块链资源管理器中的 block_id 时,我们看到它保存的块高度为 1,这证实了这实际上是比特币中开采的第一个块。

Source: Author screenshot

在分析了所有的块变量之后,我们可以进入交易级别的变量——不同比特币用户之间的交易量。

通过交易表的主键 transaction_id,我们可以解锁一个块内单个交易的信息:从每个块内每笔交易的代码输出到 satoshis (1 亿 satoshis 等于一个比特币)的金额的一切。区块将有许多交易,这些交易是比特币的生命线,即不同账户之间的价值转移。

coinbase 还包含与传输的 satoshis 无关的代码和输出——这可以用于识别挖掘池之类的事情,这些挖掘池聚合计算能力,然后在个体贡献者之间分配加密货币挖掘的收益,这些贡献者明确地将他们的签名作为输出放在块 coinbase 上以识别他们自己。

在体验了不同的 SQL 查询和 Google BigQuery 接口提供的不同概念之后,我们可以使用 Kaggle 的 BigQuery 客户端工具及其内核接口直接导入到 iPython 笔记本中,然后还可以执行聚合函数、子函数以及 SQL 提供的所有功能,以获取数据块及其包含的事务的准确数据量。

让我们对比特币区块链数据 中包含的每个数据块进行计数,并使用 iPython 和 Kaggle 内核 中的接口进行一些不同的查询,我们可以通过它们与 BigQuery 的集成轻松获得数据。

Source: Author screenshot

利用这种在比特币区块链和不同加密货币上获取丰富数据的能力,我们可以在机器学习中做些什么?

对矿工是否属于矿池进行分类

谷歌发布了一个样本项目,该项目能够对给定的交易是否由矿池生成进行分类,这是一种将几个实体和个人的计算能力聚合在一起的努力,目的是鉴于比特币和其他加密货币的难度,试图成功挖掘它们。

下面的查询从给定特定地址和空闲时间的输出得到 26 个特征向量。使用一个简单的随机森林分类器和 coinbase 中的矿工分类,谷歌能够训练和标记一个模型,帮助确定交易是否可能作为采矿池的一部分产生。

将加密货币的兴趣和难度与价格水平相关联并进行预测

你可以考虑各种因素,如区块链的难度和哈希能力,以及链条上的交易活动量,并将其与历史价格数据相关联,看看你是否可以根据时间序列分析和链条因素预测未来价格——目前这可能是一项非常有利可图的投资。

根据属性对不同的区块链进行分类

你可以从不同的区块链中获取不同的属性,例如矿工奖励的基尼系数,就像在对 Kaggle上的以太坊经典的分析中所做的那样,然后使用它来分析基于不同特征的不同区块链之间的相似性,例如采矿奖励的集中程度,或者难度水平或版本历史变化——或者你可以找到的任何其他东西。

如何用 Python 驱动你的 Arduino 推进的机械臂

原文:https://towardsdatascience.com/how-to-drive-your-arduino-propulsed-robot-arm-with-python-4e428873237b?source=collection_archive---------19-----------------------

Arduino 微控制器是一个漂亮的电子产品。开箱即用,它可以驱动您的大多数设备和原型。GPIO 的数量、用户友好的 IDE 和低廉的价格给现代原型方法带来了重大变化。然而,这种怪物不能解决强大的计算过程。由于机器人涉及复杂的算法,你应该考虑 Python 和 Arduino 的合作来让它活起来。

这是“从零开始设计机器人手臂”系列的第二篇文章。

在第一篇文章中,我们获得了一个相当有用的 Keras 模型,并在模拟中对其进行了图形化测试。

现在我非常兴奋能在真正的原型上使用这个模型!我们希望评估它与模拟结果相比有多好,并得出关于我们的接近值的第一个结论。最后的工作将是设计一些方法来最小化误差。

Python 和 Arduino 之间的串行链接。

为了连接它们,我想使用 pySerial 库,它使我们能够通过 Arduino 的串行端口进行通信。

基本上,当 Arduino 通过串口监听时,python 脚本会同时向他发送一些信息。这种基本的通信过程使我们能够向机器人发送我们预测的角度三元组,以便将它驱动到希望的位置。

Serial Communication Process

在端口参数中,您需要输入 Arduino 卡使用的通信端口。波特率应该与 Arduino 脚本中的波特率相同。

Code on the python-side

在 Serial.begin(9600)行中,您正在设置波特率。

Code on the Arduino-side

使用模型生成推论(预测需求角度)

多亏了 Keras 图书馆,这项工作才得以完成。你只需要使用函数

model.predict

您还可以决定创建两个不同的脚本:一个将训练模型,另一个将利用它。为此,您需要在第一个脚本中保存模型,并在第二个脚本中加载它。

很明显 Keras 已经帮你做了。以下是主要功能:

model.save(“model.h5”)

并且加载它:

model = load_model(“model.h5”)

现在你真的离你预想的很近了。现在的任务是设置你的伺服系统,为你的(X,Y)坐标生成预测,并将预测的角度发送给机器人——享受结果。

非常感谢您的阅读,如果您有任何问题,或者您有合理的批评,或者只是想交流您的项目,请随时联系我们。

下一篇文章将会比较模拟和应用程序的健壮性。为此,我使用 CNN 通过视觉识别来检测机器人的位置。

敬请期待!!

这是完整的 Python 脚本。

这是完整的 Arduino 脚本。

为了更好地理解,你应该读一下上一篇文章:

“一种高效快速控制机器人的方法。真的。”https://link.medium.com/LIGf4r3k5Z

参考文献:

张量流:https://en.wikipedia.org/wiki/TensorFlow

https://en.wikipedia.org/wiki/NumPy号

https://en.wikipedia.org/wiki/Matplotlib

https://en.wikipedia.org/wiki/Keras

如何使用 Flask 轻松部署机器学习模型

原文:https://towardsdatascience.com/how-to-easily-deploy-machine-learning-models-using-flask-b95af8fe34d4?source=collection_archive---------0-----------------------

把你的模型从 jupyter 笔记本带到生产中

Photo by SpaceX on Unsplash

被困在付费墙后面?点击这里阅读完整故事与我的朋友链接!

当数据科学家/机器学习工程师使用 Scikit-Learn、TensorFlow、Keras、PyTorch 等开发机器学习模型时,最终目标是使其在生产中可用。很多时候,当我们从事机器学习项目时,我们会把很多精力放在探索性数据分析(EDA)、特征工程、超参数调整等方面。但我们往往会忘记我们的主要目标,即从模型预测中提取真正的价值。

部署机器学习模型或将模型投入生产意味着将您的模型提供给最终用户或系统。然而,在机器学习模型的部署中存在复杂性。这篇文章旨在让你开始使用 Flask API 将训练好的机器学习模型投入生产。

我将使用线性回归来预测第三个月的销售额,使用前两个月的利率和销售额。

什么是线性回归

线性回归模型的目标是找到一个或多个特征(自变量)和一个连续目标变量(因变量)之间的关系。当只有一个特征时,称为单变量线性回归,如果有多个特征,称为多元线性回归。

线性回归假设

线性回归模型可以由下面的等式表示

  • Y 是预测值
  • θ ₀是偏差项。
  • θ ₁,…, θ ₙ为模型参数
  • x ₁、 x ₂,…、 x ₙ为特征值。

Linear regression illustrated

为什么是烧瓶?

  • 好用。
  • 内置开发服务器和调试器。
  • 集成单元测试支持。
  • RESTful 请求调度。
  • 大量记录。

项目结构

该项目有四个部分:

  1. model.py 它包含机器学习模型的代码,用于根据前两个月的销售额预测第三个月的销售额。
  2. app . py——它包含 Flask APIs,通过 GUI 或 API 调用接收销售细节,根据我们的模型计算预测值并返回。
  3. request.py —它使用请求模块调用 app.py 中定义的 API,并显示返回值。
  4. HTML/CSS —它包含 HTML 模板和 CSS 样式,允许用户输入销售详细信息,并显示第三个月的预测销售额。

Pipeline for deployment of a Machine Learning model

环境和工具

  1. sci kit-学习
  2. 熊猫
  3. numpy

代码在哪里?

事不宜迟,让我们从代码开始吧。github 上的完整项目可以在这里找到。

让我们从使用 HTML 为用户输入值制作前端开始。有三个字段需要用户填写——利率、第一个月的销售额和第二个月的销售额。

接下来,我使用 CSS 对输入按钮、登录按钮和背景进行了一些样式设计。

我为这个项目创建了一个自定义销售数据集,它有四列——利率、第一个月的销售额、第二个月的销售额和第三个月的销售额。

我们现在做一个机器学习模型来预测第三个月的销量。首先让我们用熊猫来处理缺失值。当没有为一个或多个项目提供信息时,可能会出现数据缺失。如果没有提供值,我用零填充比率列,用该列的平均值填充第一个月的销售额。我用线性回归作为机器学习算法。

序列化/反序列化

简而言之,序列化是一种在磁盘上编写 python 对象的方法,该对象可以传输到任何地方,稍后可以由 python 脚本反序列化(读取)回来。

Serialization, De-Serialization

我使用 pickling 将 python 对象形式的模型转换为字符流。这个想法是,这个字符流包含在另一个 python 脚本中重建对象所需的所有信息。

下一部分是制作一个 API,它通过 GUI 接收销售细节,并根据我们的模型计算预测的销售值。为此,我以 python 对象的形式反序列化了 pickled 模型。我用index.html设置了主页面。在使用 POST 请求向/predict提交表单值时,我们得到预测的销售额。

可以通过向/results.发出另一个 POST 请求来显示结果,它接收 JSON 输入,使用训练好的模型进行预测,并以 JSON 格式返回预测,可以通过 API 端点访问该格式。

最后,我使用请求模块来调用在app.py中定义的 API。它显示第三个月返回的销售额。

结果

使用此命令运行 web 应用程序。

$ python app.py

在您的网络浏览器中打开 http://127.0.0.1:5000/ ,应出现如下所示的 GUI。

Graphical user interface

结论

本文展示了一种部署机器学习模型的非常简单的方法。我使用线性回归来预测第三个月的销售额,使用利率和前两个月的销售额。人们可以利用在这个博客中获得的知识制作一些很酷的模型,并把它们投入生产,这样其他人就可以欣赏他们的工作。

参考资料/进一步阅读

[## 用 80 行代码编写一个简单的 Flask Web 应用程序

快速入门示例教程

towardsdatascience.com](/writing-a-simple-flask-web-application-in-80-lines-cb5c386b089a) [## 部署机器学习模型| Coursera

从加州大学圣地亚哥分校学习部署机器学习模型。在本课程中,我们将了解…

www.coursera.org](https://www.coursera.org/learn/deploying-machine-learning-models) [## 将机器学习模型部署到云的简单方法

使用简单的技术堆栈将您的第一个 ML 模型部署到生产环境中

towardsdatascience.com](/simple-way-to-deploy-machine-learning-models-to-cloud-fd58b771fdcf) [## 在生产中部署机器学习模型的不同方法概述

将模型投入生产的方法有很多种,不同的方法会带来不同的好处

www.kdnuggets.com](https://www.kdnuggets.com/2019/06/approaches-deploying-machine-learning-production.html)

在你走之前

相应的源代码可以在这里找到。

[## abhinavsagar/机器学习部署教程

从数据收集到将模型投入生产的端到端项目示例…

github.com](https://github.com/abhinavsagar/Machine-Learning-Deployment-Tutorials)

联系人

如果你想了解我最新的文章和项目,请关注我的媒体。以下是我的一些联系人详细信息:

  • 个人网站
  • 领英
  • 中等轮廓
  • GitHub
  • 卡格尔

快乐阅读,快乐学习,快乐编码。

如何在 Python 中通过位置快速连接数据—空间连接

原文:https://towardsdatascience.com/how-to-easily-join-data-by-location-in-python-spatial-join-197490ff3544?source=collection_archive---------7-----------------------

如何在 Python 中轻松地进行空间连接,以及为什么它是数据科学中经常被忽略的强大工具。

如果你使用了熊猫图书馆,你很有可能已经加入了两个表。令人难以置信的是,将两个共享列的不同数据集组合起来是如此容易。但是您知道有一种基于位置连接表(数据帧)的简单方法吗?

Spatial join example

我向您展示了一种使用空间连接来连接表的有效方法。空间连接类似于通过属性连接数据。关键区别仅在于表是基于它们在空间连接中的位置进行连接的。要执行按属性连接,两个表中必须有匹配的键;相反,您需要位置(纬度&经度)来执行空间连接。

空间连接的用例很多。假设您将学校作为点,将学区作为面(多边形),您想要确定每个学区有多少所学校。通过执行空间连接,可以快速将点表转换为面积表,反之亦然。

实际应用:以 Airbnb 数据集为例

足够的概念和假设的例子。让我们举一个具体的例子。我想知道每个投票区有多少 Airbnb 房源。在本教程中,我使用了斯德哥尔摩的 Airbnb 数据集。高亮显示的数据集用于演示空间连接。

Airbnb Dataset Stockholm — Source

让我们像往常一样用.read_csv()先读熊猫里的表格。在第 2 步中,我们使用 Geopandas 将纬度和经度转换成几何图形。邻域数据在 Geojson 中,因此我们可以直接在 Geopandas 中读取。Geopandas 是一个高级的 pandas 库,可以轻松处理位置数据。

import pandas as pd
import geopandas as gpd# 1-  Listing points
listings = pd.read_csv(“data/stockholm_listings.csv”)# 2 - convert to Geopandas Geodataframe
gdf_listings = gpd.GeoDataFrame(listings,   geometry=gpd.points_from_xy(listings.longitude, listings.latitude))# 3 - Neighbourhoods
geojson_file = “data/stockholm_neighbourhoods.geojson”
neighborhoods = gpd.read_file(geojson_file)

gdf_listings 表中每个属性有不同的列,包括主机名、邻居、纬度和经度。Geopandas 转换增加了几何列,允许我们进行空间连接。

Airbnb Listings table

另一方面,Geojson 邻域文件保存了邻域的名称和几何图形。

Neighbourhood table

两个数据集都有邻域列,如果你将它们重叠绘制,它们会很好地对齐(如下图),我们可以很容易地分组,并根据每个邻域的大小来计算每个邻域中的列表数。

Airbnb Listing as Points and Neighborhoods as Areas

但是,假设您有一组不同的邻域(多边形)。假设投票区(较小的区域)提供了更好的粒度,并具有其他有趣的属性,如人口总数。让我先用 Geopandas 读取数据。

stockholm_areas = gpd.read_file(“data/stockholm_areas.geojson”)
stockholm_areas.head()

每个投票区都有一个保存该区代码的Deso列和一个保存每个区总人口的Total列。这些新的粒度(更小)区域也完全覆盖了点数据集,但问题是我们不知道该点属于哪个投票区。该数据仅来自“邻居”列

Listings map — Points of listings and voting districts

空间连接

假设我们对计算每个投票区域(投票区)的列表数量感兴趣。尽管在我们的专栏中不容易获得,但我们可以很容易地做到这一点,这就是空间连接派上用场的地方。只需一行代码,您就可以确定哪个点在每个投票区内。

sjoined_listings = gpd.sjoin(gdf_listings, stockholm_areas, op=”within”)sjoined_listings.head()

上面的代码根据位置将gdf_listingsstockholm_areas连接起来。op参数决定了你想要什么样的连接。在这种情况下,我们提供了“在内”,这决定了点属于哪个区域。下面是来自连接表的 5 行示例。

Spatial join table

正如您所看到的,这个表根据它们的位置将两者连接起来。我们知道点的属性以及点属于哪个区域。现在用熊猫分组功能很容易统计每个区域有多少房源。我们可以像这样执行 pandas Groupby,以获得每个投票选区中有多少列表。

grouped = sjoined_listings.groupby(“Deso”).size()
df = grouped.to_frame().reset_index()
df.columns = [‘Deso’, ‘listings_count’]

我们以地区代码Deso的数据框架结束,并列出每个地区的计数。

Grouped-by Dataframe — number of listings per voting district

请注意,这个分组数据是一个数据帧。如果你想用投票区数据集,你可以简单地使用 pandas 合并功能,基于两个数据帧上的“Deso”列。

merged_areas = stockholm_areas.merge(df, on=’Deso’, how=’outer’)

合并的结果是地理数据框架,您可以在地理上对其进行绘制。以下是各投票区列表数量的 Choroplpleth 地图。

Choropleth map — Number of listings per voting district

如果您有一些想法,请尝试空间连接,否则请尝试连接您选择的城市和不同区域的 Airbnb 数据集。

结论

空间连接是数据科学中不常用的强大工具。在 Geopandas 的帮助下,用 Python 实现这一点非常直观和简单。在本教程中,我们使用 Airbnb 数据集通过一个实际示例执行了空间连接。我希望您发现这有助于将它添加到您的数据科学技能中。

本教程的代码可以在这个 GitHub 存储库中找到。

[## shaka som/空间连接

如果你使用了熊猫图书馆,你很有可能已经加入了两个表。令人难以置信的是,这是多么容易…

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

如果您想直接运行本文的代码,github 存储库中还包含一个 google colab 笔记本。

如何轻松地教孩子数据科学

原文:https://towardsdatascience.com/how-to-easily-teach-your-kids-data-science-4df1944338be?source=collection_archive---------10-----------------------

父母总是在寻找新的方法让他们的孩子“迷上”科学、技术、数学或工程(STEM)学科。与其说是早期灌输工程学的乐高玩具,不如说是编程的树莓 pi 或 arduino,或者是激发数学和技术兴趣的书籍和玩具,似乎有各种各样的材料可供父母一夜之间将他们的孩子变成 STEM 明星。

不久前在一次飞行中,我邻座的人问我是做什么工作的。我解释说,我本质上是一名数据科学家。他们问我那具体是什么,我没有深究其中的细节,只是说那是“一个质疑数据以寻求答案的人。”这可能不是最好的解释,但他们点点头,继续问我问题。“什么类型的数据?”他们好奇地问,因为他们盯着他们的蔓越莓苹果。我回答说:“天气和气候,但我偶尔也会涉足其他领域,比如能源。”他们接着问,“金融方面呢?”我摇摇头,但接着说“检查财务数据对我来说并不难。数据科学实际上是了解何时使用某些模型,以及哪些功能最适合该模型。”然后,不知从哪里冒出来的,这个人说了一句让我思考了一整天的话:“伙计,我希望我的孩子也能成为那样的人。听起来真的很有挑战性。”我继续解释说,数据科学并不难,寻找(现实的、可验证的)模式才是这个领域的核心。孩子们已经很有能力这样做了。

所以我想,“怎样才能让孩子们成为数据科学家?”结果如下:

请注意,这种方法已经在两个 8 岁和 11 岁的孩子身上进行了测试。

  1. )获得 11 个不同形状、颜色、气味或质地的物体。

就我个人而言,我回想起小时候老师给我们彩虹糖来练习算术的日子。在这里,Skittles 也能很好地工作,只要确保你使用了所有的颜色,但是保留一种颜色作为“随机”或“黑天鹅”数据点。任何可以得到的东西都可以。

2.)在活页夹或其他分隔物(任何不让你的孩子看到的东西)后面,只用你收集的 5 个物体做一个图案(所以如果你有一便士、五分、一角、二角五分和一美元,你可以按你喜欢的任何顺序排列它们)。让你的小科学家看看你做了什么图案,然后添加你的下 5 个对象。

3.)揭秘:问你的小科学家你认为接下来的 5 个物体会是什么图案。如果他们猜对了,显示图案,但将第 11 个(之前未介绍的对象)添加到对象行中。如果他们没有猜对,让他们继续猜,直到他们猜对为止。暗示他们可能已经看过这些物品。

4.)随机性:在处理数据时,随机性或“噪音”是很重要的。人们可能认为它“没什么”,但调查它是非常重要的,而不是它真的“没什么”,或者它是否是一个独特的事件。未引入的对象产生随机性。起初,这会让你的小科学家感到困惑,但是你做得越多,他们就越有可能期待你这样做。

5.)预测:让你的小科学家告诉你下一个 5 天体的顺序会是什么。(做一个假设)将你使用的前 5 个物品放在你在第 3 步中放置的 6 个物品之前。你的孩子应该猜对了,甚至可能猜到你已经将“随机”对象添加回模式中。

6.)下一轮:确保你指出接下来的 5(或 6)个物体将与他们已经看过的图案相似。一旦他们记下了那个模式,你可以通过尝试不同的模式来混合它,或者混合对象来使它变得更复杂。

7.)形象化它:当你进行的时候,让你的小科学家画出物体顺序和它们的预测顺序的图表。这可以通过拿起一支铅笔,写下何时何地出现了什么样的物体来完成——如下图所示。你也应该保持跟踪以验证结果。

How the game should be “playing” out. Image made by author.

8.游戏结束:自然,这是一个可以永远继续下去的游戏,老实说,那样会更有趣。但是,你至少可以在三个回合后结束游戏。匹配它,看看他们做得有多好!

使用你家周围的材料,你可以很容易地教你的孩子关于模式,随机性和数据可视化。我使用这种方法是因为我认为对于父母来说,寻找一种快速、简单的游戏来和他们的孩子一起玩而不需要购买任何东西会更容易。你可以出去让你的孩子看看树叶上的虫子,但是大自然比客厅要复杂一点,你可能不会在虫子身上找到很多图案。不用大词,你已经很容易地向你的孩子灌输了模式、概率和随机性的概念。这些是数据科学家的核心概念,早期理解将使您的小科学家更有可能在以后的其他领域和应用中理解这些东西。

免责声明:这个游戏不会让你的孩子成为数据科学天才,但它将有助于开发一些早期的基础知识。如果你有任何其他方法想要分享,请在下面的回复中发表。

如何在你的业务中有效地运用人工智能策略

原文:https://towardsdatascience.com/how-to-effectively-employ-an-ai-strategy-in-your-business-d43f41aa3b04?source=collection_archive---------14-----------------------

今天的首席管理人员的 5 个关键人工智能要点

人工智能已经从一个时髦的词发展成为今天的现实。拥有机器学习系统专业知识的公司正在寻求转向基于人工智能的技术。尚不具备机器学习文化的企业正试图设计一种策略来实现这种文化。在这种炒作和被抛在后面的恐惧中,你将如何在你的公司中着手一项人工智能战略?今天,这似乎是一个反复出现的常见问题。本文试图更深入地探讨企业在实施人工智能战略时面临的一些挑战、机遇和可能性。

当今人工智能的关键挑战:3t

在一家公司中创建人工智能生态系统会面临很多挑战。所有这些挑战可以归结为三个主要方面:

  • 人才:组建一个人才团队是当今许多企业最关心的问题之一。
  • 时间:另一个关键要素是时间。重要的是要看看通过实施人工智能战略,你能以多快的速度获得业务成果。
  • 信任:信任是指对你的机器学习模型的信任,以及你向监管者和利益相关者解释你的模型结果的能力。

这里有一些解决这些问题的建议,这些建议是通过多年来与大量 H2O.ai 的客户和用户交谈而形成的。

1.构建数据文化

为了利用产生的大量数据并理解它们,公司需要首先建立一种数据文化。在一家公司建立数据驱动的文化时,应该记住以下三个要点:

  • 数据采集

要建立数据文化,首先需要主动收集数据。今天的数据可以从各种来源获得,如市场营销部门、销售部门、产品监控、客户分析等。这实质上形成了基础。

  • 使数据可访问

已经收集的数据需要向人们公开。这意味着数据应该是这样一种格式,这使得人们可以轻松地处理数据并从中获得有意义的见解。

  • 找到合适的人才

数据本质上是一项团队运动。这意味着,尽管公司需要专家来创建模型和算法,但他们也需要具有不同技术能力的人,这些人可以在将数据传递给专家之前,从数据中发现有用的见解。为此,我们可以培训现有的员工,因为他们拥有这项工作所必需的领域经验。机器学习既是一种文化转型,也是一种商业转型。因此,公司可以雇佣一些数据科学家,并利用现有的经验丰富的员工来协助他们,而不是从头开始创建一个新团队。

2.问正确的问题

提出正确的问题是在公司中创造数据文化的必要条件。我如何获得下一个客户,谁是下一个客户,我如何优化我的供应链是当今大多数企业需要回答的一些问题。有时候,将业务问题公式化可以作为实现人工智能的垫脚石。为了能够提出相关的问题,公司需要有分析型 思维定势的人,以及有 数据 支持的解决方案,而不是直觉。

  • 你正在解决什么问题?

如今,人工智能和机器学习几乎被用于所有行业。一些众所周知的例子如下。

在这些行业中使用人工智能的想法是为了节省时间和金钱,并获得相对于其他人的竞争优势。如果您的公司处理上述任何用例或一些类似的业务问题,而您只依靠传统方法,您一定会落后。

  • 决定结果

问正确的问题决定了它能产生什么样的结果。关键思想是将贵公司的高层次目标转化为业务问题,然后确定其结果。

  • 衡量成功

公司也需要拿出衡量他们成功的标准。不同的公司对成功的定义可能不同,但最终目标是相同的,即盈利和创造价值。

3.连接到社区

社区在推动任何公司的变革中扮演着至关重要的角色。有在线(网络研讨会)和离线(聚会)两种方式与社区联系。组织聚会、网络研讨会和培训会议可以让一个人交流知识并向他人学习。向他人学习参与会议,分享相关知识是联系社区的好方法。你在哪里不重要。世界各地都有机器学习社区,可能就在你家旁边就有一个地方分会。

连接到社区的另一个重要原因是,今天的大多数数据科学家和研究人员都希望与其他人合作。人工智能领域的技术正在飞速发展,通过连接,人们希望提出所有正确的问题,与他人分享,参与其中,并向每个人学习。不用说,在最近十年中,大多数前沿研究都来自学术界和开源社区。

4.技术考虑

决定使用哪种技术是一个重要的考虑因素,会对您的业务产生深远的影响。

  • 开源还是闭源?

如果公司正在开始人工智能之旅,他们可能需要决定是使用开源软件还是开源软件,或者两者兼而有之。机器学习和人工智能领域的许多现有先驱定期开源他们的技术,这可以成为其他人的良好起点。一旦这些新的人工智能玩家成熟了,他们可能需要一个供应商来支持他们。你也可以选择一个本身就是软件包维护者的供应商,例如,对于开源的 H2O-3,H2O.ai 既是维护者也是供应商。

  • 云还是本地?

这个问题的答案取决于你想以多快的速度开始。如果您刚刚开始,并且没有现成的开发-运营系统,那么开始使用云会更容易。这将消除购买硬件、安装软件、安全、基础设施和维护问题的需要。但是,如果您已经有了一个不错的 DevOps 基础架构,内部部署选项有助于优化成本。许多公司也更喜欢混合模式,无论他们是根据自己的要求在云和本地之间切换,这都是一种很好的做法。

  • 数据

同样,正如已经提到的,数据是一个关键点。了解如何生成、保存和访问数据至关重要。数据隐私、数据治理和数据传承等是公司需要适当解决的一些问题。

5.信任人工智能

机器学习模型不应被视为“黑盒”。这意味着我们应该能够清楚地解释或识别他们预测背后的逻辑。能够充分地描述模型的决策,拥有健全的文档,从结果中消除偏见是一些重要的考虑因素,这些都是公司在向人工智能灌输信任元素时需要回答的。

你从这里去哪里?

那么,你将何去何从?通过深思熟虑以上五个要点,并与你的团队讨论,公司可以从哪里开始他们的旅程获得一种感觉或方向。思考并确定你目前试图解决的问题,看看你如何使用机器学习和人工智能来给你带来优势。人工智能文化需要发展,就像每一项重要任务一样,需要时间、耐心和资源。

如何在大规模神经网络中有效地传播激活

原文:https://towardsdatascience.com/how-to-efficiently-propagate-activations-in-a-massive-neural-network-3faed60cb8f5?source=collection_archive---------40-----------------------

事件驱动的方法

在使用 sigmoid 激活函数的传统神经网络中,所有神经元都或多或少地被激活。这里没有不活跃神经元的明确例子。如果你想计算非常大的网络,这可能会有问题,因为在每一轮中,你必须更新所有的神经元。直觉上,只更新那些与当前输入数据集有关系的神经元会更理想。例如,如果你试图处理一只猫的图像,为什么所有与识别宇航员相关的神经元也要活跃呢?实现这个目标的一个先决条件是选择一个合适的激活函数。这种激活函数应该为所有负输入值返回零。人们可以使用 ReLU 作为激活函数或双曲正切函数的正半部分。利用这样的激活函数,通过使用零阈值,有可能清楚地区分活跃和不活跃的神经元。既然我们不想更新所有的神经元,那么我们如何决定哪些神经元应该更新呢?一种简单的方法是使用队列。如果一个神经元被激活,只需将所有通过传出突触连接的神经元添加到队列中。然后,在每个处理步骤中,从队列中取出一个神经元,更新它,如果它被激活,就再次将传出神经元添加到队列中。

但是,即使使用这种优化的算法,我们也可能会计算太多的更新操作。大多数更新的神经元在更新后仍将保持不活动。如果在我们真正更新神经元之前,我们就能决定它是否有机会变得活跃,那会怎么样?

让我们仔细看看一个神经元可以拥有的不同权重模式。这里可能有像这样的分离神经元:

在这种情况下,每一个输入神经元的激活都需要一个当前神经元的更新。但是可能会有更多像这样的连接神经元:

这里,输入 A 必须在当前神经元有机会激活自己之前被激活。因此,当前神经元的更新仅需要在输入 A 被激活之后发生。但是在下面的情况下会发生什么呢?

在这种情况下,在当前神经元需要更新之前,两个输入 AB 都必须有效。这可以通过需要联合触发的三个或四个输入来进行。那么,我们如何利用这些知识来防止神经元过早更新呢?

这可以通过引入逻辑节点来实现,逻辑节点仅用于确定接下来需要更新哪个神经元。有了这些逻辑节点,我们突然进入了专家系统的领域,尽管我们是从我们的突触权重间接获得我们的知识库。这种基于逻辑的系统的好处是它们允许一些很好的优化。一种这样的优化是将较大的连接节点分割开,并在模式网格中表示它们:

在这样的网格中,如果无法激活节点,激活不需要传播到最特定的节点。例如,如果在这个点阵中只有两个输入 AC 被激活,那么激活只需要传播到相对一般的节点 AC ,而不需要传播到更具体的节点 ABC 。因此,在这种情况下,与节点 ABC 相关联的神经元不需要更新。当然,这些逻辑节点可以由几个神经元共享。

代理对象

使用大型网络结构时出现的另一个问题是如何将它们放入主存。如果模型变得太大,唯一的解决方案是在外部存储模型的一部分。当然,这会造成性能损失,但这真的有那么糟糕吗?如果只有很少使用的神经元和逻辑节点(大多数通常都是这样)被存储在外部,那么这种损失对于大多数应用程序来说应该是可以接受的。延迟参数可用于确定未使用的神经元在被移除之前应在内存中停留多长时间。使用该参数,可以在性能和内存消耗之间进行权衡。

为了能够从网络中移除单个神经元或逻辑节点,可以使用代理对象。代理对象能够从外部源加载神经元,并在需要时将其恢复到主内存中。当然,所有的突触都需要链接这些代理对象,因为一些链接的神经元可能还不在内存中。代理对象简单地提供了一个 get() 函数,然后该函数返回对主对象的引用。

当在外部存储器中存储神经元时,区分连接和分离神经元是重要的。根据它们所代表的类别,分离的神经元可能拥有非常大的一组输入突触。为了防止这些大型数据结构需要一次性加载,可以将分离的突触存储在输入神经元侧。

目前,我们正在一个拥有约 2000 万个神经元的网络上使用这种算法,对于一个给定的文档,平均有几千个神经元被激活。一份文件的处理时间约为 100 毫秒至 200 毫秒。

这种方法的一个实现可以在 GitHub 上的 AIKA 开源项目中找到。

技巧、窍门、诀窍和魔法:如何毫不费力地优化您的 Jupyter 笔记本电脑

原文:https://towardsdatascience.com/how-to-effortlessly-optimize-jupyter-notebooks-e864162a06ee?source=collection_archive---------3-----------------------

让 Jupyter 笔记本变得更好、更快、更强、更光滑、更棒的完整初学者指南

Image by peter_pyw from Pixabay

科技真正酷的地方在于有多少人在努力工作,让你的生活变得更有趣。每一天的每一分钟,都有人把他们的血汗和眼泪投入到工具中,让你的程序、软件包、应用程序和生活运行得更顺畅。

举例来说,你可能会认为一旦你有了 Jupyter 笔记本电脑,就万事大吉了。如果成功了,你就完了!你可能没有意识到的是,有几乎无穷无尽的方法可以定制你的笔记本电脑。安装程序或软件包仅仅是开始!

为什么不花几分钟时间放松一下,做一些改进呢?有很多简单的方法可以让你的 Jupyter 笔记本变得更好、更快、更强、更性感、更有趣。

本指南假设您对 Jupyter 笔记本相当陌生。在进入更酷的技巧之前,我们将从初学者真正基础的东西开始。如果您真的是新手,并且在安装和运行 Anaconda 时遇到了困难,您可能想看看这篇文章:

[## 如何在 Mac 上成功安装 Anaconda(并让它实际工作)

正确安装 Anaconda 和修复可怕的“找不到 conda 命令”错误的快速而简单的指南

towardsdatascience.com](/how-to-successfully-install-anaconda-on-a-mac-and-actually-get-it-to-work-53ce18025f97)

重要的事情先来

在你安装好所有东西后,任何时候你想启动 Jupyter 笔记本,你只需要打开你的终端并运行

jupyter notebook

你就可以开始工作了!

GIF via GIPHY

更改您的笔记本主题

人们想在 Jupyter 笔记本上改变的第一件事就是主题。人们为黑暗模式疯狂!这非常简单,你可以随时切换。

首先,转到您的终端并安装 Jupyterthemes

pip install jupyterthemes

现在你可以安装超级流行的黑暗主题

jt -t chesterish

随时使用恢复主题

jt -r

点击此处查找 Jupyterthemes GitHub 回购。

基本命令

  • 您可以使用命令选项板快速访问键盘快捷键。只需键入Ctrl + Shift + PCmd + Shift + P即可进入一个对话框,这很像 Mac 上的 Spotlight Search。它可以帮助你运行任何命令的名字,这是伟大的,如果你不知道键盘快捷键。

  • Shift + Enter让您运行当前单元格
  • Esc进入命令模式。现在你可以用箭头键在你的笔记本上导航了!

在命令模式下,使用

  • A在当前单元格上方插入新单元格
  • B在当前单元格下方插入新单元格
  • M将当前单元格改为降价
  • Y改回代码单元格
  • D + D删除当前单元格(按两次键)
  • Enter将您从命令模式带回到编辑模式

  • Shift + Tab将向您显示您刚刚在代码单元格中键入的对象的文档。(您可以持续按下此按钮在几种模式之间循环。)
  • Esc + F帮助你查找和替换代码中的信息(不是输出中的)
  • Esc + 0切换单元格输出
  • Shift + JShift + Down向下选择下一个单元格。Shift + KShift + Up向上选择单元格。选择单元格后,您可以批量删除/复制/剪切/粘贴/运行它们。当您需要移动笔记本电脑的部件时,这真是太棒了!
  • Shift + M允许您合并多个单元格。(如果你只是试图点击你想要工作的单元格,你会有麻烦。按住 shift 键并单击要合并的单元格。然后,在您仍然按住 shift 键的同时,按 m 键。)

  • 此外,如果在开头加上感叹号,您可以在笔记本中运行 bash 命令。例如:!pip install numpy
  • 您可以通过在最后一行代码的末尾添加分号来随时取消该函数的输出。

注释和取消注释代码块

您可能希望在工作时添加新的代码行并注释掉旧的代码行。如果您正在提高代码的性能或试图调试它,这是非常好的。

首先,选择您想要注释掉的所有行。

下一步点击cmd + /注释掉高亮显示的代码!

乳液

您可以随时在 Markdown 单元格中编写 LaTex,它将呈现为一个公式。

这改变了这一点

$P(A \mid B) = \frac{P(B \mid A)P(A)}{P(B)}$

变成这样

漂亮地打印所有单元格输出

通常只打印单元格中的最后一个输出。其他的都要手动添加print(),也可以但不是超级方便。您可以通过在笔记本顶部添加以下内容来进行更改:

from IPython.core.interactiveshell import InteractiveShellInteractiveShell.ast_node_interactivity = "all"

这意味着,虽然通常只打印一个输出

现在您将看到两个输出!

任何时候你想回到原来的设置,只要运行

from IPython.core.interactiveshell import InteractiveShellInteractiveShell.ast_node_interactivity = "last_expr"

请注意,您必须在单独的单元中运行设置更改,以使其在下一次单元运行时生效。

扩展ˌ扩张

因为它是一个开源的网络应用程序,已经为 Jupyter 笔记本开发了大量的扩展。你可以在这里找到官方的 iPython 扩展列表。这是另一个流行的扩展包。

您可以随时从命令行安装 Nbextensions,如下所示

pip

pip install jupyter_contrib_nbextensions
jupyter contrib nbextension install --user

或者用蟒蛇

conda install -c conda-forge jupyter_contrib_nbextensions
conda install -c conda-forge jupyter_nbextensions_configurator
jupyter contrib nbextension install --user

安装完成后,您会看到一个 Nbextensions 选项卡。继续探索!

点击这里阅读更多关于扩展的内容,以及如何启用、禁用它们,等等。

关于添加和启用扩展以及如何使用它们,我不会讲太多的细节,因为在你的 Jupyter 笔记本里已经有了很好的解释!只需点击屏幕顶部的“Nbextensions”,点击你感兴趣的扩展,然后向下滚动,找到你需要的信息和一个正在运行的扩展的 GIF!

流行的扩展

  • Scratchpad — 这太棒了。它允许您创建一个临时单元格来进行快速计算,而无需在工作簿中创建新的单元格。这是一个巨大的时间节省!
  • 腹地 —这将为代码单元格中的每次按键启用代码自动完成菜单,而不仅仅是使用 tab 键
  • 片段 —添加一个下拉菜单,将片段单元格插入当前笔记本。
  • Autopep8 —这是一个自动格式化 Python 代码以符合 pep8 风格指南的工具。太方便了!确保您已经在本地机器上运行了pip install autopep8 --user。这将确保您遵循正确的 python 编码约定。
  • 拆分单元格笔记本 —启用 Jupyter 笔记本中的拆分单元格。进入命令模式,使用Shift + S将当前单元格切换为拆分单元格或全角单元格。
  • 目录 —这个扩展使你能够收集所有正在运行的标题,并把它们显示在一个浮动窗口中,作为一个侧边栏,或者带有一个导航菜单。
  • 一个代码美化器— 清理、格式化和缩进你的代码,所以你不需要这么做。
  • Notify — 当您的内核空闲时,它会显示一个桌面通知。当您运行需要几秒钟以上才能完成的代码时,这是非常棒的。
  • 代码折叠— 在编辑模式下,一个三角形出现在装订线中,用于折叠您的代码。当你有大的函数需要隐藏以提高可读性时,这是个好方法。
  • 禅模式— 让事情变得不那么杂乱。确保关闭设置中的背景。

魔法

当你想执行特定的任务时,魔法是方便的命令,使生活变得更容易。它们通常看起来像 unix 命令,但都是用 Python 实现的。外面有一大堆魔法!

有两种魔法:线魔法(在一条线上使用)和单元格魔法(适用于整个单元格)。线条魔术以百分比字符%开始,单元格魔术以两个字符%%开始。要查看可用的魔法,请运行:

%lsmagic

设置环境

使用%env,你可以轻松管理笔记本的环境变量,而无需重启任何东西。如果您不带任何变量运行它,它将列出您的所有环境变量。

插入代码

您可以使用%load从外部脚本插入代码。(下面有更多这方面的内容,但它很棒,所以我把它加在这里)例如:

%load basic_imports.py

将抓取 basic_imports.py 文件并加载到您的笔记本中!

导出单元格的内容

这非常有帮助。几乎不费吹灰之力,你就可以用%%writefile随时导出单元格内容。例如

%%writefile thiscode.pyyou'd write some cool code or function in herethat you'd want to exportand maybe even use later!

您是否发现自己在每台笔记本上运行相同的导入或一直添加相同的功能?现在可以一次写,到处用!

您可以编写一个包含以下代码的文件basic_imports.py:

%writefile basic_imports.pyimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt

这将创建一个包含基本导入的. py 文件。

您可以随时通过编写以下内容来加载它:

%load basic_imports.py

执行此操作会用加载的文件替换单元格内容。

# %load imports.pyimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt

现在我们可以再次运行单元来导入我们所有的模块,我们准备好了。

存储和重用代码:%macro Magic

像大多数人一样,你可能会发现自己一遍又一遍地写着同样的任务。也许有几个方程你发现自己在重复计算,或者有几行代码你已经产生了无数次。Jupyter 允许你将代码片段保存为可执行的宏!宏只是代码,所以它们可以包含在执行前必须定义的变量。来定义一个吧!

比方说

name = 'Kitten'

现在,为了定义一个宏,我们需要一些代码来使用。我们可以保存几乎任何东西,从字符串到函数,或者你需要的任何东西。

print('Hello, %s!' % name)**Hello, Kitten!**

我们使用%macro%load魔法来建立一个可重用的宏。以双下划线开始宏名以区别于其他变量是很常见的。

%macro -q __hello_you 32

这个%macro魔术需要一个名称和一个单元号(或者数字),我们也传递了-q以使它不那么冗长。%store允许我们保存任何变量,以便在其他会话中使用。这里我们传递了我们创建的宏的名称,这样我们可以在内核关闭后或在其他笔记本中再次使用它。

要加载宏,我们只需运行:

%load __hello_you

为了执行它,我们可以运行一个包含宏名的单元格。

__hello_you**Hello, Kitten!**

Image by Ilona Ilyés from Pixabay

成功!

让我们修改我们在宏中使用的变量。

name = 'Muffins'

当我们现在运行宏时,我们修改后的值被选中。

__hello_you**Hello, Muffins!**

这是因为宏在单元格范围内执行保存的代码。如果name没有定义,我们会得到一个错误。

Image by Helga Kattinger from Pixabay

想要在所有笔记本上使用相同的宏吗?

商店魔术

%store允许您存储宏并在所有 Jupyter 笔记本上使用。

现在你可以打开一个新的笔记本,用%store -r __hello_you试试。把婴儿装上车,你就可以出发了!

%store -r __hello_you
name = 'Rambo'
%load __hello_you**Hello, Rambo!**

Image by Winsker from Pixabay

运行魔法

magic 将执行您的代码并显示任何输出,包括 Matplotlib 图。你甚至可以这样执行整个笔记本。

%run可以从执行 python 代码。py 文件。它还可以执行其他 Jupyter 笔记本。

Pycat 魔法

如果您不确定脚本中有什么,您可以随时使用%pycat来显示脚本的内容。

%pycat basic_imports.py

自动保存

这个魔术可以让你改变你的笔记本自动保存到检查点文件的频率。

%autosave 60

这将设置你每 60 秒自动保存一次。

显示打印图像

%matplotlib inline

你可能已经知道这个,但是%matplotlib inline会在你的单元格输出中显示你的 Matplotlib 绘图图像。这意味着您可以在笔记本中包含 Matplotlib 图表和图形。在笔记本的开头,也就是第一个单元格中运行这个是有意义的。

时机

有两个 IPython 神奇的命令对计时很有用— %%time%timeit。当您有一些缓慢的代码,并且您试图确定问题在哪里时,这些非常有用。它们都有行模式和单元模式。

%timeit%time的主要区别在于%timeit多次运行指定代码并计算平均值。

%%time会给你单元格内单次运行代码的信息。

%%timeit使用 Python timeit 模块,该模块运行一条语句无数次,然后提供结果的平均值。您可以使用-n选项指定运行次数,使用-r指定重复次数,等等。

从不同的内核运行代码

您也可以使用指定的语言执行单元格。有多种语言的扩展。你有如下选择

  • %%bash
  • %%HTML
  • %%python
  • %%python2
  • %%python3
  • %%ruby
  • %%perl
  • %%capture
  • %%javascript
  • %%js
  • %%latex
  • %%markdown
  • %%pypy

例如,要在笔记本中呈现 HTML,您可以运行:

%%HTML
This is <em>really</em> neat!

你也可以随时直接使用乳胶

%%latex
This is an equation: $E = mc^2$

谁会魔法

不带任何参数的%who命令将列出全局范围内存在的所有变量。传递一个类似于str的参数将只列出该类型的变量。所以如果你输入类似

%who str

在我们的笔记本里,你会看到

普伦魔法

%prun显示你的程序在每个函数上花了多少时间。使用%prun statement_name会给出一个有序的表格,显示每个内部函数在语句中被调用的次数、每次调用所用的时间以及函数所有运行的累计时间。

Python 调试器魔术

Jupyter 有自己的 Python 调试器接口。这使得有可能进入函数内部,看看那里发生了什么。您可以通过运行单元格顶部的%pdb来打开它。

高分辨率绘图

IPython magic 的一个简单行将为您提供 Retina 屏幕的双倍分辨率图形输出。请注意,这不会在非视网膜屏幕上呈现。

%config InlineBackend.figure_format ='retina'

跳过一个单元格不运行

只需在单元格顶部添加%%script false

%%script falseyou'd put some long code here that you don't want to run right now

提醒我

这实际上是 Python 的一个技巧,但是当你运行的代码需要花费很长时间时,你可能需要它。如果你不想整天盯着你的代码,但是你需要知道它什么时候完成,你可以让你的代码在完成的时候发出“警报”!

在 Linux(和 Mac)上

import os
duration = 1  *# second*
freq = 440  *# Hz*
os.system('play --no-show-progress --null --channels 1 synth %s sine %f' % (duration, freq))

在 Windows 上

import winsound
duration = 1000  *# millisecond*
freq = 440  *# Hz*
winsound.Beep(freq, duration)

为了使用这个,你需要安装sox,你应该能够做到

brew install sox

…假设你安装了自制软件。如果您还没有花时间定制和改进您的终端,您可能想看看这篇文章!

[## 在 10 分钟或更短时间内搞定你的终端

如何在短短几分钟内打造一个更好、更快、更强、更性感的终端

towardsdatascience.com](/trick-out-your-terminal-in-10-minutes-or-less-ba1e0177b7df)

现在玩得开心!

这应该足以让你开始!如果你知道任何你认为可以帮助其他初学者的技巧和诀窍,请在下面的评论中让每个人都知道。你在这里的选择是无限的!

如果你真的想让事情更上一层楼,你可能想看看这篇文章:

[## 优化 Jupyter 笔记本电脑—全面指南

根据我在过去一年中得到的一些提示,找到瓶颈并大幅提高速度。

towardsdatascience.com](/speed-up-jupyter-notebooks-20716cbe2025)

如果您对构建交互式仪表盘感兴趣,请查看这个:

[## 用 Jupyter 构建交互式仪表盘

欢迎来到“高级 Jupyter 笔记本技巧”的第二部分在第一部分,我描述了魔术,以及如何计算笔记本…

blog.dominodatalab.com](https://blog.dominodatalab.com/interactive-dashboards-in-jupyter/)

感谢阅读!如果你想接触或者找到更多很酷的文章,请来内容简约和我一起吧!

如何在你的 Azure 数据科学项目中嵌入安全性

原文:https://towardsdatascience.com/how-to-embed-security-in-your-azure-data-science-project-55ef3f2ab47?source=collection_archive---------13-----------------------

使用 Azure 数据块和 Azure 安全服务和技术

1.介绍

许多公司努力将他们的数据科学项目投入生产。在之前的博客中,讨论了如何为数据科学项目建立构建/发布管道。这使得公司能够 1)端到端地跟踪模型,2)建立对模型的信任,从而 3)避免模型预测令人费解的情况。

在每个构建/发布管道中,安全性都是一个重要的主题。常见的安全方面如下:

  • 对数据和端点的身份验证和授权
  • 数据和端点的网络隔离
  • 保险库中密钥的安全存储和密钥滚动过程

2020 年 9 月 17 日更新:本博客专用的博客和 gitrepo 不维护,不能 1 对 1 使用。不过,这些想法仍然有效。一个工作实例,见我之前的 博客

2.目标

在本教程中,将创建一个机器学习模型的构建/发布管道,用于预测一个人的收入阶层。在这种情况下,一个模型被构造成 Azure Databricks,然后这个模型被部署在一个 Web 应用中,这个 Web 应用充当 HTTPS 端点。构建/发布管道中包含以下安全方面:

  • 数据存储在 Azure Storage gen 2 中,服务端点指向 VNET
  • 密钥存储在密钥库中,密钥翻转是构建步骤的一部分。
  • Azure Active Directory 用于对 Web 应用程序进行身份验证
  • (可选)Web 应用程序是在 VNET 应用程序服务环境(ASE)中创建的

这可以在下面的体系结构概述中描述:

2. Architecture overview

在本博客的剩余部分,将执行以下步骤:

  • 3.先决条件
  • 4.创建机器学习模型
  • 5.在 Azure DevOps 中构建模型
  • 6.发布模型 Azure DevOps
  • 7.结论

这是一个独立的教程,但是,现在的重点将是安全性,而不是机器学习模型。如果你对 ML 更感兴趣,建议做以前的博客,这里或者使用 scikit-learn,这里看。

3.先决条件

需要在同一资源组和同一位置创建以下资源。

  • Azure CLI
  • 天蓝色钥匙金库
  • Azure Data 湖存储账户第二代
  • Azure Databricks 工作区。如果您想要在您的存储帐户上设置防火墙规则(请参见步骤 4d),请在自己的 VNET 中部署数据块,请参见此处的
  • Azure 机器学习服务
  • 蔚蓝 DevOps

4.创建机器学习模型

这一部分将执行以下步骤。请注意,尽可能使用 Azure CLI。

  • 4a。将存储密钥添加到密钥库
  • 4b。在 Azure 数据块中创建秘密范围
  • 4c。向存储帐户添加数据
  • 4d。(可选)存储帐户的网络隔离
  • 4e。在 Azure Databricks 上运行笔记本

4a。将存储密钥添加到密钥库

在此步骤中,使用 Azure CLI 将存储帐户的密钥添加到密钥库中。按如下方式复制密钥:

az login
az storage account keys list -g <<resource group>> -n <<stor name>>

现在,使用以下代码将存储帐户名称和存储帐户密钥添加到 Azure 密钥库中。建议在整个教程中使用相同的粗体名称,因为这些名称在 Azure DevOps 构建步骤中用作变量。确保用于登录 Azure CLI 的用户有足够的权限在密钥库中创建/列出/获取密钥。

az keyvault secret set -n **stor-key** --vault-name <<vault name>> --value <<stor key>>

4b。在 Azure 数据块中创建秘密范围

在数据块中创建 Azure Key Vault 支持的机密范围。这使得您可以将您的秘密存储在密钥库中,而不必再将密钥存储在笔记本中。将秘密范围命名为: devaisec

[## 秘密范围-数据块文档

管理机密从创建机密范围开始。秘密作用域由其名称来标识,在一个…

docs.azuredatabricks.net](https://docs.azuredatabricks.net/user-guide/secrets/secret-scopes.html#create-an-azure-key-vault-backed-secret-scope)

4c。向存储帐户添加数据

在您的电脑上从https://amldocker datasets . azure edge . net/adultcensus income . CSV下载数据文件。然后将数据添加到存储容器,如下所示:

az storage container create -n **dbrdata** --account-name <<stor name>>
az storage blob upload -f <<...\AdultCensusIncome.csv>> 
-c **dbrdata** -n **AdultCensusIncome****.csv** --account-name <<stor name>>

4d。(可选)存储帐户的网络隔离

只有当您在自己的 VNET 中部署了 Databricks 工作空间时,这一步才是可能的,参见此处。转到您的存储帐户,选择防火墙,然后添加您在其中部署了 Databricks 工作区的 VNET。

4d1. Add VNET to storage account

确保 Databricks VNET 的私有和公共子网都已添加到存储帐户的防火墙中。

4e。在 Azure Databricks 上运行笔记本

转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:

[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/1_IncomeNotebookExploration.py)1_incomeNotebookExploration_sec.py

用您自己的变量替换下列变量

storageAccountName = "<<stor name>>"                   #see step_3
azureKevVaultstor2Key = **"stor-key"** # see step_4a
secretScope = **"devaisec"** # see step_4b
storageContainer = **"dbrdata"** # see step_4c
fileName = **"AdultCensusIncome.csv"** # see step_4c

确保笔记本电脑可以连接的群集正在运行。可以使用默认设置创建集群。然后运行 notebook 来创建 ML 模型。

5.在 Azure DevOps 中构建模型

Azure DevOps 是一个工具,可以持续地构建、测试和部署你的代码到任何平台和云。需要完成以下工作:

  • 5a。在数据块中创建令牌
  • 5b。创建 Azure DevOps 项目并添加存储库
  • 5c。创建服务连接
  • 5d。向项目添加秘密变量
  • 5e。向项目添加其他变量
  • 5f。创建和构建管道

5a。在数据块中创建个人访问令牌

以编程方式访问 Azure 数据块需要令牌。进入 Azure Databricks,点击右上角的人物图标。选择用户设置,然后生成新令牌。

5a1. Generate Databricks Access Token

再次将密钥添加到 Azure 密钥库:

az keyvault secret set -n **dbr-token** --vault-name <<vault name>> --value <<token_id>>
az keyvault secret set -n **dbr-key** --vault-name <<vault name>> --value <<key value>>

另外,将 subscription_id 的值添加到密钥库中。

az keyvault secret set -n **subscription-id** --vault-name <<vault name>> --value <<subscription_id>>

个人访问令牌将作为构建管道的一部分进行滚动。

5b。创建 Azure DevOps 项目并添加存储库

按照这个链接创建一个新的 Azure DevOps 项目。创建新项目后,单击存储库文件夹并选择导入以下存储库:

[https://github.com/rebremer/devopsai_databricks.git](https://github.com/rebremer/devopsai_databricks.git)

5c。创建服务连接

从 VSTS 访问资源组中的资源需要一个服务连接。转到项目设置、服务连接,然后选择 Azure 资源管理器。

5c1. Go to Service Connection

选择服务主体身份验证,并将范围限制到您的资源组。将连接命名为devopsaisec _ service _ connection

5c2. Create Azure Resource Manager service connection

要从 Azure DevOps 管道配置密钥滚动,服务主体需要拥有对 Azure 密钥库的访问权限。因此,通过点击服务连接来查找服务连接的应用 id,然后选择“更新服务连接”,然后点击链接“使用服务连接对话框的完整版本”。

5c3. Application id of service connection

最后,授予服务主体对密钥库中机密的 set 权限(服务连接已经拥有 get 和 list 权限)。

az keyvault set-policy --name <<vault name>> 
--resource-group <<resource group>>
--secret-permissions get list set 
--spn <<application id>>

5d。向项目添加秘密变量

在步骤 4a 中,存储密钥被添加到 Azure 密钥库中。随后,在步骤 5a 中添加了 Databricks 访问令牌和 subscription_id。

我们的 Azure DevOps 项目需要这些秘密。因此,单击库并选择将 Azure Key Vault 中的机密链接到项目。选择在步骤 5b 中创建的服务连接和存储机密的密钥库,然后单击 authorize。

5c1. Authorize to key vault

最后,将秘密变量“dbr-key”、“dbr-token”和“subscription-id”添加到项目中,然后单击 save。

5e。向项目添加其他变量

除了秘密变量,Azure DevOps 项目运行还需要其他配置。同样,转到库,允许访问所有管道,并使用您自己的值作为组添加以下变量:

**amls-name**         <<azure ml_service name>>
**dbr-secretscope**   **devaisec** <<see step_4b>>
**dbr-url**           <<dbr_url, <<your region>>.azuredatabricks.net>>
**rg-name **          <<resource group>>
**stor-container **   **dbrdata** <<see step_4c>>
**stor-name  **       <<store name>>
**keyvault-name **    <<vault name>>

5e1. Create secret variable group to be used in project

5f。创建和构建管道

在这一步中,将创建构建管道。单击“管道”,选择“新建”,然后选择“新建管道”。保留默认值,然后单击“继续”。在下一个屏幕中,选择“配置为代码”并单击“应用”。

选择作为代理池以拥有“托管的 Ubuntu 1604”并选择作为文件路径:project/config code _ build _ sec . yml。然后单击保存,另请参见下面的屏幕

5f1. Configuration as code

最后,链接前面创建的秘密变量组。因此,单击变量组,链接 5d 中创建的秘密变量组和 5e 中的其他变量组,并单击保存和队列开始构建。

5f2. Link variables group to build pipeline and build

成功执行 run 后,您可以看到构建、首次运行和最终结果。

5f3. Succesfull build

在这个构建管道中,执行以下步骤:

  • 通过运行 notebook 使用 Azure Databricks 创建模型。
  • 从将在发布步骤中部署的模型创建 docker 映像
  • 执行 Databricks 令牌的密钥翻转,以最大限度地降低风险
  • 创建用作发布管道输入的构建工件

6.Azure DevOps 中的发布模型

下一部分是关于创建一个发布管道。在这种情况下,它将机器学习模型部署为 web 应用程序上的容器。

  • 6a。(可选)创建应用服务环境
  • 6b。创建 web 应用和应用服务计划
  • 6c。创建发布管道
  • 6d。将容器部署到 web 应用程序
  • 6e。在 web 应用中启用 Azure Active Directory 身份验证
  • 6f。在 Postman 中设置对 web 应用程序的身份验证

6a。(可选)创建应用服务环境

为了实现对您的 web 应用程序的完全网络隔离,应使用应用程序服务环境。在应用服务环境中部署的所有 web 应用和应用服务计划。

[## 使用应用服务环境 Azure 创建内部负载平衡器

关于如何创建和使用互联网隔离的 Azure 应用服务环境的详细信息

docs.microsoft.com](https://docs.microsoft.com/en-us/azure/app-service/environment/create-ilb-ase)

请注意,应用服务环境的成本可能很高。本教程的其余部分也可以使用未部署在私有 ASE 中的 web 应用来完成,但是,web 应用将拥有一个公共 IP。

6b。使用 Azure CLI 创建 web 应用程序

执行以下命令行在 linux 中创建 Azure web。

az appservice plan create -g <<resource group>> -n devaisec-plan --is-linux --sku S1
az webapp create -n devaisec-app -g <<resource group>> 
-p devaisec-plan -i elnably/dockerimagetest

6c。创建发布管道

在这一步中,容器被部署到 web 应用程序。转到“Pipelines”,选择“Releases”,然后选择“empty job”作为模板。更改名称,然后单击保存。

6c1. Create release pipeline

添加您想要在此管道中发布的工件。在这种情况下,选择从构建管道中创建的工件。确保您始终选择默认版本:最新

6c2. Add release artifact

最后,将两个变量组(在步骤 5c 和 5d 中创建的)也添加到发布管道中。转到发布管道中的变量,并链接两个组,就像在构建管道中所做的那样。

6d。将容器部署到 web 应用程序

转到发布管道并选择添加任务。然后,您将看到一个包含代理作业的屏幕。同样,您需要将代理池更改为 Hosted Ubuntu 1604。

6d1. Agent pool Ubuntu 1604

随后,通过搜索 Azure CLI 添加新任务。选择devopsaisec _ service _ connection作为服务连接,引用“41_deployImageToWebapp_sec.sh”作为脚本路径。然后通过引用变量$(rg-name)使用以下 3 个由空格分隔的参数:webapp 的名称、容器注册表的名称和资源组的名称。

6d2. Azure CLI to deploy container to web app

保存并关闭,然后选择创建发布管道。填写变量以创建发布。然后通过点击 deploy 按钮来部署发布。等待 5 分钟,然后检查状态是否从“未部署”变为“成功”。

6e。在 web 应用中启用 Azure Active Directory 身份验证

在此步骤中,使用 Azure 门户在 web 应用中启用 Azure Active Directory 身份验证。转到您的 web 应用,选择身份验证/授权,然后选择 Azure Active Directory。然后选择快速并使用与您的 web 应用程序相同的名称创建新的应用程序注册

6e1. Set up AAD authentication in web app

在此步骤之后,web 应用程序 URL 需要身份验证,并且不能被使用。

6f。在 Postman 中设置对 web 应用程序的身份验证

最后一步是设置工具邮差来验证网络应用。在下面的教程中,解释了如何做到这一点。

在 Postman to the 应用程序中设置 Postman 和客户端身份验证后,可以使用 HTTPS 端点来创建预测。可以在项目中的项目/services/50_testEndpoint.py 中找到一个示例负载。在本例中,预测了三个人的收入等级。

  • 对第一个人的预测是收入高于 50k,
  • 对于另外两个人,预测值低于 50k。

6f1. Postman with bearer authentication to consume API for predictions

7.结论

在本教程中,将为机器学习项目创建一个安全的端到端管道。在这个项目中,Azure Databricks 被用来创建一个机器学习模型,并将其作为一个端点部署在一个 web 应用程序上。端到端管道的保护如下:

  • 使用 Azure Active Directory 对 Web 应用程序进行身份验证和授权
  • 存储帐户和 Web 应用程序的网络访问控制列表
  • 在 Azure 密钥库中安全存储密钥,并在构建管道中添加密钥滚动过程

这使公司能够 1)端到端地跟踪模型,2)建立对模型的信任,3)避免模型预测莫名其妙的情况,最重要的是 4)使用 AAD、VNETs 和密钥库保护数据、端点和秘密,另请参见架构概述:

7. Architecture overview

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

如何工程贝叶斯比率特征?

原文:https://towardsdatascience.com/how-to-engineer-bayesian-ratio-features-548b9862446b?source=collection_archive---------32-----------------------

这样我们的机器学习模型就可以区分 1 / 2 和 50 / 100。

Photo by Jeffrey F Lin on Unsplash

假设我们想要建立一个机器学习模型来预测足球点球大战的获胜者。在我们拥有的关于不同足球运动员的数据中,有点球得分点球未遂。遵循传统智慧,我们设计了这个特征

*penalty_success_rate* = *penalties_scored* / *penalties_attempted*

然而,由于点球和点球决胜并不经常发生,我们对这一新功能有以下问题:

  • 有些球员从来没有罚过球,所以他们的点球成功率是不确定的。
  • 对于之前正好罚过一次的玩家,他们的 penalty_success_rate 不是 100%就是 0%。这两个数字都不能反映球员获得下一个点球的概率,并且会误导我们的机器学习模型。(作为参考,世界杯点球大战的平均点球成功率约为 70% )
  • 当我们用新数据更新 penalty_success_rate 时,对于只接受了几次处罚的玩家来说,这些值可能会大幅波动。例如,如果一名球员罚进了第一个点球,但错过了第二个,他的特征值将从 100%大幅下降到 50%。这可能会导致模型性能不稳定。
  • 最后,我们希望我们的特征考虑成功率证据的强度。2 分之 1 的记录仍然属于一个非常好的点球手,但是一个 100 分之 50 的记录的球员几乎肯定不擅长点球。但是 penalty_success_rate 的公式对两种情况都给出了 50%,无法区分。

贝叶斯方法

贝叶斯统计解决了上述所有问题。天真地说,在贝叶斯框架内,首先给玩家一个初始特征值,对应于我们关于玩家的先验知识。然后当我们接收到新的数据时,我们逐渐更新特征值。只有当我们接收到足够多的数据时,新值才会与初始值有很大的偏差。

我们的贝叶斯特征的公式是

*bayesian_penalty_success_rate* = (*penalties_scored* + α) / (*penalties_attempted* + α + β)

其中α和β是我们需要选择的超参数。直觉上,我们可以把α和β理解为我们分别给予点球得分和罚失的“领先”数量。

公式的动机

因为我们只关心点球是进了还是没进(而不是怎么进的),所以我们可以用二项式分布来模拟结果。然后,用贝塔分布来模拟球员得分的概率是自然和方便的,贝塔分布是二项式似然函数的共轭先验。

上面的公式是贝塔分布的平均值

Beta(*penalties_scored* + α, *penalties_missed* + β)

其中点球 _ 未进 = 点球 _ 未遂 - 点球 _ 进球

具体的例子

让我们选择α = 7,β = 3,并考虑一个之前从未罚过球的球员。

  • 最初,处罚 _ 得分处罚 _ 未遂均为 0。因此
    贝叶斯 _ 惩罚 _ 成功率 = (0 + 7) / (0 + 7 + 3) = 0.7
  • 假设我们的玩家第一次罚分:
    Bayesian _ penalty _ success _ rate=(1+7)/(1+7+3)≈0.7272
  • 然后我们的玩家错过了她的第二次惩罚:
    贝叶斯 _ 惩罚 _ 成功 _ 率 = (1 + 7) / (2 + 7 + 3) ≈ 0.6667
  • 最后,假设我们的玩家最终的总战绩是 100 分中的 50 分:
    贝叶斯 _ 惩罚 _ 成功率 = (50 + 7) / (100 + 7 + 3) ≈ 0.5182

我们看到Bayesian _ penalty _ success _ rate总是定义良好。它的值在收到新数据时会逐渐变化,并且它需要强有力的证据来证明该值明显偏离初始值。

如何选择α和β

  • 贝叶斯 _ 惩罚 _ 成功率的初始值为α / (α + β)。我们可以选择α和β,使得α / (α + β)等于全局平均惩罚成功率。这对应于用平均值替换缺失值的常见做法。

在满足上述等式的所有对(α,β)中,我们可以使用以下方法选择一对:

  • 查看 beta 分布的不同百分位数,看看它们是否与你的领域知识相匹配。
  • 决定多少数据算作强有力的证据。例如,假设我们做了一些探索性的数据分析,发现前 5 个点球得分的球员最终职业生涯点球成功率都在 82%以上。因此,我们可能希望选择α和β,使
    (5 + α) / (5 + α + β) >为 0.82
  • 对数据进行聚类,看看是否有解释聚类的α和β。例如,如果 3 个记录中有 2 个,7 个中有 5 个,11 个中有 8 个的玩家表现出相似的特征,我们可以选择α = 7,β = 3,分别产生特征值 0.6923,0.7059 和 0.7143。

一般来说,较小的α和β意味着我们的先验知识较弱,新数据将对β分布产生较大影响,从而影响我们的特征值。

一个具体的例子

  • 首先,我们希望α / (α + β) = 0.7,这是世界杯点球大战中的平均点球成功率。

在所有满足α / (α + β) = 0.7 的不同值中:

  • 对于α= 70 °,β= 30 °,β(70,30)的第一百分位是 0.5887。这转化为一个先验知识,即,有 99%的可能性,我们的球员的下一个点球得分的概率至少是 58.87%。这对一个从未罚过球的球员来说似乎太高了。因此,我们将拒绝这一对价值观。
  • 对于α = 7,β = 3,β(7,3)的第 1 和第 99 百分位分别为 0.3437 和 0.9467。这意味着有 98%的可能性,我们的玩家的概率在 34.37%和 94.67%之间,这比上面说的有意义得多。

另外,我们希望(5 + α) / (5 + α + β) > 0.82,因为关于球员前 5 个点球全部进球的探索性数据分析。

  • 对于α = 7,β = 3,(5 + 7) / (5 + 7 + 3) = 0.8 小于我们想要的。
  • 对于α = 3.5,β = 1.5,(5 + 3.5) / (5 + 3.5 + 1.5) = 0.85 满足我们的条件。

快速检查一下β的百分位数(3.5,1.5)看起来也不错,所以我们将选择α = 3.5,β = 1.5。

备注:通常有很多对(α,β)满足我们的条件。通常,它们的相关特征以类似的方式对我们的机器学习模型做出贡献,所以我们可以简单地选择其中一个。

常见问题

问:α和β必须是整数吗?

答:不需要。唯一的要求是它们是正实数。

问:我们可以为不同的玩家选择不同的α和β吗?

答:是的。回想一下,α和β定义了描述我们先验知识的β分布。很可能我们对不同的球员有不同的先验知识,例如前锋通常擅长点球,而后卫则不然。

问:上面的贝叶斯特征公式使用了 beta 分布的平均值。我们可以使用其他统计数据(如标准差)来定义新特征吗?

答:是的。我们可以很容易地在维基百科上找到这些公式。

问:如果我们已经在我们的机器学习模型中使用 penalty_success_ratepenalty _ scored、penalty _ attempted,那么创建这个贝叶斯特征是否有益?例如,为了区分 1/2 和 50/100,我们的模型可以简单地使用 penalties_scored 特性。

答:是的,这样做还是有好处的。假设我们开始时只有两个特征罚分 _ 得分罚分 _ 未遂。即使一个足够复杂的模型可以做除法,我们仍然会设计 penalty_success_rate 特性来使我们的模型学习得更好。工程我们的贝叶斯特征是一样的。

进一步阅读

  1. 这是一篇以棒球为例的关于 beta 发行版的博文。
  2. 威尔逊评分区间也可用于对小样本量的成功概率进行良好的估计。

如何评价 B2B 行业营销对销售的整体影响?🤑

原文:https://towardsdatascience.com/how-to-evaluate-marketing-in-the-b2b-retail-industry-5a183510006?source=collection_archive---------29-----------------------

Photo by Merakist on Unsplash

#营销# b2b #数据科学#归属#购买行为

本文旨在解决 B2B 行业的营销归因问题,其中客户有购买频率(家具,it 材料等)。

营销归因

如果你是 B2B 行业的营销人员,你可能很难找到正确的指标来评估你的活动对销售的影响。有时营销活动可以促进销售,有时可以向销售团队介绍新客户,有时客户会直接致电销售团队,而不会受到任何营销活动的激励。

处理这种销售和营销与客户互动的大熔炉的一个众所周知的方法是利用渠道&由机会产生的收入,这些机会开始于通过营销活动中的行动号召产生的线索。这些都是很好的指标,但是您可能想要创建新的指标来查看整体情况,例如对客户群销售的支持和协助。这是为什么呢?因为,你可能错过了一部分你也影响了的收入和渠道,这一部分可能是巨大的。

让我解释一下,在某些时候,潜在客户会转化为分配给销售代表的客户。因此,在一次活动中,每当向他们发出行动呼吁时,他们可以:

  • 转换并进入营销漏斗,将他们重新引导到一个队列中,有望引导到他们的销售代表。
  • 直接打电话给他们的销售代表。

简而言之,如果您使用每当客户或潜在客户点击您的活动行动号召时创建的线索标识符来评估营销对销售的影响,那么您主要是在评估您的部门将新的潜在客户转化为客户的能力。

影响管道&收入

T 这些是基于归因问题的旅程方法的简单指标,旨在描绘营销可以获得信贷的机会。

A simple attribution model

上图所示的方法在一定程度上运行良好。如果客户流失,去购买他的竞争对手的家具,然后决定再次购买你的业务,下面的错误归因问题将会发生。

A simple representation of the attribution problem

在上图中,你可以清楚地理解我们正在处理的问题:每当在与你的活动进行一次或多次互动后产生管道,你都会将其归因于营销努力,即使这没有意义。

每个客户都有自己的购买频率,如果你能接近它,你就知道在客户层面上,将机会归因于之前的营销活动是否有意义。

为您的机会创建受影响的标志(python 语言)

1.导入库

2。负载

首先,从 salesforce 或任何其他 B2B CRM 加载所有已关闭的机会。在这些字段中,您只需要三个字段:客户 id、机会 id、结束日期(如果您在此字段中有许多 NAs,您可以用最后修改日期来替换它们😉).

3。计算购买频率

您可以通过计算帐户级别的连续机会之间的时间范围来计算购买频率。

你应该保留每个客户的第一次机会。我们当时对客户知之甚少,因此我们无法知道机会的创造是否受到营销的影响(我们可以,但不是使用这种方法,而是使用线索生成分析),他可能与营销活动互动过多次,目的是创造机会,但最终在您的企业为他创造第一个机会之前就去了竞争对手那里。根据您的关注点,我们将在后面看到如何处理这些问题。

现在,从这些时间范围,你可以使用 K 均值算法,推断出一些关于你的人口购买行为的有趣行为。

4。找到拟合数据的最佳聚类数&

K-means 算法是无监督的模型,它从一维或多维(结构化)数据中形成组。核心概念是根据两个规则形成组:

  • 每个点到其聚类质心的距离被最小化。
  • 这些点到其他簇的质心的距离被最大化。

为了找出你应该形成多少个聚类,你可以计算一个聚类数范围的 SSE (误差平方和= >点到它们的组均值的距离)和/或剪影分数。

一旦找到了最佳的聚类数,就可以训练模型,确保多次运行拟合过程,并选择 SSE 最低的版本,否则您的算法可能会收敛到局部最优。完成后,您可以预测每个计算时间范围的聚类。

为了让定义每个聚类的值具有完整的意义,我们应该根据它们的平均值对它们进行重命名。聚类“0”应该是包含较慢购买频率的聚类,而聚类“k”应该是包含最快购买频率的聚类。

5。在账户级别标记购买频率群的变化

在客户层面,在连续的机会之间,购买频率群变得更慢是一个时期流逝的迹象。

对于每个客户,您可以在失效期后的第一个机会上轻松标记失效期(也就是从一个集群到另一个集群的变化,由连续机会之间较慢的平均购买频率定义)。

6。创建一组临时的假数据点来表示错过的转换

为了避免出现的错失归因问题,你可以利用目前收集的信息,创建一组与错失机会相对应的虚假记录。为此,您只需选择所有被标记的机会,并将它们的购买频率分别除以最后一个机会的聚类平均购买频率,这将为您提供在逝去期间错过的机会的近似数量。

对于每个标记机会,迭代错过的转换数,每次增加在先前机会日期的数据集中错过的转换的新观察,加上其分类的平均购买频率乘以迭代器索引。为所有创建的错过的机会分配一个唯一的机会 id。

7。处理客户的首次机会

您可以在每个帐户的第一个机会放回。根据分析结果,您还可以假设您无法理解第二次销售之前的任何购买行为,将他们排除在分析之外,并使用其他指标来评估营销能力,以转化新的潜在客户。如果你这样做,不要忘记正确过滤你的营销数据集。

8。将受影响的标志映射到机会

引入营销参与数据,并将其叠加到机会数据集中。按客户和日期对数据集进行排序,并在客户级别向后传播机会 id。

此外,禁止错过机会和机会结束日期与其结束日期之间的约定。正如图中所示,这些业务可能会引入有偏见的归因,这是归因问题的一个简单表示。

根据机会 id 进行分组,如果您获得的观察数量大于 1(则您在机会之前有营销互动),您可以将标志“受影响”归属于该机会。

现在,对于每个机会,您都有一个标志,可以用来评估受影响的渠道和收入。

您可以在我的 Github 上找到本文中的所有代码。

最后的想法

在提议的实现中,我使用了机会结束日期,假设结束日期和创建日期相对接近。虽然在某些行业可能是这样,但并不是所有行业都是这样。如果您的业务机会结束日期和创建日期相差很远,一个解决方案是将结束日期用于除步骤 8 之外的所有流程,在步骤 8 中,您可以在(实际)业务机会中更改创建日期的结束日期。

如果您觉得这很有趣,并且有一些改进的想法,请联系。总有改进的余地。

如何评估潜在客户-数据科学成熟度

原文:https://towardsdatascience.com/how-to-evaluate-potential-clients-data-science-maturity-bd4714920988?source=collection_archive---------24-----------------------

可操作的清单✅

Photo by Amogh Manjunath on Unsplash

好消息!数据科学技能的市场过去是,现在是,而且很可能会继续是非常好的。

在供给方面,训练营和 MOOCs 正在彻底改变教育,并将继续让众多来自不同背景的人才分享数据经济的战利品。从博士项目出来的聪明的学术头脑有一个奇妙的和真实的机会来建立改变生活的商业解决方案。

你是这样的一个人吗?你在寻找新客户吗?从新雇主开始?小心——寻找正确的事情,以确保该项目将是一个成长、贡献的机会,并且是一个值得骄傲和满意地回顾的事情。你的环境是决定你轨迹的一个极其重要的因素。

随着应用数据科学在商业上的成功,该领域吸引了相当程度的宣传,这是很自然的,不幸的是,这反过来又导致了各种不良后果。对于希望培养或雇佣人才的组织来说,这通常意味着筛选态度或准备有问题的候选人。对于数据科学专业人员—与缺乏组织准备和数据科学成熟度的客户或雇主打交道。这篇文章旨在帮助专业人士评估组织。

症状🤕

它们有各种各样的风格——从战略和文化的,到实际的。它们会是什么呢?

过度“利用 AI 和机器学习”,只在 PowerPoint 幻灯片上?“这将是一项巨大的人工智能计划”,尽管没有人知道如何实现,或者是否真的需要人工智能?
也许是“带后缀另存为”这种古老的版本控制技术?
你坐在椅子上的时间比你交付的东西更有价值?
数据管理和数据质量缺乏流程?
可怕的临时隐私保护措施不起作用,反而会减慢工作速度?每个项目都从编写相同的低级例程开始?
定制 CSV 阅读循环?
以 Excel 和电子邮件为中心的工作流程?
Python 2.6?

是的,这是一些症状。问题是,在你开始之前,或者之后相当长一段时间,你都不会看到很多。那是除非你仔细看。

Photo by Drew Coffman on Unsplash

请注意,风险很高。一个无心的错误判断很可能导致一个有着花哨头衔的实习生的不稳定地位。其职责包括全栈开发、监督部署,以及定期帮助同事解决 Excel 格式问题。也不学习。滚出我的草坪!

另一方面,期望客户尽善尽美的态度是不合理的,总有一些需要补充和改进的地方。努力弄清楚是你的责任。培养有益的习惯和过程是你的责任。这包括为改善你的环境做出贡献。

但是你做你的工作的条件存在吗?你将承担什么额外的任务?你想接受他们吗?他们让你走上了你想要的学习轨道吗?你一天、一周、一年的大部分时间都在工作。工作应该充满乐趣和自豪感——这取决于你,而不是其他任何人。话虽如此,你需要一定的条件。大多数公司都有合规流程。为什么没有自己的呢?

让我通过一些测试和问题来了解情况。

Photo by Glenn Carstens-Peters on Unsplash

清单

  1. 策略。公司有战略吗?他们是否有特定的目标来使自己处于持久的优势?他们有可行的成果计划吗?他们是否清楚地表达了他们期望团队和你在未来 6 个月或 12 个月内取得的成果?
    对此要非常小心。没有明确性或战略就意味着没有责任和高度的不确定性,这将导致压力或听天由命的态度。那是你最不想要的。更不用说那些无聊的会议和计算时间而不是计算进度了。尊重你的时间。
    我倾向于问的一个问题已被证明是调查的一个很好的切入点,这个问题有以下几种:“假设您决定与我合作,我们的项目已经进行了 6 个月,您对我的参与感到非常高兴和满意。我为帮助我们成功做出了哪些贡献?”
    寻找答案的清晰性和具体性,并提出后续问题。
  2. 期望和领导力。你未来的团队要么必须对你的贡献有明确的期望,要么他们希望你积极参与工作的安排和领导。警惕混乱和移动目标。你要明确期望和超额交付,以建立信任和成功。再说一次,你不想为了展示(表面上的)奉献而在办公室里花费最多的时间——你想要交付成果。
  3. 文化。你想和一群渴望自己和周围人成功的人在一起。这意味着他们没有时间参与政治。他们不会尊重无用功。他们会以高度的正直来交付坚实的工作,并感谢你也这样做。你会为你所做的感到骄傲,对你所学到的心存感激,并且会和优秀的人建立良好的关系。
    三思而后行,问问他们最自豪的成就是什么,或者他们在这个项目中从同事那里学到的最重要的一件事是什么。看看他们看待他人和与他人互动的方式。
  4. 灵活性。这个是面向员工/顾问的。你从事的是创造性职业,这应该是谈话的一个起点。应该根据你的产出的质量和数量以及你对他人的积极影响来评估你。自然,在初始阶段与团队面对面交流并了解每个人是很重要的。也就是说,正确的灵活性会大大提高你对生活的满意度,而不会对工作效率产生任何负面影响。这是值得谈判的——你再也不会拥有你生命中那些美好的岁月了。了解典型的一周是什么样的,并尝试收集有人展示灵活文化时的故事。
  5. 技术堆栈和变更流程。 非古风科技栈。你想聪明地工作,这里的关键是获得适合工作的好工具。您知道工具和行业实践都在不断改进和完善。新的框架也正在发布。负责任的和有效的变更管理是一个很大的话题,但是你至少要对两个场景有个感觉,这两个场景会非常直接地影响你的日常生活。
    第一个是你的个人编码环境——例如,安装你最喜欢的代码编辑器有多容易?您的环境中有什么级别的访问权限?这要么很容易,要么很麻烦。
    其次——询问主要依赖项更新是什么样的,需要多长时间,以及进行了哪些验证工作。它会告诉你很多关于组织发展速度的信息。
  6. 个人适合。一定要见你的直接联系人或经理。他们对你的工作被看待和接受的方式有很大的影响,也对你的日常生活有很大的影响。不是你的房东,也不是你的丈母娘,不过是类似类型的交易!理想情况下,他们应该渴望并自豪地分享他们如何让同事发展和成长的故事。相信你的直觉!

我会注意到,与你的客户的关系是不断变化的,当你把自己树立为一个值得信赖和有价值的贡献者时,你可能会获得灵活性,以及对文化和战略的影响力。一开始就推迟大的需求是合理的,但也要注意几个月后机会的总体水平,让它在你的决策中发挥作用。

Photo by Brian Metzler on Unsplash

结论

如果机会没有勾选所有的框,但是因为其他原因非常令人兴奋呢?如果你有推动工作的外部压力怎么办?

专注才是王道。专注于能带来结果的行动,并以此为杠杆引导每个人走向更好的境地。至少,在下一个项目开始之前,你已经贡献了一些有意义的东西。

我希望这个清单有助于你的成功。祝你好运!

感谢亚历克斯·格雷斯、 马頔·谢尔巴科夫*米哈尔·马祖雷克 的建议和点评。*

如何向烹饪过的人解释机器学习项目的组成部分

原文:https://towardsdatascience.com/how-to-explain-the-components-of-machine-learning-projects-to-anyone-whos-ever-cooked-8ce7af4050e1?source=collection_archive---------10-----------------------

作为制药行业的机器学习团队负责人,我经常发现自己在教育非技术受众关于机器学习项目如何工作。这种对烹饪的类比确实引起了人们的共鸣,并帮助他们理解了主题专业知识、质量数据、数据工程的作用和重要性,以及为什么将一个成功的概念验证投入生产需要这么长时间!

我希望这有助于你理解或向他人解释机器学习项目!

事不宜迟,这里有一个抓住这个故事的执行幻灯片:

Source of Pasta Image

数据=配料

成分和数据就是原材料。与流行的说法一致,垃圾进来,垃圾出去,如果原料(数据)腐烂和滋生,就无法使最终结果可口。

数据工程=配料准备

烹饪的大部分时间都花在准备和加工食材上,这一事实会引起任何在厨房里伸出援手的人的共鸣。数据工程也是如此。我们有了特征工程、数据清理和标准化,而不是烹饪的切片、腌泡和剁碎。

机器学习算法=烹饪技术

在大多数情况下,这些事情只是自己发生
一个生土豆+一壶开水+ 15 分钟=软土豆。
标记数据+ logistic 回归+ 15 分钟=系数和优势比。

当然,了解食材和技术的厨师(和 ML 从业者)对好的结果至关重要。

硬件和软件架构=炊具和器皿

不同的问题需要不同的工具和不同尺寸的工具。

一份两人份的舒适食谱需要不同的技能和设备,而不是满足 2000 人的需求。同样,处理 1,000 行数据或文档可能在一台笔记本电脑上运行,但处理 10 亿行可能需要专门的分布式编程语言和服务器。

领域专长=主厨专长

其实第一次业余都可以做饭!

Source

也就是说,有专业厨师来烹饪或至少提供建议会大大改善任何菜肴。同样,拥有专业知识可以极大地改善机器学习项目和产品。

这里实际上有两种类型的专业知识——业务领域(例如,金融市场、临床路径)和技术领域(例如,自然语言处理)。最成功的项目需要两类专家之间的密切合作。

~~~内部技术团队的插头~ ~ ~

如果你在一家大公司工作,那里对机器学习的需求和依赖不断增长,以帮助业务增长或扩大,投资内部人才至关重要。将每一个机器学习项目外包给第三方供应商,就像一家餐馆将每一单订单外包给其他餐馆一样。它成本高、速度慢、不灵活,并且缺乏一致性和可扩展性。

临时演员

可以得出许多额外的类比。如果有兴趣,我可以写第二篇文章来扩展这些概念:
项目/平台通常是由单个组件组成的,就像一道菜是中间熟的或生的配料的组合。
获取数据可能是一件苦差事,就像从各种供应商处采购高质量的原料可能在物流方面具有挑战性一样。
在云中操作就像租用厨房(或特定的器具、炉灶、冰箱等)。)点播。
API 是服务员:【https://www.youtube.com/watch?v=s7wmiS2mSXY】T4

使用 Python 浏览和可视化数据集

原文:https://towardsdatascience.com/how-to-explore-and-visualize-a-dataset-with-python-7da5024900ef?source=collection_archive---------4-----------------------

或者如何学习用 Python——一个代码向导——创建漂亮而有洞察力的图表

在上周的故事“用 Python 从各种工作表中提取数据”中,您了解了如何从不同来源(Google Sheets、CSV 和 Excel)检索和统一数据。这两个故事都是独立的故事,所以如果你跳过了上周的那篇,也不用担心。

[## 用 Python 从各种工作表中提取数据

或者如何学习统一 Google 工作表、Excel 和 CSV 文件——代码指南

towardsdatascience.com](/replacing-sheets-with-python-f1608e58d2ca)

在今天的故事中,你会学到:

  • 如何组合和争论数据,
  • 如何探索和分析数据,
  • 如何创建漂亮的图表来可视化您的发现

这篇文章是写给谁的:

  • 经常与数据打交道的人
  • 对 Python 和熊猫有基本了解的人

概述一下情况:

你的任务是找出如何提高你的销售团队的业绩。在我们假设的情况下,潜在客户有相当自发的需求。发生这种情况时,您的销售团队会在系统中输入一个订单线索。然后,您的销售代表会尝试在订单线索被发现时安排一次会议。有时在之前,有时在之后。你的销售代表有一个费用预算,并且总是把会议和他们付钱的一顿饭结合在一起。销售代表报销他们的费用,并将发票交给会计团队处理。在潜在客户决定是否接受你的报价后,勤奋的销售代表会跟踪订单线索是否转化为销售。

对于您的分析,您可以访问以下三个数据源:

  • order_leads (包含所有订单线索和转换信息)
  • sales_team (包括公司和负责的销售代表)
  • 发票(提供发票和参与者的信息)

导入和设置:

使用的库相当标准。但是,您可能需要在笔记本中运行以下命令来安装 seaborn。

!pip install seaborn

加载数据:

你可以下载并组合上周文章中展示的数据,也可以从这里下载文件并把它们载入你的笔记本。

first two rows of sales_team Dataframe

first two rows of order_leads Dataframe

first two rows of invoices Dataframe

让我们开始探索:

总体转换率发展:

Conversion rate development over time

显然,事情似乎在 2017 年初开始走下坡路。在与首席销售官核实后,发现大约在那个时候有一个竞争对手进入了市场。很高兴知道,但是我们现在在这里什么也做不了。

  1. 我们使用下划线_作为临时变量。我通常会对那些我以后不会再使用的变量这样做。
  2. 我们在order_leads.Date上使用了pd.DateTimeIndex,并将结果设置为索引,这允许我们
  3. 使用pd.Grouped(freq='D')将我们的数据按天分组。或者,您可以将频率更改为 W、M、Q 或 Y(表示周、月、季度或年)
  4. 我们计算每天“已转换”的平均值,这将给出当天订单的转换率。
  5. 我们使用.rolling(60).mean()来获得 60 天的滚动平均值。
  6. 然后,我们格式化 yticklables,使它们显示一个百分号。

销售代表之间的转换率:

看起来销售代表之间存在相当大的差异。让我们对此进行更深入的调查。

就所使用的功能而言,这里没有多少新东西。但是请注意我们如何使用 sns.distplot 将数据绘制到轴上。

如果我们回忆一下 sales_team 数据,我们会记得并非所有销售代表都有相同数量的客户,这肯定会有影响!让我们检查一下。

Distributions of conversion rates by number of assigned accounts

我们可以看到,转换率数字似乎与分配给销售代表的客户数量成反比。转换率下降是有道理的。毕竟,销售代表拥有的客户越多,他花在每个客户身上的时间就越少。

这里,我们首先创建一个助手函数,它将把垂直线映射到每个子图中,并用数据的平均值和标准偏差来注释这条线。然后我们设置一些 seaborn 绘图默认值,比如更大的 font_scale 和 whitegrid 作为 style

膳食的影响:

sample meals data

看起来我们已经有了吃饭的日期和时间,让我们快速看一下时间分布:

out:
07:00:00    5536
08:00:00    5613
09:00:00    5473
12:00:00    5614
13:00:00    5412
14:00:00    5633
20:00:00    5528
21:00:00    5534
22:00:00    5647

看起来我们可以总结如下:

请注意我们在这里如何使用pd.cut来给我们的数字数据分配类别,这是有意义的,因为毕竟,早餐是在 8 点还是 9 点开始可能并不重要。
另外,请注意我们如何使用. dt.hour,我们只能这样做,因为我们之前已经将invoices['Date of Meal']转换为 datetime。.dt就是所谓的存取器,有三个那些cat, str, dt。如果您的数据具有正确的类型,您可以使用这些访问器和它们的方法进行简单的操作(计算效率高且简洁)。

不幸的是,invoices['Participants']是一个字符串,我们必须先将它转换成合法的 JSON,这样我们才能提取参与者的数量。

现在我们来结合数据。为此,我们首先通过 order_leads 上的Company Id左连接所有发票。然而,合并数据会导致所有餐都加入到所有订单中。也把古代的餐点改成了更近的订单。为了减轻这种情况,我们计算了用餐和订购之间的时间差,并且只考虑订购前后五天的用餐。
仍有一些订单被分配了多餐。当同时有两份订单和两份餐时,可能会发生这种情况。然后,两餐将被分配给两个订单线索。为了删除重复的内容,我们只保留最接近订单的食物。

part of the combined data frame

我创建了一个已经包含一些样式的绘图栏函数。通过该功能绘图使得目视检查更快。我们马上就要用到它了。

膳食类型的影响:

哇!有餐点的订单和没有餐点的订单之间的转换率差异非常大。不过,看起来午餐的转化率比晚餐或早餐略低。

时间的影响(即用餐发生在订单引导之前还是之后):

'Days of meal before order'的负数意味着用餐发生在订单线索进来之后。我们可以看到,如果用餐发生在订单线索出现之前,似乎会对转化率产生积极影响。看起来对订单的预先了解给了我们的销售代表优势。

将这一切结合起来:

现在,我们将使用热图来同时显示多个维度的数据。为此,让我们首先创建一个助手函数。

然后,我们应用一些最终数据争论来额外考虑与订单价值相关的餐费,并将我们的交付周期划分为Before Order, Around Order, After Order,而不是从负四天到正四天,因为解释起来会有些忙。

运行下面的代码片段将生成一个多维热图。

Heatmap to visualize four dimensions in one graphic

热图当然很漂亮,尽管一开始有点难读。所以让我们过一遍。该图表总结了 4 个不同维度的影响:

  • 用餐时间:点餐后、点餐前后、点餐前(外排)
  • 用餐类型:早餐、晚餐、午餐(外列)
  • 餐费/订单值:最便宜、不太贵、成比例、较贵、最贵(内排)
  • 参加人数:1,2,3,4,5 (内列)

很明显,图表底部的颜色更深/更高,这表明

  • 当用餐发生在点菜之前时,转化率更高
  • 当只有一个参与者时,晚餐的转化率似乎更高
  • 看起来与订单价值相比,更贵的饭菜对转化率有积极的影响

调查结果:

  1. 不要给你的销售代表超过 9 个账户(因为转化率会迅速下降)
  2. 确保每笔订单都伴随着一次会面/用餐(因为这将使转化率提高一倍以上
  3. 当客户只有一名员工时,晚餐是最有效的
  4. 你的销售代表应该支付大约订单金额 8%到 10%的餐费
  5. 时机是关键,理想情况下,你的销售代表尽可能早地知道交易即将到来。

点击此处获取代码: GitHub Repo/Jupyter 笔记本

热图备注:

要解决可能不可靠的格式,您可以通过先卸载(您必须在终端中完成)然后运行以下命令,将 matplotlib 降级到版本 3.1.0:

!pip install matplotlib==3.1.0

如果你对此有问题,请告诉我

如何使用 Python 提取在线数据

原文:https://towardsdatascience.com/how-to-extract-online-data-using-python-8d072f522d86?source=collection_archive---------8-----------------------

Photo by Aaron Burden on Unsplash

关于 HTML、XPath、Scrapy 和 spiders 的基本概念

她的一位同事说:“我希望能拥有网站的所有文件。”

“是的,这能给我们提供很多信息”——另一位同事说

“你会做刮刀吗?”他们都转头看着她

"嗯……我可以……她开始喃喃自语

【完美】——他们都说

“…。她说完了,但为时已晚

她一生中从未用过刮刀。所以她当时不知所措。

“我不知道该怎么办” —她哭着给我打电话— “我觉得这对我来说太难了”

“你别担心!我们可以一起做”——我说

我完全理解她。第一次我不得不为一个 scraper 编码时,我也感到很失落。

就像我在看一场魔术表演。我记得当我开始阅读刮痧时。

“Web scrapers…mm…HTML 标签…mm…蜘蛛什么…?"对我来说,这听起来像是一门外语

但我读得越多,就越开始明白,就像魔术一样,你需要知道要寻找什么才能理解其中的诀窍。

到底什么是 web 刮刀?web scraper 是一种从网站上自动收集数据的程序。

我们可以收集网站的所有内容,或者只是关于某个主题或元素的特定数据。这将取决于我们在脚本中设置的参数。这种多功能性是 web 刮刀的魅力所在。

我们举个假设的例子。我们想从一个网址为https://www.mainwebsite.com的网站上抓取数据。特别是,这个网站包含不同的文件。我们对获取他们的文本感兴趣。

在主页中,我们可以找到三个子部分,如下图所示。

例如,点击topic1,我们将进入另一个页面(https://www.mainwebsite.com/topic1,在那里我们可以找到我们感兴趣的文档列表。

如果我们点击document1,我们将进入另一个页面(https://www.mainwebsite.com/topic1/document1/date),在那里我们可以获得该文档的内容。

如果我们要手动操作,我们会将内容复制并粘贴到文件中。相反,我们将自动化这一过程。

我们看到了获取数据所需遵循的路径。现在,我们应该找到一种方法来告诉 web scraper 在哪里寻找信息。

网站上有很多数据,比如图片、其他页面的链接、标题,我们都不感兴趣。因此,我们需要非常具体。

这是我们开始揭开魔术的地方。那我们解剖一下吧。

1HTML 代表超文本标记语言。它与层叠样式表(CSS)和 Javascript 一起,用于在交互式网站上构建和呈现内容。

你不需要学习如何使用 HTML 编码来构建一个 scraper。但是你应该知道如何识别 HTML 标签和元素。

为什么?因为数据会有一个特定的 HTML 标签。我们可以通过向 scraper 显示正确的 HTML 元素来提取这些数据。

一个 HTML 标签由一个用尖括号括起来的标签名组成。通常,您需要一个开头和一个结尾标签来框定一段特定的文本。

开始标记由一个名称和可选属性组成。结束标签由相同的名称加上一个正斜杠(/)组成。

每个标签名称都指一个特定的元素。我们会注意下面的标签:<p>用于段落;<a>或锚标记为超链接;<img>为图片;<h1><h2>等。对于文本标题;<div>为分隔线,<tr>为表格行,<td>为表格列。

大多数标签还带有idclass属性。id为 HTML 文档中的 HTML 标签指定了一个惟一的 id。class用于定义标签将采用的样式。

让我们观察一个 HTML 元素:

在这种情况下,我们希望提取 HTML 元素的内容“2019 年 6 月 28 日版”。我们会告诉 scraper:寻找所有的

元素,给我一个带有类“text-primary”的元素。

如果有一个以上的元素具有这些特征,我们就需要更加具体。指示 ID 属性可以实现这一点。

好的。但是我在网站上哪里可以找到这些信息呢?

这是一个简单的步骤:右击网页上的任何地方。将出现一个小窗口。接下来,你点击检查,如下图所示。

你可以访问网站的源代码,图片,CSS,字体和图标,Javascript 代码。

此外,您可以使用光标选择器(下面的图片)选择网站中的项目。

因此,对应于所选项目的 HTML 元素将被突出显示。

在上图中,我们可以观察到一个典型的 HTML 结构是什么样子。

正常情况下,所有内容都包含在开始和结束body标签中。每个元素都有自己的标签。

一些 HTML 元素嵌套在其他元素中,形成层次结构。这可以用树来表示。

如果我们在树中从左向右移动,我们向前移动了几代。如果我们从上到下移动,我们会在同一代之间移动,或者在来自同一个父元素的兄弟元素之间移动。

注意两个<div>元素。他们是兄弟姐妹,因为他们共享<body>作为父母。他们是html元素的第二代传人。他们每个人都有孩子。第一只<div>有两个孩子。它的第一个孩子是一个包含“网页抓取有用!”元素。然而,这个元素并不是第二个<div>的后代。这是因为您不能沿着从这个 div 元素到 paragraph 元素的路径。

这些关系也将有助于我们向 web scraper 指示所需的元素。

2XPath 代表 XML 路径语言。跟网页抓取有什么关系?我们将学习如何识别 HTML 元素。但是现在出现的问题是我如何向刮刀指出元素?答案是 XPath。

XPath 是一种特殊的语法,可用于浏览 XML 文档中的元素和属性。此外,它将帮助我们获得某个 HTML 元素的路径并提取其内容。

让我们看看这个语法是如何工作的。

/用于向前移动一个代,tag-names给出哪个元素的方向,[]告诉我们选择哪个兄弟元素,//查找所有后代,@选择属性,*是通配符,表示我们希望忽略标记类型。

如果我们看到下面的 XPath:

Xpath = '//div[@class="first"]/p[2]'

我们会理解,从所有(//)div元素中带class"""(div[@class="first"]),我们要第二个([2])段落(p)元素。

幸运的是,web 浏览器有一种简单的方法来获取元素的 XPath。

检查网站时,右键单击突出显示的元素。将显示一个小窗口。然后可以复制 XPath

3Scrapy 是一个 Python 框架,专为抓取网站和提取结构化数据而设计。它是专门为网络抓取而设计的,但是现在它也可以通过 API 来提取数据。

为了安装 Scrapy,你需要安装 Python。建议只使用 Python 3。Python 2 将于 2020 年 1 月弃用。

要安装 Scrapy,您可以使用 pip:

pip install Scrapy

或者使用康达

conda install -c conda-forge scrapy

Scrapy 的一个重要方面是它使用了 Twisted,这是一个流行的 Python 事件驱动网络框架。Twisted 为并发性异步工作

这是什么意思?同步意味着您必须等待一个作业完成,以便启动一个新作业。异步意味着您可以在前一个作业完成之前移动到另一个作业。

44蜘蛛。因为这个特点,Scrapy 可以在很短的时间内抓取一组 URL。因此,Scrapy 与蜘蛛合作,而不是在一个网站上抓取。

蜘蛛是我们定义的类,Scrapy 使用它来抓取多个页面的链接并抓取信息。

蜘蛛结构:

蜘蛛必须满足某些要求才能正常工作。他们必须子类化***scrapy.Spider***,并定义要发出的初始请求。此外,他们还可以决定如何在页面中跟随以及如何解析下载的页面内容。

让我们详细看看这些要求:

  1. 每个蜘蛛必须是***scrapy.Spider***类的子类:这意味着它必须把它作为一个参数。
  2. 蜘蛛的***name***在一个项目中必须是唯一的。
  3. 他们必须定义最初的请求:必须有一个方法调用***start_requests()***。Scrapy 将总是寻找它来发起请求。它还必须返回一系列请求,蜘蛛将从这些请求开始爬行。
  4. 他们可以决定如何解析下载的内容:通常会定义一个***parse()***方法。我们调用它来处理为每个请求下载的响应。parse()方法通常会解析响应,提取抓取的数据,还会找到新的 URL 并根据它们创建新的请求。
  5. 我们也可以找到**allowed_domains**名单。这告诉蜘蛛什么是允许抓取的域名。
  6. 此外,我们可以设置一个列表。用来指定我们要刮什么网站。默认情况下,Scrapy 使用 HTTP 协议。还得改成 https。

现在,我们已经剖析了 web 刮刀的所有组件。

→该写了!!←

我们将带来 URL 为https://www.mainwebsite.com的网站的初始示例。

让我们回顾一下事实:

  • 我们有一个主网站,有三个链接到三个不同的部分。
  • 在每个部分中,我们都有一个文档链接列表。每个部分都有一个特定的 URL,例如https://www.mainwebsite.com/topic1
  • 每个链接都将我们带到我们感兴趣的文档内容。我们可以在每个部分的 HTML 结构中找到每个链接。

首先,我们将设计我们的文件架构。

让我们探索一下我们的文件夹

我们已经创建了一个名为scraper的主文件夹,在这里我们将存储与我们的刮刀相关的所有文件。

然后,我们将收集 JSON 文件中的所有数据。这些文件都将保存在JSON文件夹中。

常用文件夹还有一个文件夹叫spiders。在那里,我们将为每个蜘蛛保存一个文件。我们将为每个主题创建一个蜘蛛。所以,总共三只蜘蛛。

现在,是时候了解我们创建的文件了。

先从settings.py说起吧。Scrapy 设置允许我们定制所有 Scrapy 组件的行为,包括核心、扩展、管道和蜘蛛本身。

在那里,我们可以指定由 Scrapy 项目实现的 bot 的名称,Scrapy 将在其中寻找蜘蛛的模块列表,以及 HTTP 缓存是否将被启用,等等。

现在,我们到达主要的两个文件。

我们先从**topic1.py** 蜘蛛开始。我们将只研究一个例子,因为它们都非常相似。

我们需要做的第一件事是导入所有需要的库。

显然,我们需要导入 scrapy。模块将允许我们使用正则表达式提取信息。json模块将在保存信息时帮助我们。os模块对于处理目录很有用。

我们之前说过,蜘蛛必须继承***scrapy.Spider*** 所以我们将创建一个名为FirstSpider 的类来继承它。我们将指定**name** 主题 1。然后,我们将定义**allowed_domains**列表。

我们还需要创建**start_request()**方法来初始化请求。在这个方法中,我们为请求定义了一个 URL 列表。在我们的例子中,这个列表只包含 URL [www.mainwebsite.com/topic1](http://www.mainwebsite.com/topic1.) 。然后,我们要用scrapy.Request提出请求。

我们将用[yield](https://pythontips.com/2013/09/29/the-python-yield-keyword-explained/)代替return。我们将告诉 scrapy 使用回调参数中的**parse()**方法来处理下载的内容。

到目前为止,你可能认为关于 HTML 和 XPath 的解释是没有用的。现在是我们需要它的时候了。

在我们定义了启动初始请求的方法之后,我们需要定义处理下载信息的方法。

换句话说,我们需要决定如何处理这些数据。哪些信息值得保存。

为此,让我们假设这是我们网站的 HTML 结构。

正如您在图片中看到的,突出显示的元素是我们提取链接所需的元素。

让我们建造到达那里的路径。从所有(//)具有class col-md-12 ( div[@class='col-md-12'])的div元素中,我们需要来自a子元素(a/@href)的属性href

因此,我们有了 XPath: //div[@class='col-md-12']/a/@href

在我们的parse方法中,我们将使用response.xpath()来指示路径,使用extract()来提取每个元素的内容。

我们期待得到一个链接列表。我们希望提取那些链接中显示的内容。蜘蛛需要跟踪它们中的每一个,并使用我们称之为parse_first的第二种解析方法解析它们的内容。

注意,这次我们在响应变量中使用follow发送链接,而不是创建一个请求。

接下来,必须定义parse_first方法来告诉蜘蛛如何跟踪链接。

我们将提取文档的标题和正文。

在探索了一个文档的 HTML 结构之后,我们将得到任何一个idtitleDocument、的元素,以及任何一个idBodyDocument 的元素的子元素的所有段落。

因为我们不关心他们有哪个标签,所以我们将使用*

得到每个段落后,我们将把它们添加到一个列表中。

之后,我们将把文本列表中的所有段落连接在一起。我们会提取日期。最后,我们将使用datetitletext定义一个字典。

最后,我们将数据保存到一个 JSON 文件中。

这里是函数extractdate的定义,我们将使用正则表达式来提取日期。

现在,我们的蜘蛛完成了。

B 该调查**scraper.py**文件了。我们不仅需要创造蜘蛛,还需要发射它们。

首先,我们将从 Scrapy 导入所需的模块。CrawlerProcess将启动抓取过程,而settings将允许我们安排设置。

我们还将导入为每个主题创建的三个蜘蛛类。

之后,我们启动一个爬行过程

我们告诉进程使用哪些蜘蛛,最后,我们将开始爬行。

完美!我们现在有我们的铲运机了!!!

但是等等,我们实际上如何开始抓取我们的网站呢?

在终端中,我们通过命令行导航到 scraper 文件夹(使用cd)。一旦进入,我们就用图中看到的python3命令启动蜘蛛。

然后瞧啊!蜘蛛正在爬网站!

在这里,我列出了一些非常好的资源和课程来学习更多关于网络抓取的知识:

  1. 数据营课程。
  2. 网页抓取教程
  3. 刺儿头文档
  4. HTML 长和短解释

如何假装成为一名优秀的程序员

原文:https://towardsdatascience.com/how-to-fake-being-a-good-programmer-cbef2c39764c?source=collection_archive---------0-----------------------

秘密就在光学中

Photo by Braydon Anderson on Unsplash

程序员是巫师——贫穷、衣衫褴褛的角色将咖啡变成代码。我不懂魔术,我只是个魔术师。我的工作是做一个假程序员比做真正的程序员更真实。

我很擅长我的工作,一个十足的江湖骗子。我骗过一些商人,让我成为他们的技术合伙人。我骗过了工程师,让他们向我咨询人工通用智能。我的行为如此真实,以至于司法部曾经征求我的建议,用 Visual Basic 创建一个 GUI 界面来追踪一个连环杀手的 IP 地址。

秘诀:重要的不是你知道什么,而是你表现出什么。

真正的工程师缓慢而乏味,因为他们被现实所拖累。一个魔术师只受他的想象力的限制。他可以自由地表演最复杂的场景,越色情越好。公众对黑客的认知是由狂欢和口交的场景塑造的——成为利用他们错误观念的罕见个体,允许门外汉沉迷于他们的幻想,你将被誉为英雄。

一场令人信服的表演需要一个精心设计的舞台,因为它会分散观众的注意力,让他们意识不到你缺乏深度。在电影中,软件是通过将 3D 块堆叠在彼此之上,或者通过抚摸一些全息图来编写的。当然,这是幻想。在现实生活中,最接近它的方法是结合使用三种古老的技术,这些技术都是几十年前发明的。

首先,你有 vim一个高度可配置的文本编辑器,很难使用数百万开发者无意中被困在它的爪子里,无法弄清楚如何关闭这个该死的东西。你大胆使用它的事实提升了你在同事中的地位。你似乎是彻头彻尾的神话,就神圣的编辑战争这样的历史主题启发他人,并激起对你讨伐 Emacs 教会的支持。

第二,tmux 是一个允许你在一个终端窗口中打开多个窗格的工具。这意味着您可以在一个面板中编写代码,在另一个面板中运行终端命令,并在剩下的面板中打开完全无用的插件,如音频声谱图和超大时钟。一般来说,你希望尽可能多的窗格打开,用这种突兀的景象压倒观众的感官。我自己强调永远不要关闭窗格,因为没有功能的代码不会老化。

给你一个例子,这是我生成一些 deepfakes 时的屏幕快照:

Spectrogram credit: M.O.P. — Ante Up

最后,最重要的是你要掌握 bash,一种直接在命令行中使用的脚本语言。了解 bash 可以让你最大限度地利用在终端的时间——在表演中途离开是一种亵渎,相当于在电影中途打开电影院的灯。需要计算一些东西吗?给你:echo "scale=0; 2 + 2" | bc。想知道自己的 CPU 使用率?命令如下:mpstat | grep -A 5 "%idle" | tail -n 1 | awk -F " " '{print 100 - $ 12}'a。你明白了。

比离开终端更糟糕的事情是离开键盘。使用光标会显得无能。如果你有一台个人电脑,立即把你的牙齿咬进人体工程学的怪物——鼠标的尾巴。如果你使用笔记本电脑,在触摸板上粘上砂纸——你想把它的使用与鲜血和痛苦联系起来。

现在,当你在终端时,敲击键盘很容易。要继续在浏览器中聊天,请使用 Vimium ,这是一个 Chrome 扩展,可以在不使用鼠标的情况下帮助浏览网页。它通过一系列按键突出显示网站上的每个链接,按下这些按键会模拟鼠标点击,从而打开所需的页面。它看起来是这样的:

Vimium

作为一个专业提示,请注意我是如何在浏览互联网时打开终端的。正如剧作家约翰·海伍德所说,“半块面包总比没有好”。此外,仔细看看我的 Chrome 标签,可以发现 arXiv 论文和堆栈溢出帖子的混合。这不是偶然的。战略性编排的标签阵列传达出你已经跨坐在令人垂涎的机器学习工程师的椅子上,一条腿在理论上摇摆,另一条在实践中摇摆。

T2:舞台布置好了,表演可以开始了。你的一举一动都表明你最不需要一只老鼠。也许你可以靠在椅子上,把腿放在桌子上,把键盘放在腿上。我自己在离我的 40 英寸显示器 10 英尺远的豆包里晒太阳。

至于行为本身,记住:这是巴洛克风格,不是极简主义。你想用你敏捷的手指动作和复杂的过渡来吸引观众。在 vim 中,您从一行跳到另一行,从一个函数跳到另一个函数,速度之快,旁观者几乎没有注意到。就在他们的眼睛开始适应,就在他们要理解你的废话的时候——很少有任何一行真正包含有效的代码——你切换到另一个 tmux 面板,他们的斗争重新开始。

一场好的演出是由它引起的混乱和沮丧的程度来衡量的。伟大的表演令人作呕。它简直让观众神魂颠倒——他们情不自禁地抽搐着倒在地上,垂涎三尺。

也许你认为这样的权谋策略太天真和不真诚,浮夸太轻浮。你宁愿保持低调,专注于这门手艺,希望在努力、诚实工作的最后,你会得到认可。

也许会,但为什么要浪费你生命中最美好的十年去辛苦工作呢?为什么不把你的脚放在桌子上,马上表现得像个高手?让我告诉你,做一个假的大人物比做一个真正的无名小卒要好。

如何以正确的方式“养殖”Kaggle

原文:https://towardsdatascience.com/how-to-farm-kaggle-in-the-right-way-b27f781b78da?source=collection_archive---------3-----------------------

本文描述了如何有效地使用 Kaggle 作为竞争平台,以最大的效率和盈利能力提高数据科学从业者技能的建议和方法。

农场(farming) —一种游戏策略,玩家通过重复动作来获得经验、点数或某种形式的游戏内货币。

描述

这些方法帮助我在六个月内获得了 Kaggle 竞赛大师的称号,仅仅是在单人模式下参加了三场比赛。当我在 Kaggle 上登上200 强世界排名时(在撰写 2018-10-18 原文时),他们也帮助了我。我希望这回答了我为什么冒昧地写这样一篇文章的问题。

介绍

最近(2019 年 2 月 11 日)新一期关于机器学习的惊人课程已经上线。这门课程是英文的,它是根据一群 Kaggle 大师的意见创建的,我强烈推荐它作为任何想在数据科学领域开始职业生涯的人的入门课程。像往常一样,在完成这门课程(或任何这方面的课程)后,学生中出现了一个问题:我们在哪里以及如何获得实践经验来巩固新获得的理论知识。如果你在任何相关论坛上问这个问题,答案很可能是“Kaggle”。好吧,Kaggle 不错,但是从哪里入手,如何最高效的利用这个平台进行实践技能的提升呢?在本文中,我将根据自己的经验尝试给出这些问题的答案,并描述如何避免竞争数据科学领域的一般错误,并在过程中获得乐趣的同时加快提振您技能的过程。

关于课程的创始人的几句话:

mlcourse.ai 是 OpenDataScience 社区的主要活动之一。 Yury Kashnitskiy(约尔科) & Co. (~60 多人)表明原则上不需要大学就能获得现代技术技能;此外,你可以完全免费这样做。这门课程的主旨是理论和实践的最佳结合。一方面,基本概念的介绍涉及一些数学知识,另一方面,在你的努力下,课堂竞赛和项目中的大量作业、将提高你的机器学习技能。更不用说这门课程的竞争性质了——互动的学生评分让参与变得有趣,并激励他们坚持到最后。此外,该课程发生在一个真正充满活力的社区。

在课程进行期间,有几场班级竞赛。两者都非常有趣,都是必需的特性工程。第一个是在 上,通过 访问站点的顺序进行用户识别。第二种尝试 预测媒体文章的流行度 。在一些作业中,你需要尽最大努力在这些比赛中超越基线。

向课程和它的创造者致敬,我们继续我们的故事…

我记得一年半前的自己,当我通过来自吴恩达的第一版 ML 课程,完成 MIPT 专精,读了堆积如山的书……不用说,我有很多理论知识,但是当我试图从现实生活中解决一个基本任务时,我碰壁了。我不知道从哪里开始。我知道如何解决这个问题,知道使用哪些算法,但是写代码非常困难,必须不断地搜索提示,查看 sklearn 帮助等。为什么?因为我没有完成这样一项任务的工作流程和实践经验。

这样是行不通的,我想,然后走向卡格尔。从排名赛开始很吓人,第一个目标是入门赛“房价:高级回归技术”。在进行这项竞赛的过程中,形成了高效的 kaggle 农业方法,本文对此进行了描述。

本文中描述的方法并不是唯一的,也没有“诀窍”,所有的方法和技术都是众所周知和简单明了的,但是这并没有降低它们的有效性。这些方法帮助我在六个月内获得了 Kaggle 竞赛大师的称号,仅仅是在单人模式下参加了三场比赛。当我在 Kaggle 上登上200 强世界排名时(在撰写 2018-10-18 原文时),他们也帮助了我。我希望这回答了我为什么冒昧地写这样一篇文章的问题。

一言以蔽之,Kaggle 是什么?

Kaggle 是举办数据科学竞赛的最著名平台之一。在每场比赛中,赞助商主持真正的任务,提供任务的描述、任务的数据、用于评估解决方案的指标,还设置截止日期和奖金。参与者通常每天有 3 到 5 次机会“提交”该任务的解决方案。

数据分为训练集和测试集。您将获得培训部分的目标变量的值,而不是测试部分的目标变量的值。参与者应该创建一个模型,当对数据的训练部分进行训练时,该模型在测试集上实现最大结果(根据所选的度量)。

每个参与者对一个测试集进行预测,并将结果发送到 Kaggle 上,然后机器人(它知道测试集的目标变量)评估收到的结果,对其进行评分,并将其显示在排行榜上。

但事情没这么简单,测试数据依次按一定比例分为公共部分和私人部分。在比赛期间,根据测试集公共部分的既定指标对提交的解决方案进行评估,并将结果放在“公共”排行榜上,参与者可以在比赛期间评估他们模型的质量。最终解决方案(通常是参与者选择的两个)在测试数据的私人部分进行评估,结果将进入私人排行榜,该排行榜仅在比赛结束后才可见,实际上,最终评级将根据该排行榜进行评估,并分发奖品和奖牌。

因此,在比赛期间,参与者只知道他们的模型在测试数据的公开部分表现如何(产生的结果或分数)。如果在真空中的球形鸡的情况下,数据的私人部分具有与公共部分相同的分布和统计,那么一切都可能是好的。如果不是这样,那么这个被证明对测试集的公共部分有好处的模型可能会在私有部分失败。这被称为“在公共董事会上过度配合”。这导致了“排行榜外逃”,当公共排行榜上排名第 10 位的人在私人部分跌至 1000–2000 位,因为他们选择的模型过度拟合,无法在看不见的数据上给出所需的准确性。

如何避免?首先,您需要建立一个适当的验证方案,这是几乎所有数据科学课程的第一课。为什么这么重要?好吧,如果你的模型不能对之前从未见过的数据集做出正确的预测,那么无论你使用什么样的技术或者你的神经网络有多复杂都没有用。您不能在生产中发布这样的模型,因为看不见的数据的结果将是没有价值的。

对于每场比赛,Kaggle 管理员都创建了自己的独立页面,其中包含数据、时间表、指标描述以及对我们来说最有价值的部分——论坛和内核。

论坛是一个标准的论坛,人们可以在这里讨论和分享想法。但是内核更有趣。事实上,是运行您的代码直接访问 Kaggle 云中的竞争数据(类似于 AWS、GCE 等)的机会。)每个内核的计算资源都是有限的,所以如果数据集不太大,你可以直接在 Kaggle 网站的浏览器上使用它。您可以编写代码、执行代码、调试代码,当然还可以提交结果。两年前,Kaggle 被谷歌收购,因此“引擎盖下”这一功能使用谷歌云引擎并不奇怪。

此外,还有几个竞赛(例如, Mercari )要求你只能通过内核处理数据。这是一种令人兴奋的格式,它补偿了参与者之间的硬件差异,并让您在代码优化和方法的主题上使用您的大脑,因为内核当时对资源有硬性限制(4 个内核/ 16 GB RAM / 60 分钟运行时间/ 1 GB 暂存磁盘空间和输出)。在这次比赛中,作者学到了比任何理论课程都多的关于神经网络优化的知识。得分比黄金级低一点,在单人模式中排名第 23,但获得了很多经验和快乐…

我很高兴借此机会再次感谢 ods.ai 的同事们——亚瑟·斯特塞潘尼卡(亚瑟)、康斯坦丁·洛普欣(科斯蒂亚)、谢尔盖·菲罗诺夫(谢尔盖夫)对本次比赛的建议和支持。总的来说,有许多有趣的时刻,Konstantin Lopuhin(kostia),他在这次比赛中与pawejankiewicz一起获得了第一名,随后做了被称为“75 行参考羞辱”的帖子,他们发布了 75 行内核,给出了黄金排行榜区的结果。你真得去看看!

好吧,让我们回到比赛上来。人们编写代码并发布带有解决方案、有趣想法等的内核。在每次比赛中,通常在比赛开始后的几周内,都会出现一两个漂亮的 EDA(探索性数据分析)内核,其中包含对数据集、属性统计、特征等的详细描述。和几个基线内核(基本解决方案),当然,它们不会在排行榜上显示最佳结果,但您可以使用它们作为创建自己的解决方案的起点。

为什么是 Kaggle?

其实玩什么平台没什么区别。Kaggle 只是第一个也是最受欢迎的一个,有很棒的社区和舒适的环境(我希望他们会为了稳定性和性能而修改内核。许多人还记得在墨卡里发生的事情,但是,总的来说,这个平台是非常方便和自给自足的,卡格尔等级(大师)仍然很有价值。

在竞争数据科学的主题上有点偏离主题。很多时候,在文章、对话和其他交流中,人们认为比赛中获得的经验不能用于现实生活中的问题,所有这些人都只调了分数的第五位小数,这是疯狂的,离现实太远了。让我们更仔细地看看这个问题:

作为一名实践数据科学的专业人士,与来自学术界和科学界的人相比,我们应该并将在工作中解决实际的业务问题。换句话说,(这里引用的是 CRISP-DM )要解决这个问题有必要:

  • 为了理解业务问题
  • 评估数据以确定它是否能解决这个业务问题
  • 如果现有数据不足以得到答案,则收集额外的数据
  • 选择最接近业务目标的指标
  • 并且只有在选择了一个模型之后,才转换所选模型的数据并“堆栈 xgbosts”。

这个列表中的前四项在任何地方都没有教授(如果有这样的课程,请纠正我——我会立即报名参加),唯一的方法是从在特定行业工作的同事那里学习经验。但是最后一条——从选择车型开始,你可以,也应该在比赛中提高。

在任何比赛中,赞助商已经为我们完成了大部分工作。我们已经有了业务目标、选定的近似度量、收集的数据,我们的任务是从所有这些中构建一个工作管道。这里是技能需要改进的地方——如何处理缺失值,如何为神经网络和树准备数据(以及为什么神经网络需要一种特殊的方法),如何建立一个验证方案,如何不过度拟合,如何选择合适的超参数,以及许多其他“如何做”,在我们的专业中,专家与路人之间的区别在于其执行能力。

你可以在 Kaggle 上“耕种”什么

基本上,所有的新人来到 Kaggle 都是为了提高他们的实践经验,但不要忘记,除此之外,至少还有两个额外的目的:

  • 农场奖章和军衔
  • Kaggle 社区的农场声誉

需要记住的关键一点是,这三个目标是完全不同的,实现它们需要不同的方法,尤其是在初始阶段,不应该混淆!

请注意单词、【初始阶段】、,因此当你提高技能时——这三个目标将合并为一个,并平行实现,但当你刚刚开始时——不要把它们混淆!这样你将避免痛苦、挫折和对这个不公正世界的怨恨。

让我们自下而上简要介绍一下目标:

  • 声誉 —通过在论坛上写好的帖子(和评论)和创建有用的内核来提高声誉。比如 EDA 内核(见上),有创新技术描述的帖子等。
  • 奖牌 —一个非常有争议的话题,但是……它可以通过混合公共内核(*)、加入经验不平衡的团队,当然也可以通过创建自己的顶级解决方案来改进
  • 经验 —通过对决策和错误的分析得到增强。

(*) 混合公共内核—获得奖牌的技术,当选择公共排行榜上得分高的内核时,对它们的预测进行平均(混合),并提交结果。通常,这种方法会导致在公共排行榜上很难超配,但有时会让你几乎获得银牌。在初始阶段,作者不推荐这种方法(阅读下面关于腰带和裤子的内容)。

我建议首先选择“体验”目标,并坚持下去,直到你觉得准备好同时为两三个目标努力。

还有两件事值得一提(Vladimir Iglovikov(tern aus)——感谢提醒)。

第一个是将在 Kaggle 投入的精力转化为一份新的、更有趣和/或报酬更高的工作。对于理解题目的人来说,简历中的那一行“Kaggle 竞赛大师”和其他成就还是有价值的。

为了说明这一点,你可以阅读两个采访(一个,两个,请注意,这些采访是用俄语进行的)与我们的同事谢尔盖·穆欣斯基(切佩拉 _ 昂)和亚历山大·布斯拉耶夫(阿尔布)

还有 Valeriy Babushkin (venheads) 的意见:

valeriy Babushkin——X5 零售集团数据科学负责人(领导一个 50 多人的团队,分为 5 个部门:CV、机器学习、数据分析、NLP 和 Ad Hoc),Yandex Advisor 分析团队负责人

Kaggle 竞赛大师是评估未来团队成员的一个很好的替代指标。当然,由于最近的事件是 30 人一组,而且几乎没有人做任何事情,这就需要比以前更仔细地研究这个轮廓,但这仍然只是几分钟的事。获得大师头衔的人,很有可能能够写出至少一般质量的代码,精通机器学习,能够清理数据并构建可持续的解决方案。如果你没有硕士学位,仅仅参与的事实也是一个加分项,至少候选人知道 Kaggle 的存在,并花了一些时间来熟悉它。如果他贡献的解决方案不仅仅是一个公共内核(这很容易检查),这是一个关于技术细节的具体对话的好机会,这比传统的应届毕业生求职面试好得多,也更有趣,因为后者提供的信息少得多,不知道未来人们将如何在工作中取得成功。我们唯一需要担心的是,我遇到的是一些人认为数据科学工作与 Kaggle 相同,这完全不是事实。很多认为数据科学=机器学习,这也是错误的。

第二点许多任务可以以预印本或文章的形式安排,一方面,它允许集体智慧在竞争中获得的知识不会在论坛的荒野中消亡,另一方面,它为作者的作品集增加了另一条线,为可见性增加了+1,这在任何情况下都会对职业生涯和引用指数产生积极影响。

例如,这是我们同事在几个比赛结束时的作品列表:

  • 使用深度卷积神经网络的卫星图像特征检测:Kaggle 竞赛
  • TernausNet:带有 VGG11 编码器的 U-Net,在 ImageNet 上预先训练,用于图像分割
  • 使用深度卷积神经网络的血管发育异常检测和定位
  • 机器人辅助手术中的自动器械分割使用深度学习 用于从卫星图像中自动提取道路的全卷积网络
  • Ternausnetv2:全卷积网络实例分割
  • 用于多级土地分割的特征金字塔网络
  • 使用深度卷积神经网络进行儿科骨龄评估
  • 使用卷积神经网络的摄像机型号识别
  • 理解简单语音命令的深度学习方法
  • 用于乳腺癌组织学图像分析的深度卷积神经网络
  • 通过集成深度学习分类框架进行糖尿病视网膜病变检测
  • 使用 U-Net 和 Lovasz-Softmax Loss 对卫星图像进行土地覆盖分类
  • 超像素土地覆盖分类和 Jaccard 指数后优化
  • 使用复合损失函数从卫星图像中检测建筑物
  • 用卷积神经网络检测北大西洋露脊鲸叫声
  • 奔跑,骨骼,奔跑:基于物理的模拟中的骨骼模型
  • 学习运行挑战解决方案:适应神经肌肉骨骼环境的强化学习方法
  • 【ImageNet 分类的正则化方法与深度卷积神经网络的比较
  • 面向人脸表征学习的重身幽灵挖掘 具有辅助嵌入的硬示例挖掘
  • 在 Kaggle 竞赛框架内使用 WaveNet 进行销售预测

如何避免失去奖牌的痛苦

别管他们!

让我解释一下。实际上,在每一场接近尾声的比赛中,都有人用一个解决方案编写了公共内核,让整个排行榜上升,但你用你的解决方案却下降了。每次在论坛上痛苦就开始了!“哦,在这里我有一个银的解决方案,现在我甚至不在铜。到底是怎么回事,我们把东西都拿回来。”

请记住,Kaggle 是竞争数据科学,你在排行榜上的位置只取决于你自己。不是来自发布内核的人,也不是来自聚集在一起或不聚集在一起的明星,只是取决于你在决策中投入了多少努力,以及你是否使用了所有可能的方法来改进它。

如果公共内核把你从排行榜上抢走了——那不是你的位置。

而不是不得不为这个世界的不公倾吐痛苦——感谢这个家伙。说真的,比你的解决方案更好的公共内核意味着你在自己的管道中错过了一些东西。找到它,改进它,并以相同的分数绕过所有的仓鼠。记住,要回到原来的位置,你只需要比这个公共内核好一点点。

在第一场比赛的这个时刻,我是多么的沮丧!我的手开始下垂,我准备放弃了。刚才你还在银牌级别,而现在你在……排行榜的末尾。没关系,我只需要让自己明白在哪里错过了什么,就可以改变我的决定,回到比赛中来。

此外,这一时刻只会出现在你竞争过程的早期。你越有经验,就越感受不到发表的内核和明星的影响。在最近的一次比赛(谈话数据,我们的团队获得第八名)中有这样的内核,但在我们的团队聊天中,来自的 Pavel Pleskov (ppleskov) 在一行文字中提到了它:“伙计们,我把它与我们的解决方案混合在一起,它变得更糟了,所以我把它扔掉了”。这意味着内核从数据中提取的所有有用信号都已经被我们的模型提取出来了。

顺便说一句,关于奖牌,请记住:

“没有技能的腰带只起到撑住裤子的作用”

在哪里以及如何编写代码

我推荐的是Ubuntujupyter 笔记本python 3.6 。鉴于大量的库和社区,Python 已经成为数据科学中事实上的标准。Jupyter,尤其是有了jupyter _ contrib _ nb extensions的存在,对于快速原型制作、分析和数据处理非常方便。Ubuntu 本身很简单,而且数据处理部分有时用 bash 比用 python 更自然。

在安装了jupyter _ contrib _ nb extensions之后,我建议启用:

  • 可折叠标题 (真正有助于组织代码块)
  • (同)
  • (如果你需要调试什么东西的话很有用)

你的生活会变得更加舒适和愉快。

一旦您的管道变得或多或少稳定,我建议将您的代码转移到单独的模块中。相信我——你会重写不止一次两次甚至五次,这没关系。

有一种相反的方法,参与者试图尽可能少地使用 jupyter notebook,并且只在必要时使用,他们更喜欢通过脚本编写管道。(这个选项的内行,比如(弗拉基米尔·伊格洛维科夫(ternaus) )。你也可以阅读“与卡格尔大师弗拉基米尔·伊格洛维科夫(Vladimir I. Iglovikov)的任意提问环节”,在那里他描述了这种方法。

还有人试图将 jupyter 与任何 IDE 结合起来,比如 Pycharm。

每种方式都有存在的权利,各有利弊,就像他们说的,口味不同。选择你觉得舒服的工作。

但是在任何情况下,记住这条规则

**保存每次提交/OOF 的代码。(见下文)

()OOF—out of folds,一种使用交叉验证为数据集的训练部分获取模型预测的技术。对于几个解决方案的进一步组合是至关重要的。***

怎么会?嗯,至少有三种选择:

  • 对于每个竞赛,我们在 GitHub 或 BitBucket 上创建一个单独的存储库,并为我们提交到存储库的每个代码提交一个注释,其中包含获得的分数、模型参数等。
  • 每一次提交后的代码被组合成一个单独的档案,其文件名包含所有元信息(获得的分数、选项等)。)
  • 使用了用于数据科学任务的专用版本控制系统。比如说 DVC 。

一般来说,在社区中,有一种逐渐过渡到第三种选择的趋势,因为第一种和第二种都有缺点,但它们简单可靠,老实说,对 Kaggle 来说,它们绰绰有余。

对于不是程序员的人,再多说几句 python。不要害怕。你的任务是理解基本的代码结构和语言的基本本质。它将使你能够理解别人的内核代码,并编写自己的库。在互联网上有许多优秀的初学者课程,也许在评论中,有人会给你链接。不幸的是(或者幸运的是)我不能评价这些课程的质量,所以我不会把这些链接放在文章里。

好了,我们去框架

本文中描述的所有技术都基于处理表格和文本数据。使用图片是一项独立的任务,具有独立的框架。在基本层面上,能够与它们一起工作是很好的,至少可以运行像 ResNet/VGG 这样的东西并获得特性,但是与它们进行更深入、更微妙的工作是一个单独的、非常广泛的主题,不在本文中讨论。

我不太擅长处理影像数据。唯一一次尝试是在比赛相机识别中,顺便说一下,在比赛中,带有【ODS . ai】标签的团队炸毁了整个排行榜,所以 Kaggle 管理员必须来我们的松弛区检查一切是否符合规则。在这次比赛中,我以第 46 名的成绩获得银牌,但当我阅读了我们同事对顶级解决方案的描述后,我明白这是我最好的地方,因为他们使用了一个真正的黑魔法,增加了图片,增加了 300 多 GB 的数据,牺牲了其他东西。例如,您可以阅读来自Vladimir Iglovikov(tern aus)的关于“数据增强的重要性”的帖子。

一般来说,如果你想开始使用图像,那么你需要其他的框架和指南。

主要目标

你的主要任务是为以下任务编写管道(以 jupyter 笔记本+模块的形式下发):

  • 探索性数据分析。这里有必要做一个评论,Kaggle 上有专门训练过的人:),他们每次比赛都写出非常好看和全面的 EDA 内核。击败他们很难,但理解如何看待数据仍然是必要的,因为在你的工作任务中,这个经过特殊训练的人就是你。所以你需要研究方法和途径,扩大你的图书馆。
  • 数据清理—数据清理的所有方面。处理缺失值、异常值等。
  • 数据准备就是为模型准备数据。多个块(通用,用于回归/神经网络,用于树模型,特殊(时间序列,图像, FM/FFM ),文本(矢量器,TF-IDF ,嵌入))
  • 模型(线性模型、树形模型、神经网络、外来(调频/FFM))
  • 特征选择
  • 超参数搜索
  • 全体

在公共内核中,所有这些任务通常都集中在一个代码中,但是我强烈建议为这些子任务中的每一个创建单独的笔记本和单独的模块(或模块集)。这个方法以后会对你有帮助。

为了防止可能的圣战,请记住——这个框架的结构并不是最后一个实例的真相,还有许多其他方式来构建管道,这只是其中之一。

数据以 CSV 或 feather/pickle/hdf 格式在模块之间传输,这是您喜欢的方式,也是您习惯或喜欢做的事情。

其实很多还是要看数据量。例如,在 TalkingData 竞赛中,我必须通过 memmap 来避免在为 lgb 创建数据集时出现内存不足的错误。

在其他情况下,主数据存储在 hdf/feather 中,这是 CSV 中的一个小文件(如所选属性集)。我重复一遍——没有模板,这只是可能的方式之一。你应该尝试所有的方法,选择最适合你的一个。

初始阶段

从任何入门竞赛开始(如前所述,我从房价:高级回归技术开始),开始创建你的管道和笔记本。读取公共内核,复制代码片段、过程、方法等。,然后运行您的数据管道,提交—查看结果,改进,清洗并重复。

这一阶段的主要任务是创建一个高效运行的全周期管道——从读取和清理数据到创建最终提交。

在进行下一步之前,应准备好并 100%工作的样本列表:

  • EDA(数据集统计、图表、一系列类别等)
  • 数据清理(使用 fillna 填充缺失,清理类别,合并类别)
  • 数据准备(通用(处理类别-标签/ohe/频率,数值到分类的投影,数值转换,宁滨),用于回归(不同的比例))
  • 模型(线性模型(不同的回归-岭/逻辑),树模型(lgb))
  • 特征选择(网格/随机搜索)
  • 集合(回归/ lgb)

投入战斗

选择任何你喜欢的比赛,让我们开始…

  • 查看数据,阅读论坛,建立一个强大的验证方案。如果没有强大的验证,你将在排行榜上落榜,就像在梅赛德斯、桑坦德和其他公司的竞争中发生的那样。例如,看看梅赛德斯和讨论的排行榜(绿色箭头和数字表示与公众相比,人们在排行榜中上升的位置数,红色表示下降的位置数)

此时(2018-02-10)箭头从所有比赛的排行榜中移除。我不知道原因,但希望它会回来。

  • 还有,我推荐阅读文章(Rus)演讲(Rus)丹尼拉·萨文科夫(danila_savenkov) :
  • 此外,课程如何赢得数据科学竞赛:向顶尖高手学习也很好地涵盖了这一主题

不要继续,直到您构建了一个健壮的验证模式——!!!

好了,你得到了可靠的验证,下一步做什么?

  • 运行您的管道并提交结果
  • 抓住你的头,吓坏了,冷静下来…并继续…
  • 阅读所有内核/论坛,了解使用的技术和方法
  • 用新技术重建你的管道
  • 转到步骤 1

记住你这个阶段的目标是获得经验!我们必须用工作方式和方法填充我们的管道,用工作代码填充我们的模块。不要担心奖牌——我的意思是,如果你能立即在排行榜上占据一席之地,那就太好了,但如果不能,也不要沮丧。我们来这里才五分钟,所以勋章和军衔不会去任何地方。

好了,比赛结束了,你在排行榜的某个位置,你学到了一些东西,想去参加下一场比赛?

不!

下一步做什么:

  • 等五天。不要看论坛,暂时忘记 Kaggle。让大脑休息一下,让眼睛有机会重新磨砺。
  • 然后回到比赛中。在这五天中,根据礼仪规则,所有顶级团队都将在论坛上发布他们的解决方案,以帖子、内核或 GitHub 资源库的形式。

这里你的个人地狱开始了

  • 你拿几张 A4 纸,在每张纸上写上来自上述框架的模块名称(EDA/Preparation/Model/Ensemble/Feature selection/Hyperparameters search/…)
  • 然后坚持阅读所有高层决策,并用新的技术、方法和途径填写相应的表格。

还有最差的:

  • 对于每个模块,您依次编写这些方法的实现,扩展您的管道和库。
  • 然后运行更新后的管道并提交解决方案。
  • 重复这个过程,直到你在排行榜的黄金区域找到解决方案,或者直到你失去耐心和勇气。

只有在那之后才能进入下一场比赛。

不,我没开玩笑。是的,你可以做得更容易。由你来决定。

为什么要等 5 天,而不立即阅读论坛?嗯,你正在失去问一些问题的机会,但在这个阶段(在我看来),最好是阅读已经形成的讨论解决方案的线索,然后问一些别人已经问过的问题,或者最好不要问,自己寻找答案。

你为什么要这么做?好吧,再说一遍——这个阶段的目的是开发你自己的解决方案、方法和途径的数据库。创造一个有效的渠道。所以在下一场比赛中,你不要浪费时间,只要说——是的,的意思是这里可以使用目标编码,顺便说一下,我有正确的代码,它使用了折叠中的折叠。或者,我记得在那个任务中,最好的方法是使用 scipy.optimize 使用 ensemble,顺便说一下,我已经为它准备好了代码。

差不多吧…

进入工作模式

用同样的方法,你应该参加一些其他的比赛。每次我们注意到工作表中的条目越来越少,而模块中的代码越来越大。渐渐地,分析的任务收敛到确保你阅读解决方案的描述,说耶,地狱耶!并在你的库中添加一两种新的方法或途径。

此后,学习模式变为纠错模式。基础库已经准备好了,现在只需要正确使用了。每次比赛后,你都会阅读解决方案的描述,看看你做了什么,哪些地方可以做得更好,你错过了什么,或者你具体哪里搞砸了,就像我在有毒中做的那样。我在黄金地带的下腹部走得很好,私下跌了 1500 点。这简直是侮辱到流泪…但我冷静下来,找到了一个 bug,在我们的 Slack 社区写了一个帖子——并吸取了教训。

建立工作模式的一个标志是,顶级解决方案的一个描述将写在你的昵称下。

粗略地说,在这个阶段结束时,您的管道中应该有什么:

  • 预处理和创建数字特征的各种方法—投影、关系
  • 关于如何处理类别的不同方法—意味着以正确的形式、频率、标签/ ohe 进行目标编码
  • 文本的各种嵌入方案(Glove、Word2Vec、Fasttext)
  • 文本的各种矢量化方案(计数、TF-IDF、哈希)
  • 几个验证方案(N*M 代表标准交叉验证,基于时间,按组)
  • 贝叶斯优化/超点/超参数选择的其他方法
  • 用于特征选择的洗牌/目标排列/博鲁塔/ RFE
  • 线性模型—编写代码,在一个处理过的数据集上以相同的风格运行不同的模型
  • LGB/XGB/Catboost —编写一个代码,在一个处理过的数据集上以相同的风格运行不同的模型

作者为具有相同外部接口的线性和基于树的模型分别创建了几个元类,以中和模型库的不同实现之间的 API 差异。但是现在他可以通过一行代码在一个处理过的数据集上运行同一类型的不同模型(例如 LGB 或 XGB)。

  • 几个不同类型的神经网络(不用于图片)——文本的嵌入/CNN/RNN,序列的 RNN,其余的前馈。理解和实现自动编码器是很好的。
  • 基于 lgb/regression/scipy 的集成—分别用于回归和分类任务。
  • 能够使用遗传算法很好,有时它们工作得相当好。

总结

正如在任何运动中一样,在竞争数据科学中,有大量的汗水和大量的工作。这不好也不坏,这是事实。参加比赛(如果你正确地对待这个过程)会大大提高技术技能,而且或多或少会培养一种体育精神——当你真的不想做某事,但你拿起笔记本电脑,重建模型并运行它来提高你分数的这该死的第五位小数时。

所以去玩 Kaggle 吧——收获经验、奖牌和乐趣!

关于作者的管道说几句话

在这一节中,我将尝试描述一年半以来我收集的管道背后的基本思想。同样,这种方法并不要求普遍性或独特性,但也许您会发现它很有用。

  • 除了平均目标编码之外,特征工程的所有代码都作为函数写在一个单独的模块中。我试图通过对象来实现,但结果很麻烦,在这种情况下没有必要。
  • 特征工程的所有函数都采用相同的风格,并具有相同的调用签名和返回:
**def do_cat_dummy(data, attrs, prefix_sep=’_ohe_’, params=None):*# do something*
return _data, new_attrs**

输入是数据集、属性、新属性的前缀和附加参数。输出是具有新属性的新数据集和这些属性的列表。此外,这个新数据集存储在一个单独的 pickle/feather 中。

它提供了什么—我们能够从预先构建的部件快速组装工作数据集。例如,我们对类别进行了三种不同的处理——标签编码/ OHE /频率,并将它们存储在三个单独的羽毛中,然后在建模阶段,我们需要做的只是玩这些块,通过一个优雅的动作创建不同的数据集进行训练。

**pickle_list = [‘attrs_base’,‘cat67_ohe’,# ‘cat67_freq’,]
short_prefix = ‘base_ohe’_attrs, use_columns, data = load_attrs_from_pickle(pickle_list)
cat_columns = []**

如果有必要组装另一个工作数据集—我们只需要替换 pickle_list,重新加载并使用新的数据集。

表格数据(实数和分类数据)的一组基本函数包括各种类别编码、数字属性到分类数据的投影以及各种转换。

**def do_cat_le(data, attrs, params=None, prefix=’le_’):
def do_cat_dummy(data, attrs, prefix_sep=’_ohe_’, params=None):
def do_cat_cnt(data, attrs, params=None, prefix=’cnt_’):
def do_cat_fact(data, attrs, params=None, prefix=’bin_’):
def do_cat_comb(data, attrs_op, params=None, prefix=’cat_’):
def do_proj_num_2cat(data, attrs_op, params=None, prefix=’prj_’):**

Universal Swiss army knife 用于组合属性,它将源属性列表和转换函数列表作为输入,其输出通常是数据集和新属性列表。

**def do_iter_num(data, attrs_op, params=None, prefix=’comb_’):**

加上各种附加的特定转换器。

为了处理文本数据,使用了单独的模块,包括预处理、标记化、词条化/词干化、频率表中的翻译等不同方法。,使用 sklearn,nltk 和 keras。

时间序列在一个单独的模块中处理,该模块具有为常见任务(回归/分类)以及序列到序列任务转换源数据集的功能。感谢 Franç ois Chollet 对 keras 的更新,所以现在构建 seq-2-seq 模型看起来不像是恶魔召唤的巫毒仪式。

顺便说一下,在同一个模块中还有传统的序列统计分析功能——平稳性测试、STL 分解等。在分析的初始阶段“感受”时间序列并了解它实际上是什么是非常有用的。

  • 不能立即应用于整个数据集的函数,以及您需要在折叠交叉验证中使用的函数,被移到单独的模块中:
  • 平均目标编码
  • 上采样/下采样
  • 它们在训练阶段被传递到模型类的内部(见下文)。
**_fpreproc = fpr_target_enc_fpreproc_params = fpr_target_enc_params_fpreproc_params.update(**{‘use_columns’ : cat_columns,})**
  • 对于建模,创建了新的元类,它用抽象方法概括了模型的概念:fit/predict/set_params/ etc。对于每个库(LGB、XGB、Catboost、SKLearn、RGF……)来说,已经创建了这个元类的单独实现。

换句话说,为了与 LGB 合作,我们创建了一个模型

**model_to_use = ‘lgb’
model = KudsonLGB(task=’classification’)**

对于 XGB:

**model_to_use = ‘xgb’
metric_name= ‘auc’
task=’classification’model = KudsonXGB(task=task, metric_name=metric_name)**

现在在我们的代码中,我们可以通用地操作这个模型。

  • 为了验证,创建了几个函数,一个为几个种子同时计算预测和 OOF,另一个是使用 train_test_split 的基本验证,等等。所有函数都使用元模型方法进行操作,这提供了与模型无关的代码,并方便了与任何其他库的管道连接
**res = cv_make_oof(
model, model_params, fit_params, dataset_params,     XX_train[use_columns], yy_train, XX_Kaggle[use_columns], folds, scorer=scorer, metric_name=metric_name, fpreproc=_fpreproc, fpreproc_params=_fpreproc_params, model_seed=model_seed, silence=True
)score = res[‘score’]**
  • 对于特征选择——没有什么有趣的,只是标准的 RFE,以及我最喜欢的所有可能方式的混合排列
  • 为了找到超参数,我主要使用贝叶斯优化,再次以标准化的形式能够运行任何模型的搜索(通过交叉验证模块)。这段代码驻留在建模笔记本中
  • 对于系综,创建了几个函数,根据岭/对数、LGB、神经网络和我最喜欢的 scipy.optimize 对回归问题和分类进行了标准化
  • 稍微解释一下——管道中的每个模型都生成两个文件作为输出:sub_xxx 和 oof_xxx,分别表示测试集的预测和训练集的 oof 预测。接下来,在 ensemble 模块中,这些文件(来自所有模型)从指定目录加载到两个数据帧中— df_sub / df_oof。然后我们查看相关性,选择最好的,然后在 df_oof 上建立第二级模型并应用于 df_sub
  • 有时候用遗传算法搜索模型的最佳子集会产生极好的结果(我用的是这个库,有时候卡鲁阿纳的一个方法效果很好。在最简单的情况下,标准回归和 scipy.optimize 可以完成这项工作。
  • 神经网络生活在一个独立的模块中,我在中使用 keras 一个函数风格,是的,我知道,它不如 pytorch 灵活,但也足够了。同样,通用的训练函数被编写,对网络的类型是不变的

这一管道在最近的 Home Credit 的比赛中再次得到了检验,所有模块和模块的谨慎和准确应用为作者带来了第 94 名和一枚银牌。

作者其实很愿意表达一个煽动性的想法,对于表格数据和体面的管道,任何比赛的最终结果都必须在排行榜的前 100 名。当然也有例外,但总的来说,这种说法似乎是正确的。

关于团队合作

如何解决 ka ggle——在团队或 solo 中——主要取决于一个人(和一个团队),但我对刚开始的人的建议是——尝试开始 solo。为什么?我会试着解释我的观点:

  • 首先,你会看到自己的优势和劣势,并能够评估自己作为一名数据科学家的总体潜力。
  • 其次,即使是在一个团队中工作(除非是一个建立良好的、角色分离的团队),团队仍然会等待你的一个完成的解决方案。所以你必须有工作管道来很好地合作。
  • 第三,最理想的是,当团队中球员的水平差不多时(并且足够高),你可以学到一些真正有用的东西。在弱队(没有什么贬义,我说的是 Kaggle 上的训练水平和经验)IMHO 学点东西很难,不如看论坛和内核。是的,这是有可能的农场奖牌,但看到以上关于目标和一个腰带保持你的裤子

来自明显队长的好建议和承诺的一般错误地图:

这些小技巧反映了作者的经验,可以(也应该)通过自己的实验来验证

  • 总是从建立一个健壮的验证方案开始——否则,所有其他的努力都是徒劳的。再看看奔驰的排行榜。

令作者非常高兴的是,在这次比赛中,他建立了一个强大的交叉验证方案(3x10 倍),保持了一个分数,并获得了第 42 名。

  • 如果你已经建立了一个可靠的验证——永远相信你的验证结果。如果你的模型的分数因为验证而提高,但是在公共排行榜上变得更差,相信验证是更明智的。在分析中,只考虑数据,这是一个公共排行榜作为另一个折叠。你不会想让你的模型在一个单一的折叠上过度拟合,对吗?
  • 如果模型和方案允许-始终进行 OOF 预测并将其保存在模型旁边。在合奏阶段,你永远不知道什么最有帮助。
  • 总是将代码保存在结果/OOF 旁边,以便重新创建它们。在哪里保存并不重要——在 GitHub,本地,任何地方。有两次,我发现最好的模型是两周前开箱的,而且没有保存代码。痛苦。
  • 放弃选择交叉验证的“正确”种子。最好选择任意三个一,做 3хN 交叉验证。结果会更稳定。
  • 不要追逐集合中模型的数量——越少越好,但要更加多样化——在模型、预处理和数据集方面多样化。例如,在最坏的情况下,在参数中,一个深树具有硬正则化,一个浅树。
  • 对于特征选择,使用无序排列/博鲁塔/ RFE,记住在不同的基于树的模型中,特征的重要性是一袋锯屑中鹦鹉的度量。
  • 作者个人意见(可能与读者意见不一致)贝叶斯优化 >随机搜索> 超视对于超参数的选取。("> " ==更好)
  • 如果您在公共排行榜上看到分数更高的公共内核,最好的处理方式是:
  1. 如果您有时间,看看有什么新内容,更新您的渠道
  2. 更少的时间-为您的验证方案重建它,运行,获得预测-并在您的集合中使用它
  3. 没有时间—只要混合您的最佳解决方案并查看分数。
  • 如何选择两个最终的提交——当然是凭直觉。但说真的,通常每个人都会实践以下方法:
  1. 保守提交(可持续模式)/风险提交。
  2. 在验证/公共排行榜上获得最高分

记住——你周围的一切都是数字,使用它们的可能性只取决于你的想象力。用分类代替回归,把序列当成图片等等。

最后:

  • 加入 ods.ai ,享受数据科学和生活带来的乐趣!

有用的链接

请注意,下面的一些材料是俄语的,

普通的

http://ods.ai/—面向那些想要加入最好的数据科学社区的人

【https://mlcourse.ai/ —尼斯机器学习课程网站

https://www.Kaggle.com/general/68205——在 Kaggle 上发布关于课程的帖子(上一个链接)

总的来说,我强烈推荐使用本文描述的方法观看系列视频 ml training(Rus),其中有许多有趣的方法和技巧。

录像

  • 关于如何成为大师的非常好的视频:帕维尔·普莱斯科夫
  • 来自Stanislav semen ov(stasg 7)的关于黑客攻击、非常规方法和目标手段编码的视频,以法国巴黎银行竞赛为例
  • 斯坦尼斯拉夫斯基的另一个视频《卡格尔教什么》

课程

你可以从这个专业化 — 如何赢得数据科学竞赛:向顶尖 kaggler学习的第二个课程中学到更多在 Kaggle 上解决问题的方法和途径。

额外阅读:

  • Laurae++,XGBoost/LightGBP 参数
  • FastText —脸书文本的嵌入
  • WordBatch/FTRL/FM-FTRL —一套库来自 @anttip
  • FTRL 的另一种实现
  • 用于选择超参数的贝叶斯优化库
  • 正规化贪婪森林(RGF)库——另一种树法
  • 凯格勒模型堆叠实践指南
  • ELI5 是一个很棒的库,用于可视化来自Konstantin Lopuhin(kostia)的模型的重量
  • 功能选择:目标排列,并跟随中的链接
  • 树模型的特征重要性度量
  • 重要性为零的特征选择
  • 自动编码器简介
  • 幻灯片共享上关于 Kaggle 的演示
  • 又一个
  • 这里有很多有趣的东西
  • ka ggle 比赛获奖方案
  • ka ggle 上的数据科学术语表

结论

一般来说,数据科学的主题,特别是竞争数据科学的主题是“像原子一样永不枯竭”。在这篇文章中,作者仅仅触及了使用竞争平台提升实践技能这个主题的表面。如果你感兴趣——在 Kaggle 上注册,考察它,收集经验——写你自己的文章。好内容的数量越多,对我们大家越好!

不,作者的管道和库还没有公开。

非常感谢来自 ods.ai 的同事们:弗拉迪米尔·伊格洛维科夫(特尔瑙斯),尤里·卡什尼茨基(约尔科),瓦列里·巴布什金(文海德),阿列克谢·普龙金(普龙金 _ 阿列克谢),德米特里·彼得罗夫(德米特里 _ 彼得罗夫),阿图尔·库津(n01z3)

特别感谢Nikita Zavgorodnii(njz)—最后的校对。

也感谢阿列克谢·伊斯克洛夫和弗拉德·伊凡诺夫【命运】对翻译的修改。

感谢您的关注,希望这篇文章对某人有用。

我在ka ggle/ODS . ai:kruegger****

本文原文为俄语, 发表于 2018 年 10 月 18 日 habr.com**

使用卷积神经网络(CNN 深度学习)对乳腺癌肿瘤类型进行分类

原文:https://towardsdatascience.com/how-to-fight-breast-cancer-with-deep-learning-ab28e42e4250?source=collection_archive---------15-----------------------

在美国,八分之一的女性(约 12%)预计会在其一生中患浸润性乳腺癌,这显然是对人类的医疗保健相关挑战。早期检测肿瘤的存在和类型是避免大多数威胁生命的情况发生的关键。

高风险女性和那些表现出乳腺癌发展症状的女性可以获得乳房区域的超声波图像。有经验的肿瘤学家应该能够查看这些图像的样本,并确定是否存在肿瘤以及肿瘤的类型。

基于其特征和细胞水平行为,肿瘤被分为两种类型:良性和恶性。

Illustration explaining difference between benign and malignant tumours Image source

被检测出患有恶性肿瘤的人,建议进行治疗以治愈那些癌细胞。

随着机器学习技术的出现,特别是在可以从标记有每个图像代表的类型的图像中学习的深度神经网络的方向上,现在可以基于其超声图像以高精度自动识别一种类型的肿瘤。

错误识别肿瘤类型的后果

如果医生将肿瘤错误地分类为良性而不是恶性,而实际上肿瘤是恶性的,并且选择不建议患者接受治疗,那么随着时间的推移,细胞转移到更大形式或扩散到身体其他部位的风险很大。这可能会导致威胁患者生命的情况。在统计学术语中,这将被认为是医生犯了“1 型”错误,即患者患有恶性肿瘤,但她没有被确定为患有该肿瘤。

考虑到这种可能性,如果医生保守地建议每一个患有肿瘤的患者进行癌症治愈治疗,不管他们是良性还是恶性肿瘤,那么一些患者就有遭受不必要的精神创伤和与治疗相关的其他费用的风险。在良性肿瘤的情况下,即使患者不选择接受治疗,也可以正常生活,而不会出现任何威胁生命的症状。医生的这种错误被认为是统计学意义上的“2 型”错误:患者没有恶性肿瘤,但被确定为患有恶性肿瘤。

我们还必须明白,在这种情况下,医生犯第二类错误比犯第一类错误更容易接受。在这种情况下,犯 1 型错误会给患者带来威胁生命的并发症,而 2 型错误会给患者带来不必要的费用和情感负担。

同样重要的是将所有患有恶性肿瘤的患者识别为患有恶性肿瘤。假设患有恶性肿瘤的患者为真阳性病例,敏感性是患有恶性肿瘤的人中通过测试被正确识别为患有恶性肿瘤的比例。

如果我们选择关注良性肿瘤患者免于不必要的治疗费用,我们必须评估诊断测试的特异性。特异性是没有恶性肿瘤的人被确定为没有恶性肿瘤的比例。

理想的肿瘤类型诊断测试将具有 1 的特异性和敏感性分数。

卷积神经网络非常适合于图像识别等应用,使用卷积神经网络可以根据肿瘤的超声图像确定肿瘤的类型。

为了探索和展示如何使用这种技术,我使用本页的提供的数据集进行了一个小实验。数据集包含 250 个肿瘤的超声灰度图像,其中 100 个为良性,150 个为恶性。

这是一些在数据集中发现的良性肿瘤的样本图像。

Ultrasonic images of Benign Tumours in breast

下面是一些在数据集中发现的恶性肿瘤样本。

Sample ultrasonic images of malignant tumours in breast

尽管与训练通常具有大量要调整的权重的神经网络所需的数据量相比,该数据集非常小,但是通过向神经网络提供分配用于训练目的的图像的随机失真,可以训练高度准确的深度学习神经网络模型,该模型可以将肿瘤类型分类为良性或恶性,具有相似的数据集质量。

训练图像数据可以通过轻微旋转、翻转、完全变换、拉伸来扩充,然后馈送到网络用于学习。这种技术有助于神经网络能够很好地进行归纳,以便在测试过程中正确地对看不见的图像进行分类。

Python 中用于构建神经网络的 Keras 库有一个非常有用的类,名为 ImageDataGenerator ,它有助于在将图像训练或测试到模型之前将这种转换应用到图像。

我将原始图像数据集分成三组:训练、验证和测试,比例为 7:2:1。只有训练和验证数据集是用 ImageDataGenerator 扩充的。

卷积神经网络的体系结构

CNN 的核心是一个多层感知器,由三种主要的层组成。

This how output of convolution operation from specific kernel is calculated

卷积层

在这些层中,检测边缘、形状和对象等过滤器的过滤器被应用于前一层,该前一层可以是原始输入图像层或深层 CNN 中的其他特征地图。在这一层,我们必须指定网络的重要超参数:用于过滤前一层的核的数量和大小。

This is how kernel moves with stride value = 2 and extra padding added around the border to apply convolutional to points located at the boundary of layer.

卷积层的另外两个参数是步幅和填充。在计算该层的下一个输出之前,步距控制内核的移动量。填充控制是否在输入层的边界上添加额外的虚拟输入点,以便应用滤波器后的结果输出与前一层相比保持相同的大小或从边界收缩。

汇集层

它降低了维度并消除了来自前一层的噪声激活。对于给定位置,可以通过计算从前一层连接到内核的输入的最大值或平均值来完成汇集操作。Max pooling 在应用程序中更受欢迎,因为它消除了干扰,而不会影响层的激活值。

展平层

它将 2D 或更高维度的前一层转换成一维向量,这更适合作为全连接层的输入。

Fully connected hidden layers

全连接层

这用于学习非线性决策边界,以便在以简单前馈方式紧密连接到前一层的层的帮助下执行分类任务。

Comparison of Standard Neural network and the one with dropout applied

Effect of dropout layer on the nodes in preceding layer during training and test

脱落层

在这里,我们还可以在完全连接的层之间包括脱落层。它在训练阶段随机避开来自前一层的某一部分节点的输出,并在预测阶段按比例抑制相同部分的激活。如果没有丢弃层,隐藏层中只有一小部分节点通过更新连接它们的边的权重从训练中学习,而其他节点通过在训练阶段不更新它们的边权重而“保持空闲”。在训练阶段,Dropout 通过随机避开来自前一层的特定部分节点的所有连接来强制所有边进行学习。为了在预测阶段保持类似的效果,来自先前层的所有激活都以与丢失分数相同的比例衰减。这种特殊的技术使得神经网络在最近几年变得更深更广,而不用担心一些节点和边处于空闲状态。总的来说,这种技术通过帮助 generalise 在测试阶段以更高的精度更好地分类更多看不见的案例来防止网络的过度拟合。

隐藏层通过重新激活层以仅允许正激活通过下一层。念此为理。

输出节点是一个 sigmoid 激活函数,对于从负到正的输入范围,它从 0 到 1 平滑变化。

我在 Keras 中创建了一个神经网络模型,用 Python 中的以下代码解决了这个问题。

def generate_model():model = Sequential()model.add(Conv2D(64, (3, 3), input_shape=input_shape, padding='same'))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3,3)))model.add(Activation('relu'))model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten())model.add(Dense(64))model.add(Activation('relu'))model.add(Dropout(0.5)) model.add(Dense(64))model.add(Activation('relu'))model.add(Dropout(0.5)) model.add(Dense(1))model.add(Activation('sigmoid'))    model.compile(loss='binary_crossentropy',optimizer=keras.optimizers.Adam(),metrics=['accuracy', sensitivity, specificity, fmed, f1])return model# Training Modelnum_train_samples = 10000
num_validation_samples = 1000
batch_size = 32
model = generate_model()
history_val_fmed = model.fit_generator(train_generator,steps_per_epoch= num_train_samples // batch_size,validation_data=validation_generator,validation_steps= num_validation_samples // batch_size,epochs=1000, verbose=1,callbacks=[EarlyStopping(monitor='val_fmed', mode="max", verbose=1, patience=50),ModelCheckpoint(data_dir + '/nn_best_model_cv_val_fmed.h5', monitor='val_fmed', mode="max", verbose=1, save_best_only=True)],class_weight=class_weights)

决定模型的复杂性

各种参数,如卷积层中的滤波器数量、滤波器大小和全连接层中的节点数量,决定了模型的复杂性和学习能力。在创建具有这些参数的一些值的模型并通过一些时期训练该模型之后,如果我们注意到训练误差和验证误差/损失都没有开始减小,那么这可能意味着该模型具有高偏差,因为它太简单,并且不能在问题的复杂程度上学习以准确地对训练集中的模型进行分类。在这种情况下,我们可以尝试增加模型的复杂性,例如通过在卷积层中使用更多数量和大小的滤波器,以及在全连接层中使用更多节点。

另一方面,如果我们注意到模型在训练集上做得非常好,即训练数据值的误差/损失随着模型通过更多数量的时期学习而保持下降,但是验证数据的误差/损失显著滞后或者根本没有下降,即在相同数量的时期之后保持相对显著地高于误差/损失训练数据集,则这意味着模型过度拟合训练数据集。它有很高的方差。通过减少卷积层中滤波器的数量和/或大小以及减少全连接层中节点的数量来降低模型的复杂性,有助于使验证集上的误差/损失值与训练集上的误差/损失值一样快。

用类权重处理数据不平衡

由于良性肿瘤与恶性肿瘤的样本数量比为 2:3,因此在拟合模型时,我使用了 Keras 的类别权重特征,通过为每个类别的训练样本分配不同的权重,将两个类别同等对待。

批量的重要性

将输入的训练数据分批送入神经网络。根据经验,建议将输入的批量大小保持在 32–512 之间。在神经网络训练中,在一个时期完成后更新权重。批量越大,训练越快,但是在训练和测试集上获得的总体准确度越低。你可以在这里阅读更多。

尽早停止训练并将最佳模型保存为检查点

在训练神经网络时,在称为时期的循环中训练神经网络是一种实践,其中相同或扩充的训练数据用于重复训练神经网络。这提高了神经网络在训练和验证数据集上的性能,直到一定数量的时期。在此之后,训练数据的准确性不断提高,而验证数据开始下降。这在神经网络中称为过拟合。为了防止这种情况发生,我们可以在每个时期完成后,在验证数据集上测量对我们重要的评估指标。我们可以保存最后的最好成绩,并耐心等待一定次数,以便在训练后得到提高。此外,由具有新的最佳性能测量的模型学习的权重可以被保存为模型的检查点。每次有改进,patience就被认为是复位到满。如果经过patience指定的次数后网络性能没有改善,我们可以停止用更多的次数训练模型。小patience可以在未成熟阶段停止训练模型。建议对就地保存模型检查点具有更高的耐心,以保存在搜索更好的模型中迄今为止看到的最佳性能模型的参数。通过这样做,我们可以得到参数最接近最优的模型,同时避免我们的模型过度拟合。

在处理扩充的训练样本时,我们还需要决定每个历元中用于训练的样本数量。较高的数字导致每个时期更多的训练,但是它可以降低管理性能改进和防止过度拟合之间的折衷的粒度。换句话说,对于单个时期中的大量样本,即使单个或几个额外时期也可能导致高度过度拟合的神经网络。

正如我前面提到的,我们模型的敏感性和特异性都是衡量其性能的重要指标。我们希望最大化这两者。因此,我选择使用自定义评估指标,该指标将在每个时期后进行评估,并基于其改进,决定是否提前停止训练神经网络。我把它叫做 F_med

注意,它类似于在信息检索任务中用于测量其质量的 F1 分数的构造。但是请注意,精确度和特异性在概念上是不同的,而敏感度和召回率在概念上是相同的。

我选择保持每个时期的样本大小为 10,000。在每个时期之后,在样本量为 1000 的验证数据集上测试神经网络的性能,用于评估指标,如灵敏度、特异性、验证损失、验证准确性、F_med 和 f 1。我选择用 50 的耐心尝试最多 1000 个纪元。在我的例子中,在模型开始显示出过度拟合的迹象之前,花了大约 300 个历元,并且使用 Keras 的 EarlyStopping 回调在该点停止训练。训练集上的 F_med 为 0.9617,验证集上的 F _ med 为 0.9733。

通过历元训练模型时,模型性能会发生什么变化?

使用 Adam Optimizer

这是模型性能图与时期的关系。

评估在 Adam optimiser 上对看不见的测试数据训练的最佳执行模型,在 25 个图像的测试数据集(即原始数据集的 10%)上证明了 0.8666 的灵敏度和 0.9 的特异性。

采用 SGD 优化器和内斯特罗夫动量

评估在 SGD +内斯特罗夫动量优化器上对未知测试数据训练的最佳执行模型,在 25 个图像的测试数据集(即原始数据集的 10%)上证明了 0.9333 的灵敏度和 1.0 的特异性。

这里有项目笔记本和 Github 代码库。

更多探索的方向

在这个实验中,我使用了一个小的乳腺癌肿瘤超声图像数据集来快速概述使用卷积神经网络处理癌症肿瘤类型检测问题的技术。

还有一些公开可用的数据集,包含组织病理学图像格式的乳腺细胞图像。数据集更大,图像也有多个颜色通道。感兴趣的读者也可以利用这些数据集来训练神经网络,该网络可以根据图像标签的可用性将图像分类为乳腺癌的各种亚型。

[## 乳房组织病理学图像

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/paultimothymooney/breast-histopathology-images) [## BreakHis

下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…

www.kaggle.com](https://www.kaggle.com/ambarish/breakhis)

这里有一些研究论文集中在 BreakHis 数据集,用于将肿瘤分类为乳腺癌肿瘤的 8 种常见亚型之一。

https://www . science direct . com/science/article/pii/s 0925231219313128

[## 基于深度学习的乳腺癌组织病理学图像分析

乳腺癌是世界上发病率最高的癌症,并且已经成为主要的癌症

www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6390493/)

我希望你发现这篇文章很有见地,可以帮助你开始探索和应用卷积神经网络来基于图像对乳腺癌类型进行分类的方向。就像你一样,我非常兴奋地看到临床世界采用人工智能和机器学习的现代进步来解决人类面临的挑战。

如何通过列值过滤熊猫数据帧的行

原文:https://towardsdatascience.com/how-to-filter-rows-of-a-pandas-dataframe-by-column-value-51996ea621f8?source=collection_archive---------1-----------------------

过滤行的两种简单方法

Image Courtesy of Peter Oslanec via Unsplash

通常需要根据列值过滤表格数据。我们可能会看到一个表格,并希望执行自定义过滤操作。幸运的是,我们可以利用熊猫来做这个手术。Pandas 是一个用于数据分析的开源 Python 库。它使 Python 能够处理类似电子表格的数据,实现快速文件加载和操作等功能。为了实现这些特性,Pandas 向 Python 引入了两种数据类型:Series 和 DataFrame。

本教程将重点介绍通过列值过滤数据帧的两种简单方法。

以下示例是 BLAST 搜索的结果。在生物信息学中,BLAST(基本局部比对搜索工具)是一种用于比较一级生物序列信息的算法,例如蛋白质的氨基酸序列或 DNA 和/或 RNA 序列的核苷酸。这个表有一个用数字表示的查询序列的 ID 和与之匹配的物种,以及其他元数据。

这个例子完全是任意的,下面的技术可以应用于大量的其他情况。

首先,我们导入 pandas 库,并给它起别名 pd

然后我使用熊猫 read_csv() 函数读取我的数据帧。我用文件扩展名保存了我的数据帧。csv(逗号分隔值文件)。接下来,我执行一些基本操作来熟悉数据帧。下面显示的是我常用的三种操作。其中包括:使用 head 方法打印前 5 行,使用 DataFrame 对象的 column 属性访问列名。最后,我查看 DataFrame 对象的 shape 属性。

这三个打印函数的输出如下所示(为了增强表示,我建议对 Jupyter 笔记本运行相同的代码,这将把 pandas DataFrame 对象显示为一个更加浏览器友好的 HTML 表)。shape 属性返回一个元组,该元组在逗号的左侧给出行数,在右侧给出列数。该数据帧有 29 行和 5 列。但是请注意,只显示前 5 行。

假设我们想要过滤该数据帧,以便排除Species _ name _ blast _ hit列中的任何“细菌”条目。

我们将如何着手做这件事?

我将介绍两种选择性过滤表格数据的方法。

首先,我创建了一个布尔值的 Python 列表。然后,我编写了一个 for 循环,该循环迭代熊猫系列(系列是数据帧中的一列)。熊猫系列,Species _ name _ blast _ hit是一个可迭代的对象,就像一个列表。然后,我在条件语句中使用一个基本的正则表达式,如果“细菌”不在序列值中,则附加 True,如果“细菌”存在,则附加 False。当我打印布尔列表的前 5 个条目时,所有的结果都为真。

这完全在意料之中,我们从前面的表格中可以看到, 中的前 5 个条目 Species_name_blast_hit 名称中没有细菌。

这里,我创建了一个布尔列表,其长度与 DataFrame,29 相同。接下来,我将布尔列表转换成 Pandas 系列,并给它分配变量名 Filtered。

您可以通过向 pd 传递一个列表来创建一个熊猫系列。系列()功能。

接下来,我对我的原始 Pandas 数据帧使用布尔子集/索引,使用方括号符号 Blast,并为新数据帧分配变量名 New_blast_df 。在这里,我写了原始的 DataFrame,Blast,后面是方括号,里面是经过过滤的熊猫系列。该系列指示选择哪些行,因为它由真值和假值组成,这些值与 Blast 数据集中的行相对应。

从 Jupyter 笔记本输出中可以清楚地看到,所有的“细菌”条目都被忽略了!

我们可以通过检查从原始数据帧中删除的行数,从 shape 属性返回的 New_blast_df 的第一个索引中减去 shape 属性返回的元组的第一个索引。现在,我们可以看到删除了 8 行。

幸运的是,还有一种更简单的方法可以通过列值来划分数据帧的子集。对于这个例子,让我们假设我们只想要包含那些包含物种名‘Phoxinus’的行。

这种方式使用了 包含 的方法。 包含 方法返回一个布尔数组,如果每个字符串都包含该模式。要使用它,您需要输入 DataFrame 的名称,然后使用点标记法选择感兴趣的适当列名,接下来是。str 和最后的 包含 ()。contains 方法还可以找到部分名称条目,因此非常灵活。

默认情况下. str.contains 区分大小写。要忽略大小写,只需将关键字参数 case 设置为 False,. str.contains(case=False)。这进一步增加了灵活性,但必须谨慎使用。

结论

本教程演示了两种基于列值过滤表格数据的方法。虽然这里给出的例子利用了单个条件,但是可以容易地应用多个条件来进一步微调滤波输出。

如何找到黑盒模型的特征重要性?

原文:https://towardsdatascience.com/how-to-find-feature-importances-for-blackbox-models-c418b694659d?source=collection_archive---------17-----------------------

Source: DavidRockDesign, Randomness-the lifeblood of many algorithms

DS 算法

置换重要性作为一种特征选择方法

数据科学是对算法的研究。

我每天都在努力学习许多算法,所以我想列出一些最常见和最常用的算法,这些算法将在这个新的 DS 算法系列中使用。

有多少次,当你创建了很多功能,然后你需要想办法减少功能的数量?

上次我写了一篇名为“每个数据科学家都应该知道的 5 种特征选择算法”的文章,其中我谈到了使用相关性或基于树的方法,并在特征选择过程中添加一些结构。

最近,有人向我介绍了另一种新颖的特征选择方式,叫做 排列重要性 ,我非常喜欢这种方式。

因此,这篇文章解释了排列重要性是如何工作的,以及我们如何用 ELI5 来编码它。

什么是排列重要性?

简单地说,我们可以根据我们的评估指标(F1、准确性 AUC 等)来确定某个特征的重要性。)在我们从数据集中移除特定要素时会发生变化。

这可能非常简单—我们从数据集中移除一个要素,训练分类器,然后查看评估指标如何变化。我们对所有功能都这样做。

因此,我们至少拟合我们的模型 n 次,其中 n 是模型中特征的数量。这是如此多的工作和计算。 我们能做得更好吗?

Source: We permute a feature and predict using the updated dataset. Intuitively, if our accuracy or any evaluation metric doesn’t take a hit, we can say that the feature is not important. If our accuracy does take a hit, we consider this feature important.

是的,我们可以。为了计算排列重要性,我们对单个要素的值进行混洗/排列,并使用生成的数据集进行预测。

然后,这些预测用于计算我们的评估指标。直观地说,如果我们的准确性或任何评估指标没有受到影响,我们可以说这个特性不重要。如果我们的准确性受到影响,我们认为这个特性很重要。

数据

我们将尝试使用数据集来更好地理解它。

我将使用一个足球运动员数据集,并尝试使用它找出最重要的特征。

如果你不懂足球术语,也不用担心。我会尽量把它保持在最低限度。

你可以在这个 Kaggle 内核中看到完整的代码。

一些简单的数据预处理

我们已经做了一些基本的预处理,如删除空值和一个热编码。我们还使用以下公式将问题转化为分类问题:

y = traindf['Overall']>=80

在这里,我们用高总体来代表一个伟大的球员。我们的数据集(X)如下所示,有 223 列。

train Data X

履行

1.对于 sklearn 型号

ELI5 库让我们很容易对sklearn模型使用排列重要性。首先,我们训练我们的模型。

from sklearn.ensemble import RandomForestClassifier
my_model = RandomForestClassifier(n_estimators=100,random_state=0).fit(X, y)

然后我们使用来自eli5.sklearn模块的函数PermutationImportance

from eli5.sklearn import PermutationImportance
import eli5
perm = PermutationImportance(my_model,n_iter=2).fit(X, y)
eli5.show_weights(perm, feature_names = X.columns.tolist())

结果看起来像:

这里我们注意到反应、拦截和控球是衡量一名球员水平的最重要的特征。

2.对于黑盒模型或非 sklearn 模型

我们还可以使用 eli5 来计算非 scikit-learn 模型的特征重要性。这里我们训练一个 LightGBM 模型。

import numpy as npfrom lightgbm import LGBMClassifierlgbc=LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=32, colsample_bytree=0.2,reg_alpha=3, reg_lambda=1, min_split_gain=0.01, min_child_weight=40)lgbc.fit(X,y)

我们需要为分数函数创建一个包装器来计算我们的评估指标。

from sklearn.metrics import accuracy_score#define a score function. In this case I use accuracy
def score(X, y):y_pred = lgbc.predict(X)return accuracy_score(y, y_pred)

我们现在可以使用来自eli5.permutation_importanceget_score_importances函数来获得最终的特征重要性。

from eli5.permutation_importance import get_score_importances# This function takes only numpy arrays as inputs
base_score, score_decreases = get_score_importances(score, np.array(X), y)feature_importances = np.mean(score_decreases, axis=0)

我们可以使用以下工具来查看前 5 大功能:

feature_importance_dict = {}
for i, feature_name in enumerate(X.columns):feature_importance_dict[feature_name]=feature_importances[i]print(dict(sorted(feature_importance_dict.items(), key=lambda x: x[1], reverse=True)[:5]))---------------------------------------------------------------
{'Reactions': 0.019626631422435127,'Interceptions': 0.004075114268406832,'BallControl': 0.0025001376727793235,'ShortPassing': 0.0012996310369513431,'Strength': 0.0009251610771518149}

结论

特征工程和特征选择是任何机器学习管道的关键部分。

我们力求模型的准确性,如果不一次又一次地重温这些作品,就不可能达到良好的准确性。

在这篇文章中,我试图解释排列作为一种特征选择方法的重要性。它帮助我们找到任何黑盒模型的特征重要性,不像我之前的文章中关于特征选择的技术。

如果你想了解更多关于特征工程/选择的知识,我想在 Kazanova 的高级机器学习专业化课程中喊出如何赢得数据科学竞赛:向顶级 Kagglers 学习。本课程讲述了许多使用有用的特征工程/选择技术来改进模型的直观方法。绝对推荐。

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

如何使用 MATLAB 找到线性(支持向量机)和二次分类器

原文:https://towardsdatascience.com/how-to-find-linear-svms-and-quadratic-classifiers-using-matlab-97ea7550655a?source=collection_archive---------28-----------------------

使用 YALMIP 寻找用于数据分类的分离超平面和二次超曲面的快速指南(带图片)

A pretty smart looking elliptic hyperboloid

想知道线性分类器是否可以推广到其他形状,而不仅仅是一个看起来无聊的平面(或超平面)?

是的。欢迎来到二次分类器的世界,其中两个或更多类别的数据点由二次曲面分隔开!

现在,在我们进入所有这些之前,让我们看看什么是线性分类器,以及我们如何用 MATLAB 和 Johan Lö fberg 开发的优化包 YALMIP 对它们建模。然后,在本文的后半部分,我将讨论二次分类器以及如何对它们建模。

*这篇文章的某些部分可能看起来有点过于数学化,但我会尽可能保持简单,以便在编程部分花更多的时间。

我们都从数据开始

我们从一些随机数据点开始,每个数据点在欧几里得空间中有 3 个维度。这些点来自 2 个不同的类(X & Y),我们每个类有 5 个点。

% Define some key problem parameters
nDimension = 3;
nVariable = 5;% Generate some random numbers
X = randn(nDimension, nVariable);
Y = randn(nDimension, nVariable);

*你总是可以将问题一般化到更高的维度、更多的类和更多的数据点,但在本文中我们将保持这些值较小,以保持事情简单和易于可视化。

Random data points that we have just generated in 3D-space

然后,想法是找到一个分类器,使用来自给定数据点的信息,将整个空间(在这种情况下是 3D 欧几里得空间)分成两个,其中位于一侧的所有点属于类别 X,而位于另一侧的点属于第二类别 y。

但是我们如何选择一个边界来分隔整个空间呢?快速直观的方法是使用平面。

分离超平面

超平面指的是一个子空间,它的维数比它所在的空间的维数小一。换句话说,一个超平面在一个 n 维空间中将有 n-1 维。

例如,在 2D 空间中,超平面将是 1D 线,而在 3D 空间中,超平面将仅仅是 2D 平面。

Visualisations of what a hyperplane is (Image: DeepAI)

回到我们的问题,我们想要构建一个超平面来将整个空间一分为二。特别地,我们希望超平面(仅由向量 a 和标量 b 定义)满足以下等式:

Equations that define a separating hyperplane

其中 ab ,分别是一个矢量和一个标量。

如您所见,这假设数据点的坐标之间存在某种线性关系。

然而,正如我们的本能现在可能已经告诉我们的那样,并不总是可能找到一个超平面,它会以这样一种方式完美地分隔整个空间,即只有属于 X 的点位于一侧,而属于 Y 的点位于另一侧。

尽管如此,即使这是真的情况,我们仍然希望找到最好的超平面,在某种程度上将空间一分为二,即使这意味着有一些点在错误的一边结束。

为此,我们需要在方程中引入一些误差变量(每个数据点一个),以便在定义超平面时留有余地:

Equations for a less than perfect hyperplane

类似于 ab ,这些误差变量由我们决定,用最优化的说法就是我们所说的决策变量。

现在我们的问题以这种方式定义,最佳超平面可以说是最好地减少这些误差总和的超平面。因此,我们问题的目标可以简洁地改写为:

A linear programme that when solved, provides a separating hyperplane

正如你们中的一些人现在已经注意到的,我们上面定义的问题被称为线性规划,因为它的目标函数(最小化函数)和约束条件(所有其他方程/不等式)都是线性的。

用 MATLAB 实现线性规划

回到我们离开 MATLAB 的地方,我们想使用 YALMIP 来求解我们已经定义的线性规划,以便获得一个分离超平面。

我们从定义线性规划中的决策变量开始。这需要为它们中的每一个创建一个 sdpvar 对象,然后 YALMIP 会将其识别为决策变量:

% Hyperplane variables
a = sdpvar(nDimension, 1, 'full');
b = sdpvar(1);% Error variables for points in X and in Y
xError = sdpvar(1, nVariable);
yError = sdpvar(1, nVariable);

接下来,我们继续定义问题中的约束:

% Error variables should be above 0
constraints = [xError >= 0, yError >=0];% Hyperplane constraints
constraints = [constraints, a'*X+b <= -(1-xError), a'*Y+b >= 1-yError];

最后,我们需要指定我们的目标函数:

% Minimise error values for all points in X and in Y
objective = sum(xError) + sum(yError);

定义了我们的问题,剩下的就是解决问题了!我们通过调用 optimize() 函数来实现这一点。

% Solve the linear programme
diagnosis = optimize(constraints, objective);disp(diagnosis.info); % Success/failure report

检索决策变量的值和最优目标值是容易的;它们的最佳值存储在创建它们时所在的对象中。

然而,我们需要将它们从SDP 变量转换为实际值,以访问它们的最佳值:

a = value(a);
disp('a =');
disp(a);b = value(b);
disp('b =');
disp(b);objective = value(objective);
disp('Optimal objective =');
disp(objective);

如果确实可以为您生成的随机数据点找到一个完美的超平面,您应该会得到这样的结果,其中最佳目标值正好是 0:

否则,高于 0 的目标值将指示所找到的超平面没有将 3D 空间完美地分成仅包含来自每一侧的 X 或 Y 的数据点的两个半空间。

绘制超平面

Where’s the fun in solving the problem if we don’t get to see anything?

因为我使用的例子非常简单——只有来自两个不同类的 10 个数据点的三维例子,所以很容易(也是可行的)将我们从求解线性规划中获得的结果绘制到图上。

让我们首先从绘制超平面开始。

回想一下超平面需要满足的两个方程?那么,为了画出实际的分离超平面,我们只需要画出超平面的一般方程:

General equation of a hyperplane

为此,我们将生成一些虚拟的x-坐标和y-坐标值,然后通过求解上面的等式来计算它们各自的z-坐标值。在 MATLAB 中,这看起来像这样:

% Generate x and y dummy data points
[xValuesDummy,yValuesDummy] = meshgrid(-4:0.1:4);% Solve for z
zValuesDummy = -1/a(3)*(a(1)*xValuesDummy + a(2)*yValuesDummy + b);% Plot the hyperplane
surf(xValuesDummy, yValuesDummy, zValuesDummy, 'FaceAlpha', 0.5, 'FaceColor', 'blue')% Holds the figure before displaying
hold on;

接下来,我们需要沿着每个轴检索每个数据点的坐标值,并将它们存储在相应的数组中。我们还想选择不同的颜色来绘制这两个类的数据点。

% Retrieve values of each data point along each axis
xValues = [X(1,:) Y(1,:)];
yValues = [X(2,:) Y(2,:)];
zValues = [X(3,:) Y(3,:)];% Create different colours for points from different classes
Colour = repmat([1,10],nVariable,1);
colour = Colour(:);% Plot the data points
scatter3(xValues.', yValues.', zValues.', 100, colour,'filled');

完成后,您应该能够制作出如下漂亮的 3D 图:

A perfect separating hyperplane

A hyperplane that fails to separate the data points into 2 separate half-spaces

现在,如果您不想使用超平面将空间分成两半,尤其是当您的数据似乎不是线性分布时,该怎么办?

嗯,我们可以尝试找到我们的数据点之间的非线性关系,其中一种方法是考虑将它们分开的二次函数!

分离二次曲面

什么是二次曲面?简单地说,它们是 2D 圆锥曲线(椭圆、双曲线和抛物线)的一般化形式。

I hope you find these more cool-looking than hyperplanes (Image: Saeid Pashazadeh & Mohsen Sharifi)

正如您可能已经想到的,这些形状在某些情况下可能更适合某些数据,所以让我们来试试吧!

类似于我们如何提出定义分离超平面的方程,我们需要寻找满足这些二次方程的对称矩阵 A ,向量 b 和标量 c :

Equations that define a separating quadric surface

同样,我们需要包含误差变量,以使我们的模型能够拟合无法通过二次曲面分离的数据集:

Equations for a not-so-perfect separating quadric surface

有了这些方程,我们现在可以定义我们的新问题,就像在超平面的情况下一样:

Problem to solve to find a quadric surface

用 MATLAB 求解

现在,我们的决策变量不再像我们在超平面问题中使用的那些变量,让我们看看我们应该如何定义它们,以便可以使用 YALMIP 解决它们:

% Quadric surface variables
A = sdpvar(nDimension, nDimension, 'symmetric');
b = sdpvar(nDimension, 1);
c = sdpvar(1);% Error variables for points in X and in Y
xError = sdpvar(1, nVariable);
yError = sdpvar(1, nVariable);

接下来,我们必须定义问题中的约束:

% Error variables should be above 0
constraints = [xError >= 0, yError >=0];% Quadric surface constraints
constraints = [constraints, diag(X'*A*X)'+b'*X+c<= -(1-xError), diag(Y'*A*Y)'+b'*Y+c >= 1-yError]; % We are only concerned with the diagonal entries of the nVariable x nVariable matrix

最后,我们指定问题的目标函数:

% Minimise average error values for all points in X and in Y
objective = sum(xError) + sum(yError);

现在,是时候使用我们在超平面问题中使用的同一个函数 optimize() 来解决问题了:

diagnosis = optimize(constraints, objective);disp(diagnosis.info); % Success/failure report

在成功完成算法后,我们检索最优决策变量和最优目标值。

A perfect separating quadric surface is found!

绘制二次曲面

A hyperboloid that separates the two data classes

与我们在上一节中绘制超平面的方式不同,我们需要采用一种稍微不同的方法来绘制二次曲面。

我们首先在整个绘图区域生成虚拟的 x、y 和 z 值,当使用函数 isosurface() 时,这些值将用于求解一般的二次曲面方程。 lhs 表示将用作函数第 4 个参数的等式左侧,而 0 表示用作第 5 个参数的等式右侧。

General equation of a quadric surface

% Generate x, y and z dummy data points
[xValuesDummy,yValuesDummy,zValuesDummy]= meshgrid(-5:0.05:5); q1 = A(1,1)*xValuesDummy+A(2,1)*yValuesDummy+A(3,1)*zValuesDummy;
q2 = A(1,2)*xValuesDummy+A(2,2)*yValuesDummy+A(3,2)*zValuesDummy;
q3 = A(1,3)*xValuesDummy+A(2,3)*yValuesDummy+A(3,3)*zValuesDummy;lhs = q1.*xValuesDummy+q2.*yValuesDummy+q3.*zValuesDummy+b(1)*xValuesDummy+b(2)*yValuesDummy+b(3)*zValuesDummy + c; isosurface(xValuesDummy,yValuesDummy,zValuesDummy,lhs,0);hold on;

最后但同样重要的是,我们将绘制两个类中发现的单个数据点:

% Plot data points
xValues = [X(1,:) Y(1,:)];
yValues = [X(2,:) Y(2,:)];
zValues = [X(3,:) Y(3,:)];Colour = repmat([1,10],nVariable,1);
colour = Colour(:);scatter3(xValues', yValues', zValues', 25, colour,'filled');

瞧,你完成了!这将允许您生成各种二次曲面,将您的数据点分隔在醒目的图中,如下所示:

2-sheet hyperboloid

Hyperbolic paraboloid (or saddle)

Hyperbolic cylinder

当然,如果生成的任何二次曲面未能完美分离所有数据点,也不必过于惊慌。就像在超平面的情况下,不可能总是找到适合每个可能的数据集的完美解决方案。

结论

我刚刚向您展示了如何使用 MATLAB 和 YALMIP 不仅可以找到而且可以绘制分离超平面和二次曲面以进行数据分类。

然而,重要的是要记住,我给出的例子非常简单,当然可以推广到更高维度和更大数量。尽管这些问题仍然很容易解决,但是如果数据大于三维,就很难用同样的方式显示所有的数据。

我希望你已经对各种功能和情节玩得很开心了,非常感谢你阅读我的文章,如果你设法一直做到这里的话!

如何从概率密度图中找到概率

原文:https://towardsdatascience.com/how-to-find-probability-from-probability-density-plots-7c392b218bab?source=collection_archive---------5-----------------------

通过知道一个范围内的实际概率来理解数据的分布

在进一步发展之前,让我们面对它。

如果您已经在数据科学领域工作了一段时间,那么您可能已经制作了概率密度图(如下所示)来了解数据的总体分布。

(Source)

嗯…首先,什么是密度图?Will Koehrsen 给出了一个伟大而清晰的解释:

密度图是根据数据估计的直方图的平滑、连续版本。

最常见的估计形式被称为核密度估计 (KDE)。

在这种方法中,在每个单独的数据点绘制一条连续的曲线(内核),然后将所有这些曲线加在一起,进行一次平滑的密度估计。

最常用的内核是一个高斯(它在每个数据点产生一个高斯钟形曲线)

概率密度图简单地表示概率密度函数(Y 轴)对变量数据点(X 轴)的密度图。

通常,概率密度图用于了解连续变量的数据分布,我们希望知道获得连续变量可以假设的数值范围的可能性(或概率)。

但问题是。

通过显示概率密度图,我们只能直观地了解数据的分布,而不知道某一范围值的确切概率。

换句话说,仅仅看图很难量化曲线下的概率。

然而,得到曲线下的确切概率是极其重要的(我会在下一节告诉你为什么),尤其是当你向商业利益相关者陈述的时候。**

在本文中,我将向您展示我用来计算概率的完整代码,并一步一步地向您解释您如何也能这样做。

在本文结束时,我希望您能够通过计算一系列值中的实际概率来更好地理解数据的分布,并随后能够用您的见解说服利益相关者。

你可以从我的 GitHub 获取数据集和 jupyter 笔记本。

我们开始吧!

为什么概率密度图说服力不够?

从视觉上回顾上面的密度图,你可能会得出一个结论,阿拉斯加航空公司的航班往往比联合航空公司更早。

想象一下,现在你的老板问了这个问题,并质疑你的说法,“阿拉斯加航空公司的航班比联合航空公司的航班早多少,发生这种情况的几率有多高?你有什么数字证据证明你的结论是正确的吗?”****

你惊呆了。因为结论来自于你对数据整体分布的观察。

更糟糕的是,现在你没有任何数字证据——确切的概率——来支持你的说法。

你没有做好充分的准备,如果你不能证明自己的观点,你作为数据科学家的可信度就会立刻下降。

这就是从概率密度图计算概率的重要性所在。

不幸的是,如果你使用 Seaborn 来制作使用distplot的密度图,很难计算概率。

在花了一些时间弄清楚如何计算概率之后,我决定使用来自sklearnKernelDensity

这个方法非常有效,我很高兴能和你分享这个!👇🏻

下面是如何从概率密度图中找到概率

我们将使用小费数据,它由一些可能影响餐馆中顾客给小费数量的因素组成。你可以在这里得到数据。

Tips data loaded in a dataframe

因为我们的目标是从密度图中找到概率,所以为了简单起见,我们将集中回答一个问题— 顾客在午餐/晚餐时间会给更多小费吗?

由于数据已经足够清晰,因此我们可以开始绘制密度图并直接计算各自的概率值。

对于以下步骤,请参考笔记本了解所用功能的完整代码实现。

1.绘制概率密度图

Function to make probability density plots without using Seaborn

由于 Seaborn 没有提供任何从 KDE 计算概率的功能,因此代码遵循这 3 个步骤(如下)来绘制概率密度图,并输出 KDE 对象来计算概率。

  • 绘制标准化直方图
  • 执行核密度估计(KDE)
  • 绘图概率密度

Probability density plot of tips amount (USD) given by customers

现在我们有了午餐和晚餐时间小费数量的概率密度图来进行比较。

仅从顾客给的 1-3 美元的小费来看,我们可以得出这样的结论:与晚餐时间相比,的顾客更倾向于在午餐时间给 1-3 美元的小费。****

同样,为了有数字证据(也称为概率值)来加强我们的陈述,让我们计算一下顾客在午餐和晚餐时间给 1-3 美元小费的概率,以作比较。

2.计算概率

Function to calculate probability

一旦我们使用函数plot_prob_density绘制了概率密度图,我们将使用这个函数的输出 KDE 对象作为输入来使用下一个函数get_probability计算概率。

Calculate and output probability

现在你知道了!

标准化密度曲线下的概率总和总是等于 1。由于概率是曲线下的面积,因此我们可以指定一个值范围(本例中为 1-3 美元小费)来计算该范围内的概率。

因此,概率就是概率密度值(Y 轴)和小费数量(X 轴)的乘积。

乘法在每个评估点上完成,然后将这些相乘的值相加,以计算最终概率。

计算出的概率证明支持了我们最初的说法——与晚餐时间相比,顾客倾向于在午餐时间给 1-3 美元的小费,概率为 63%比 49%。****

最后的想法

Photo credit: Campaign Creators

感谢您的阅读。

我希望这篇文章能让你对概率密度图有更好的理解,最重要的是,向你展示如何计算概率密度曲线下值范围内的实际概率。

计算概率相当简单,但并不简单。它确实起到了至关重要的作用让利益相关者更好地理解你的概率密度图,从而根据数字证据而不是主观和模糊的观察提出可行的见解。

一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄

关于作者

Admond Lee 目前是东南亚排名第一的商业银行 API 平台【Staq】的联合创始人/首席技术官。

想要获得免费的每周数据科学和创业见解吗?

加入 Admond 的电子邮件简讯——Hustle Hub,每周他都会在那里分享可行的数据科学职业技巧、错误&以及从创建他的初创公司 Staq 中学到的东西。

你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。

** [## 阿德蒙德·李

让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。

www.admondlee.com](https://www.admondlee.com/)**

如何用 spaCy 和 StanfordNLP 寻找最短依赖路径

原文:https://towardsdatascience.com/how-to-find-shortest-dependency-path-with-spacy-and-stanfordnlp-539d45d28239?source=collection_archive---------7-----------------------

最短依赖路径是关系抽取中常用的方法

Photo by Caleb Jones on Unsplash

TL;速度三角形定位法(dead reckoning)

考虑到文档和依赖解析的准确性,我推荐使用 spaCy 而不是 StanfordNLP。

内容结构如下。

  • 什么是最短依赖路径(SDP)?
  • 用空间寻找最短依赖路径
  • 用 StanfordNLP 查找最短依赖路径

什么是最短依赖路径(SDP)?

语义依存句法分析曾被频繁地用于剖析句子和捕获单词的语义信息,这些语义信息在上下文中靠近,而在句子距离较远的地方靠近

要提取两个实体之间的关系,最直接的方法是使用 SDP。使用 SDP 的动机是基于这样的观察实体之间的 SDP 通常包含识别它们关系的必要信息。

A dependency tree example

Convulsions that occur after DTaP are caused by a fever.

在上图中,方括号中的单词是标记的实体。红色虚线箭头表示两个实体之间的 SDP

用空间寻找最短依赖路径

首先,在终端中安装必要的库。为了清晰起见,我添加了版本号。

pip install spacy==2.1.4
python -m spacy download en_core_web_smpip install stanfordnlp==0.2.0
pip install networkx==2.3

首先,我们按照官方教程打印出所有的依赖标签。

import spacy
import networkx as nxnlp = spacy.load("en_core_web_sm")doc = nlp(u'Convulsions that occur after DTaP are caused by a fever.')for token in doc:print((token.head.text, token.text, token.dep_))# output: (head, current_token, dep_relation)
('caused', 'Convulsions', 'nsubjpass')
('occur', 'that', 'nsubj')
('Convulsions', 'occur', 'relcl')
('occur', 'after', 'prep')
('caused', 'DTaP', 'nsubjpass')
('caused', 'are', 'auxpass')
('caused', 'caused', 'ROOT')
('caused', 'by', 'agent')
('fever', 'a', 'det')
('by', 'fever', 'pobj')
('caused', '.', 'punct')

我们可以通过方便的空间可视化工具绘制整个依赖树。

下面的代码可以给 SDP

import spacy
import networkx as nxnlp = spacy.load("en_core_web_sm")doc = nlp(u'Convulsions that occur after DTaP are caused by a fever.')print('sentence:'.format(doc))# Load spacy's dependency tree into a networkx graph
edges = []
for token in doc:for child in token.children:edges.append(('{0}'.format(token.lower_),'{0}'.format(child.lower_)))graph = nx.Graph(edges)# Get the length and path
entity1 = 'Convulsions'.lower()
entity2 = 'fever'print(nx.**shortest_path_length**(graph, source=entity1, target=entity2))
print(nx.**shortest_path**(graph, source=entity1, target=entity2))

edges如下图所示。

In [6]: edges
Out[6]:
[('convulsions', 'occur'),('occur', 'that'),('occur', 'after'),('caused', 'convulsions'),('caused', 'dtap'),('caused', 'are'),('caused', 'by'),('caused', '.'),('by', 'fever'),('fever', 'a')]

输出如下

3
['convulsions', 'caused', 'by', 'fever']

这意味着从“抽搐”到“发烧”的 SDP 长度为 3。

如果你不想使用 networkx 库,而只使用 spaCy,你可以查看我的另一个帖子,用 spaCy 找到最低公共祖先最短依赖路径

用 StanfordNLP 查找最短依赖路径

首先,我们按照官方教程打印出所有的依赖标签。

import stanfordnlpstanfordnlp.download('en')
nlp = stanfordnlp.Pipeline()doc = nlp('Convulsions that occur after DTaP are caused by a fever.')
doc.sentences[0].print_dependencies()# output: (current_token, head_index, dep_relation)
('Convulsions', '0', 'root')
('that', '3', 'nsubj')
('occur', '1', 'acl:relcl')
('after', '7', 'mark')
('DTaP', '7', 'nsubj:pass')
('are', '7', 'aux:pass')
('caused', '3', 'advcl')
('by', '10', 'case')
('a', '10', 'det')
('fever', '7', 'obl')

为了遵循 networkx 图的[(token, children), (token, children),...]格式,我们需要根据源代码修改代码。

import stanfordnlpstanfordnlp.download('en')
nlp = stanfordnlp.Pipeline()doc = nlp('Convulsions that occur after DTaP are caused by a fever.')# Load stanfordnlp's dependency tree into a networkx graph
edges = []
for token in doc.sentences[0].dependencies:if token[0].text.lower() != 'root':edges.append((token[0].text.lower(), token[2].text))graph = nx.Graph(edges)# Get the length and path
entity1 = 'Convulsions'.lower()
entity2 = 'fever'
print(nx.shortest_path_length(graph, source=entity1, target=entity2))
print(nx.shortest_path(graph, source=entity1, target=entity2))

edges如下图所示。

In [19]: edges
Out[19]:
[('occur', 'that'),('convulsions', 'occur'),('caused', 'after'),('caused', 'DTaP'),('caused', 'are'),('occur', 'caused'),('fever', 'by'),('fever', 'a'),('caused', 'fever'),('convulsions', '.')]

输出如下

3
['convulsions', 'occur', 'caused', 'fever']

即使是 StanfordNLP 计算的 SDP 长度也与 spaCy 相同。但在 SDP 中两个实体之间的词语应该是** **'caused', 'by'** 。因此,spaCy 的依赖解析精度优于 StanfordNLP。**

查看我在 中的其他帖子 一个归类视图
git hub:
BrambleXu LinkedIn:徐亮Blog:BrambleXu

参考

** [## 如何在 Python 中找到两个单词之间的最短依赖路径?

您的问题可以很容易地想象成一个图形问题,我们必须找到两个节点之间的最短路径。去…

stackoverflow.com](https://stackoverflow.com/questions/32835291/how-to-find-the-shortest-dependency-path-between-two-words-in-python) [## 基于最短依赖路径的蛋白质-蛋白质关系卷积神经网络…

生物医学关系在生物过程中起着重要的作用,在生物医学领域得到了广泛的研究。

www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4963603/)**

距离掌握数据科学又近了 1000 个小时

原文:https://towardsdatascience.com/how-to-find-time-to-learn-data-science-8b73578619f0?source=collection_archive---------26-----------------------

一年 1000 小时的学习时间,每年学习更多数据科学的简单有效的方法

数据科学、机器学习或人工智能领域正在随着不断扩展的知识领域、无数的突破和令人难以置信的创新进步而爆炸。无论是专家还是新手,管理时间以跟上变化变得越来越复杂。这篇文章对任何人都有用,比如:

  1. 有人想把职业生涯转向数据科学
  2. 数据科学专家,但希望保持其专业知识最新的人
  3. 一个是特定领域的专家,比如 NLP,他们希望转向视觉或机器人或人工智能领域的其他领域
  4. 或者想从初级数据科学家成为高级数据科学家

无论你属于哪一类,你都可以很容易地在一年中找到 1000 个小时来学习更多的东西,以实现上述目标之一。这 1000 个小时不算你在职学习或培训的时间。这 1000 小时完全是你在日常办公时间之外的额外学习活动。

那么它是如何工作的呢?这很简单,遵循以下准则

将 1000 小时分成每天、每周和每月的目标

这种分裂并不新鲜;你可能已经从许多自助大师那里听过很多次了。如果你有一个更大的目标,把它分成更小的目标块,这样你就可以有效地衡量,每天或每周跟踪。所以,如果我们用 1000 个小时除以 365(哦,是的,这是一年中的天数),大约得到 2.74 个小时。但我建议将平均每天的目标设定为 3 小时,并留出 30 天以备不时之需,那时你不会像每隔一天一样感到疯狂(比如度假或与孩子一起运动,或者只是因为深夜派对后的头痛)。休息 335 天,你平均要花 3 个小时(怎么?我们稍后会谈到这一点)。所以,335 乘以 3 等于 1005(哦,对了,还有 5 个小时的奖励)。在每周目标方面,你可以设定每周 21 小时(仍然保持这个目标,因为不是每周都一样)。同样,每月的目标是大约 90 小时。

创建一个用于计划和跟踪的跟踪器

跟踪对于检查你做得如何至关重要。你需要记录所有的学习活动,如阅读、观看视频、参加课程等。将这些计划按组或流派、内容来源、媒体、编码小时数等进行划分。适用于你的。一个电子表格将是正确的选择,这样你就可以生成一个数据透视表和总结或视觉效果,如果你需要看到你的努力在哪里。然后你需要每天更新,每周和每月跟踪,检查你的进展如何。每天、每周、每月和每年跟踪的少量样本:

买个 ANC 耳机

由于你需要有效地利用每一点时间,我强烈建议你买一个 ANC ( 主动噪音消除)耳机。Bose 和 Sony 有一个非常有效的,虽然有点贵。只要记住 ANC 耳机会是你这段旅程中最好的伴侣;因此,总是带在身边。你需要用它来观看培训或会议视频或听有声读物或数据科学解说文章在嘈杂的地方,如健身房或在公共汽车、火车等交通工具上。

旅行时间是最好的时间

我们大多数人每天都要进行大量的旅行。无论我们是去办公室还是去购物中心,大多数时候我们都是在旅行。一定要在手机上使用耳机来浏览任何视频内容或听有声读物。如果你在开车,不要使用 ANC 耳机,使用车载音乐设备来听有声读物或任何其他不太需要集中注意力的音频内容,记住生命比 1000 小时的学习目标更宝贵。

没有手机不要上厕所

是的,分秒必争,包括你在厕所的时间。我们在浴室里花了很多时间。如果你打算快速复习任何内存密集型活动(如浏览 Numpy 或 Tensorflow 2.0 备忘单),我们可以有效地利用这 5-10 分钟。我们可以使用抽认卡或像 Anki 这样的工具来快速学习。

锻炼不仅对身体有益,对大脑也有好处

如果你在健身房跑步或锻炼,你可以使用你的手机和 ANC 耳机来复习。选择一个不需要太注意的题目或科目,这个时候最适合复习。如果你经常游泳,你可以得到一个防水耳机。

在周末留出时间

如果你有固定的工作或学校/大学时间,那么在周末留出一些额外的时间。通常情况下,要在工作日达到平均 3 小时的睡眠时间是很有挑战性的,所以周末需要迎头赶上。即使在与家人、朋友和社区度过了美好时光后,你也可以在一些周末和假期坚持 7-8 小时。

在跟踪器中也包括准备时间

一项重要的活动是准备学习材料。作为一名数据科学家,我需要搜索并准备好学习材料、书籍和视频/音频课程。媒体可能是一个很好的来源(最好是付费订阅,因为这将打开一个完整的信息世界,这些信息是经过策划、增强的,并且针对你需要的特定点)。使用谷歌或其他搜索引擎来准备学习材料。对于博客甚至媒体文章,你可以转换成 PDF 文档(从 Chrome 浏览器使用打印选项,并保存为 PDF),你可以再次参考,你也可以做突出显示或另一个跟踪喜欢的日期在文件名中,等等。

像运动蔻驰一样追踪你的进度

只要你能跟踪并采取纠正措施,你的表现就会很好。就像体育教练对球员、比赛、策略、统计数据的每一个细节都有敏锐的眼光一样,你也需要虔诚地跟踪进展。千万不要把这个留到周末活动时用。每天,遵循这一点,更新信息,检查你是否达到了每日、每周的目标,或者如果你设定了子学习目标,哪些领域需要更多的学习。

使用 YouTube 获取免费内容

无论你在哪个领域或者想学什么,YouTube 都是一个很好的来源。我不能亲自参加所有的会议、训练营和大学课程,但使用 YouTube,我可以轻松做到。有令人难以置信的免费和高质量的信息。使用播放列表或为自己创建一个播放列表。你可以使用 YouTube 的海量下载软件(搜索谷歌,你会发现很多免费软件可以这样做)供以后观看。我把从 YouTube 上下载的大部分学习视频保存在我手机上的一个适当的文件夹结构中,当我在家里和办公室之间旅行时使用。你甚至可以下载 mp3 格式的 YouTube 作为你的纯音频时间。

如果可以的话,利用办公时间

你也可以利用办公时间来学习(不要把正式培训或在职学习算作这 1000 个完全额外的学习时间,这是你办公室工作相关培训和学习之外的时间)。许多组织有专门的学习系统,使他们的劳动力管理技能。许多人订阅 Udemy Business 或 Udacity 或其他一些外部或内部课程。如果你有这样的设施,充分利用这一点。除此之外,你可以在伸展手脚的间隙,读一篇 5 分钟的关于某个特定主题的中型文章。大多数时候,1-2 个小时可以来自办公时间本身。利用午休时间,不要只是坐着闲聊(许多人认为这是建立关系网)。

社交媒体不是为了有针对性的学习

是的,社交媒体包含了很多信息(其中大部分对你设定的特定目标毫无用处)。这些对放松或娱乐有好处,但大多没有任何价值,因为这些不是集中在学习上。更好地利用这段时间(不要同意我……没关系,我的意思是——至少减少并转移这段时间去学习或快速复习抽认卡)

数学落后 1000 小时

在这里,我展示了一些日常样本数据。这里有几个例子来展示一个人如何能达到 3 小时。每个人的情况不同;因此,你需要找出什么适合你。

最后一个音符

这篇文章不仅仅是理论或噱头;在过去的几年里,我个人每年持续达到 1000 小时以上。我 40 多岁了,家里有两个正在成长的孩子。如果我能做到,为什么你不能?可能不是同一个配方或配方。你需要根据你的承诺、生活方式和情况来定制。如果你觉得 1000 小时太多,那就从 500 小时开始,并根据你的进度进行调整。再次重申,准备和跟踪是成功的关键,不要忘记小休息(记住每一滴都很重要),永远不要忘记你的 ANC 耳机。

我现在很想分享爱比克泰德的一句非常著名的励志名言,瑞安·哈乐黛在他的书《障碍就是出路》中让这句话变得更加流行

“坚持,反抗”。坚持努力。抵制分心、沮丧和混乱。"

因此,只要你练习、【坚持和抵抗】,你就可以达到 1000 小时甚至更长时间,让你追求数据科学的旅程发生重大变化。

感谢阅读。你可以在@ LinkedIn 联系我。

只需每月 5 美元,就可以无限制地获取最鼓舞人心的内容…点击下面的链接,成为媒体会员,支持我的写作。谢谢大家!
https://baijayanta.medium.com/membership

如何找到你的伴侣并发展你们的关系

原文:https://towardsdatascience.com/how-to-find-your-partner-and-grow-your-relationship-ae3a31bb1ede?source=collection_archive---------12-----------------------

情人节到了。无论你是否会和某人分享这一天,你可能都想过你理想中的伴侣和关系应该是什么样子。如果你想知道关于“如何找到你的伴侣并发展你们的关系”的数据(来源在脚注中)是怎么说的,我们可以为您提供一些有用的见解。

情侣在哪里见面?

大多数情侣在工作或学校相遇,紧接着是夜总会、酒吧或私人聚会。健身房,作为遇见你的意中人的地方,几乎和在线约会服务或应用程序一样受欢迎。还有一件有趣的事情是,当同性恋者互相比较时。超过一半的同性恋夫妇说他们在酒吧或聚会上相遇,但只有不到 20%的同性恋夫妇在那里相遇。女同性恋通常在工作或学校相遇。

你有没有想过情侣们如何被介绍给彼此和他们的关系有多幸福之间是否存在依赖关系?如果你的家人给你介绍人,一定要小心。大多数通过家人认识伴侣的人后来的关系都很差或非常差。根据数据,我们还观察到勇敢是有回报的。通过自我介绍认识的夫妇比其他人更快乐。这难道不令人鼓舞吗?明天,你应该向你喜欢的人迈出第一步,这是我们的建议。

如何保持快乐?

幸福的夫妇通常表示他们的父母认可他们的伴侣。显然,知道你可以依靠家人的支持,对某人来说更容易享受一段关系。除此之外,我们还发现工作状态对一段关系的质量有很大的影响。失业的人会发现比有固定工作的人更难维持良好的关系。“对自己的爱情生活最满意”的是企业家。人们可以得出这样的结论:在享受稳定的关系之前,个人的幸福和满足感必须放在第一位。

如何白头偕老?

金钱买不到幸福。就是你经常在碰到社交媒体或者网络平台的时候看到的吧?然而,我们发现,对于 60 岁以上的人来说,金钱确实可以买到一段美好的关系。

把自己描述为非常差、差或一般的家庭平均收入是 32,000 美元。良好的人际关系平均能多挣 13,000 美元,总收入为 45,000 美元。因此,专注于你的事业一点也不自私。下一次你的伴侣抱怨你总是在办公室呆太久的时候,请随意参考我们的分析,以表明你在乎你们关系的质量。

您可以在此 自行进入 探索项目:

大家一起多找一些感悟吧!

数据集来源:
罗森菲尔德、迈克尔·j、鲁本·j·托马斯、马亚·法尔孔。2018.情侣如何相遇并在一起,wave 1,2,3:公开版 3.04,加上 wave 4 增补版 1.02 和 wave 5 增补版 1.0 和 wave 6 增补版 1.0【电脑档案】。斯坦福大学图书馆。

如何微调 GPT-2,让你可以产生长篇的创造性写作

原文:https://towardsdatascience.com/how-to-fine-tune-gpt-2-so-you-can-generate-long-form-creative-writing-7a5ae1314a61?source=collection_archive---------9-----------------------

世界上最伟大的文本生成人工智能可以成为你的写作伙伴!

自从 OpenAI 将其 GPT-2 语言模型发布到野外以来,人们一直在使用这种人工智能写作工具来生成滑稽、可怕和有趣的简短文本。

如果你想使用 GPT-2 生成包含你喜欢的主题、人物、背景和写作风格的长篇作品,你需要微调基本模型并进行大量阅读。

我可以免费教你怎么做!

Photo by Brett Jordan on Unsplash

认识一下输出先生,我的 AI 写作伙伴

我刚刚花了 18 天完成了全国小说世代挑战(NaNoGenMo),电脑生成一份 51422 字的手稿。

在这场编写和编码马拉松进行到一半的时候,我的人工智能编写伙伴产生了一位名叫输出先生的人工智能作者的这段令人惊叹(也有些令人不安)的独白:

This monstrosity of yours? The monstrosity that is being written now, by the talented and novel-obsessed AI writer you just launched against your will, is just so terribly boring, there's no way I could squeeze in one more story.I write fantasy, I write sci-fi, I write horror, I write romance, I write all sorts of nonsense. You can't even imagine how many lines I've written, how many worlds and histories I've created and twisted and broken and made to rhyme and rhyme and be the best that there ever was.

今年剩下的时间我会想办法把 Output 先生奇怪而精彩的 AI 作品融入到我自己的写作中。如果你喜欢这一段,给我发一条带有你地址的信息,我会用蜗牛邮件给你一个 Output 先生手写的故事。

在为出版商周刊撰写关于 NaNoGenMo 的文章时,我有机会与伟大的作家讨论长篇人工智能文本生成,如罗宾·斯隆、半影先生的 24 小时书店Sourdough 的作者。作为他写作项目的一部分,斯隆在他从一个比特币矿工那里购买的 GPU 上运行一个版本的 GPT-2。

Robin 告诉我,在长篇文本的生成中包含人类作者是“至关重要的”。“这基本上仍然是关于一个人的,”他解释道,并指出人类作者和人工智能语言模型之间的未来合作。“一个作家做决定,有一个计划和一些他们想对世界说的话。如果这意味着他们成为其他文本的编辑或策展人,我认为这很好,甚至很棒!”

按照罗宾的建议,我在我的 NaNoGenMo 项目中扮演了馆长。

我本可以与我的人工智能写作伙伴在不到一小时的时间内生成 5 万字,但我选择花 18 天时间阅读数百页,并将最引人注目的文本收集到一个文档中。

我还在代码中使用了前缀标签,以确保 GPT-2 模型在整个项目中专注于我最喜欢的形而上学主题。

约翰·奥诺在 Medium 上写道:“在小说的程序化生成中,一个悬而未决的问题是如何保持读者的兴趣。”。希望通过我的 NaNoGenMo 项目解决这个问题,我决定使用书写提示和回复来生成更短(可能更有趣)的部分。

我是这样做的…

Photo by Brett Jordan on Unsplash

创建一个数据集。

无论你想生成哪种形式的长篇文章,你都需要找到尽可能大的数据集。

使用谷歌的 BigQuery 工具和归档在 Pushshift.io 的 Reddit 数据的巨大档案,我在一个方便的 CSV 文件中创建了一个由个人写作提示组成的大规模数据集——每个都用< |startoftext| >和< |endoftext| >标记分隔。

我还使用了 Pushshift 的 Reddit 搜索工具来收集数百个与人工智能相关的写作提示,以添加到数据集,因为我希望我的机器人能够处理我最喜欢的科幻主题。

在这个过程的最后,我得到了一个包含 1,065,179 个标记的书写提示数据集。GPT-2 是一个大规模的语言模型,所以你需要一个相对较大的数据集来有效地调整模型。

创建另一个数据集(如果需要)。

除非你想遵循我的写作提示/回答模型,否则你只需要创建一个数据集。

我的项目需要两个数据集。使用同样的工具和大量的 Reddit 搜索,我收集了我能在网上找到的评分最高和最棒的写作提示。我添加了许多专注于人工智能的回复,包括我多年来写的我自己的写作提示回复。

在第二个训练数据集中,我得到了 1,947,763 个标记。

构建数据集。

如果你想生成任何结构的作品,这一步真的很重要。

我想给我的人工智能尽可能最整洁和高质量的学习数据,所以我使用了一系列简单的标记来教 GPT-2 书写即时反应的形状。

我添加了和标记来匹配书写提示数据集,但我也确保每个响应都有标记为[WP]的原始书写提示和标记为[RESPONSE]的响应本身。

虽然这是一个巨大的,耗时的工作,但它使我的输出更加有趣。我将整个数据集保存为. TXT 文件。这是数据集的样子:

<|startoftext|>[WP] On November 4, 2020, humanity abandons the Internet. Billions of bots have colonized the web with spam, deepfakes, and fake news. At the now deserted r/WritingPrompts, literary AIs (trained on great works of human literature) create an infinite library of prompts & responses.[RESPONSE] Zackary Blue worked as a night janitor in the basement for major financial services company. He cleaned cavernous spaces beneath the building where hundreds of millions of dollars got traded every single day.
<|endoftext|>

微调你的 GPT-2 语言模型。

微调我的两个语言模型花了几天时间。Max Woolf 教会了我这一步需要知道的一切。

重要更新: Google Colab 更新了它的标准张量流版本,你必须在 Max Woolf 的 Colab 笔记本顶部添加一行代码才能使用旧版本的张量流。只需将这行代码添加到 Colab 笔记本的顶部,Woolf 的笔记本就可以完美运行了:

%tensorflow_version 1.x

我用的是中等大小的 355M 版本的 GPT 2,因为它足够大,可以处理我的数据集,但又足够小,可以在 Google Colab 的云服务器上运行。我用 42000 步训练了这两个模型。

我将训练分成更小的部分,因为谷歌 Colab 不会跑超过 12,000 步。

使用微调后的 GPT-2 模型生成文本。

一旦我的两个语言模型被训练好,我就开始生成我的 NaNoGenMo 项目。

每天早上,我都会运行写作提示程序(Jane Doe ),生成 10-20 页由电脑生成的写作提示。

对于每次运行,我设置长度为 100 个字符,温度为 0 . 7,输出为 10 个样本。为了塑造这个项目,我使用 prefix 函数将写作提示输出指向我最喜欢的主题,如虚拟现实、模拟理论和 AI 作家。

The code from one of my many Writing Prompt Prompter runs.

除非您想遵循我的书写提示/响应模型,否则您只需要用一种语言模型生成文本。

然而,我为我的 NaNoGenMo 项目增加了一个额外的步骤。

我挑选了我最喜欢的计算机生成的写作提示,并将其输入到写作提示响应者(输出先生)中,以生成 100 至 125 页的响应。 Max Woolf 的 Google Colab 笔记本帮我编写了这一步的所有代码。

The code from one of my many Writing Prompt Responder runs.

通读你所有的输出。

我梳理了无名氏和 Output 先生生成的数百页文本,挑选了最引人注目的故事。

对于我为 NaNoGenMo 收集的每 350 个令人信服的计算机生成的文字,我都必须费力地阅读大约 10,000 个单词的奇怪、令人困惑、重复或简单易懂的计算机生成的文本。

将最好的作品收集在一个主文件中。

在 11 月,我将每天的输出存储在一个文件中。我每天晚上都会阅读那个文件,寻找引人注目的文字。这是我保存的第一批作品之一,一个乌托邦宣言:

We are a group of artists, writers, coders, and tinkerers, who have banded under the banner of Humanity v2.0\. We are a worldwide collective of similar interests. We all have the same goal - to create anew the foundations of a better world.

我建议你在电子书阅读器或平板电脑上阅读电脑生成的文本。它让你远离电脑屏幕,给你更多实际的阅读体验。我还使用了神奇的语音梦想阅读器在早上上班的时候听我的电脑生成的内容。

在这些史诗般的阅读过程中,我将最好的作品保存在一个标有“NaNoGenMo Final”的主文件中

重复这个过程,直到你有足够引人注目的写作。

之后,我在 11 月连续 17 天运行相同的文本生成步骤。我一直在我的最终文档中添加计算机生成的文本,直到我越过了 NaNoGenMo 马拉松的 50,000 字终点线。

策划你的计算机生成的创作。

一旦“NaNoGenMo Final”文档达到临界质量,我就使用强大的写作工具 Scrivener 围绕虚拟现实、人工智能写作或上帝等主题重新排列计算机生成的故事。

我只对简单的重组进行了编辑,但人类管理员可以使用这一步骤来制作章节、编辑特定段落、添加插图、撰写评论或其他任何内容!

检查抄袭和出版!

一旦我完成了最终的手稿,我就通过 Quetext 工具运行每个提示和回复,以确保我的机器人没有在网上抄袭任何人。GPT 2 号运行着一个拥有数百万篇文章的庞大数据集,但它偶尔会鹦鹉学舌。

就是这样!NaNoGenMo 是一次很棒的写作和编码体验,如果你这个月有时间,我推荐你试试。

从来没有这么多的资源可供像我这样的业余爱好者使用,GPT-2 在经过微调后确实非常强大。我将在今年余下的时间里阅读这些由 GPT-2 产生的故事。

这里是最后一个例子,人工智能作家和人类作家之间的一点联系…

They are a species apart, but they share one thing in common: their love of books. They are the ones who seek out books for their own needs, whether they be scientific, philosophical, or religious texts. They are the ones who, from the beginning, have been able to find meaning within books.

如何针对数据微调神经网络:图像分类

原文:https://towardsdatascience.com/how-to-fine-tune-your-neural-network-for-your-data-image-classification-d0f01c92300b?source=collection_archive---------10-----------------------

使用 PyTorch 从迁移学习中获得更多

Photo by Denisse Leon on Unsplash

介绍

当你没有很多数据时,建立一个用于图像分类的神经网络并不总是容易的。近年来,这一领域取得了一些重大进展,使得构建有价值的模型变得更加可能,而无需使用数百万张图像进行训练。最值得注意的是,迁移学习名列榜首。

迁移学习是从在 I mageNet 数据集上训练的大型模型中提取预先训练的权重,并使用这些权重作为不同数据集的起点。通常,这是通过替换最后一个全连接层并训练模型,同时仅更新线性层的权重并让卷积层保持它们的权重来完成的。

这种图像分类方法通常非常有效,因为卷积层(我们可以将其视为学习图像特征的模型的一部分)已经看到了许多不同的图像,并且通常在提取图像特征以传递给线性层方面做得非常好。有一些简单的方法可以让这种普遍有效的方法更好地适用于您的特定数据。

GoodReads 案例研究

数据

为了证明迁移学习的有效性以及如何在迁移学习的基础上进行改进,我使用了一个从 Goodreads 收集的数据集,这个数据集可以在 Kaggle 上找到。从这些数据中,我试图根据书籍封面的图像来预测一本书的正确类型。为了节省计算时间,我只使用了数据的子样本,并删除了所有少于 5 次观察的类型。最终的数据集有 77 种类型和近 20,000 个观察值,我们将其分为一个训练、验证和测试集(60/20/20)。

Example of book cover image

模型

在这个案例研究中,我使用了 VGG 11 网络,如下图所示。

https://www.quora.com/What-is-the-VGG-neural-network

我将对网络进行的唯一更改是用一个新的线性层替换最后一个输入为 4096、输出为 1000 的线性层,新的线性层输入为 4096、输出为 77(我们拥有的流派数量)。除此之外,网络的架构将保持不变。

对于模型的每个版本,我们保持相同的超参数,以便进行公平的比较。我使用 0.0003 的学习率,Adamax 优化器,交叉熵损失,以及 10 个时期后没有改善的早期停止。

迁移学习

如上所述,迁移学习为图像分类任务提供了巨大的收益。我们要运行的第一个测试是比较迁移学习和在没有任何预训练权重的情况下从头开始训练 VGG-11 架构。在 PyTorch 中,我们通过加载模型的预训练权重,替换最后一层,并从所有卷积层中移除梯度来实现这一点,如下所示。

现在我们可以像普通网络一样训练它。我训练并测试了我们的转移学习网络,以及我们的从头开始的网络。结果完全符合我们的预期。

Losses for transfer model vs. scratch model

Accuracy for transfer model vs. scratch model

从准确度图和损失图来看,很明显,我们的迁移学习模型比我们的从头开始模型表现得好得多。事实上,看起来我们迁移学习模型第一个时期的验证损失比我们从头开始的模型要好。除此之外,值得注意的是,传输模型达到最小验证损失只需要一半的时间。因此,传输模型在一半的时间内执行得更好。这是双赢的局面。

微调

很明显,迁移学习是有效的,我们也很好地理解了它为什么有效。该模型从图像中学习了许多特征,并根据这些特征对我们的书籍封面进行了训练。让我们快速看一下 ImageNet 到底是什么样子。

https://www.researchgate.net/figure/Examples-in-the-ImageNet-dataset_fig7_314646236

这些图像中有很多多样性,所以模型学习一般特征如此之好并不令人惊讶。如果我们看看这些数据,它看起来真的不像许多图片看起来像我们的哈利波特书的封面。有理由认为,更好地学习我们的书籍封面的特性可能有助于我们的转移模型进一步改进。

我们可以通过在训练时慢慢解冻卷积层的梯度来微调我们的传输模型,以适应我们独特的数据。首先,我们开始加载我们的模型,并以与我们第一个传输模型完全相同的方式更改最后一层。然后,在每一次训练之后,我们可以用类似这样的代码来更新网络的下一个卷积层的权重。

我们慢慢地更新渐变,从最底层开始,一直到顶层。这保留了我们的模型从预先训练的权重中获得的大量信息,同时有助于根据我们的书籍封面对其进行微调。经过训练和测试后,我们可以将其与我们的其他两个网络进行比较。

Losses for all models

Accuracy for all models

对我们的模型进行微调会使我们的原始模型获得一些适度的收益。同样,我们也看到它减少了达到最小验证损失所需的训练时间。

提示和技巧

  • 我在所有这些模型中使用了相同的超参数,试图使比较公平。实际上,在进行微调以防止过度拟合时,使用较低的学习速率(通常是递减的学习速率)通常更有效。
  • 与大多数深度学习实例一样,大量数据将使微调更加有效。
  • 同样的技术也可以用于 NLP 任务的网络。它不限于图像。

最后的想法

像这样微调一个模型并不总是能得到更好的结果,但是绝对值得尝试。这是一个很容易的调整,你可以对你的代码进行调整,这有可能为你的模型提供一个几乎没有成本的提升。

如果你想看完整的代码,你可以查看我的 github repo。数据和代码都在那里,应该可以运行。

如何预测销售收入:比较各种预测方法

原文:https://towardsdatascience.com/how-to-forecast-sales-revenue-compare-various-forecasting-approaches-7c4d69242469?source=collection_archive---------8-----------------------

预测销售额的方法有 100 多种。问题变成了选择哪一个。在本文中,我将简要介绍预测销售的流行方法,以及如何将这些方法与关键指标进行比较。根据使用案例,客户可能对平均值等简单方法满意,而其他人可能想要使用预测算法进行更精确的预测。

那么我应该使用哪种方法呢?答案很简单。计算预测值和实际值之间的误差。哪种方法的误差最小,就选择哪种方法。如果简单平均法能准确预测实际收入,就没有理由不使用它。

用例&数据定义

对于这篇文章,我将采用一家年收入为 7500 万美元的公司 2016 年至 2018 年的销售数据,并使用这些数据来预测 2019 年 1 月至 3 月的收入。我会将预测值与实际值进行比较,并计算两者之间的差异。差异最小的方法将胜出&也就是说,该方法将用于计算今年剩余时间的预测。

测量预测值与实际值之间的误差

有两种计算误差的标准方法。第一个是计算一月、二月和三月的预测值和实际值之间的差值,以达到全年的平均值。

一月预测错误= Abs(一月预测-一月实际)

二月预测误差= Abs(二月预测-二月实际)

三月预测误差= Abs(三月预测-三月实际)

平均误差=(一月预测误差+二月预测误差+三月预测误差)/ 3

使用 abs(绝对值)的原因是,有时预测值会高于实际值,也可能低于实际值。因此,当我们添加误差时,我们添加的是误差的绝对值。

上面的度量被称为平均绝对误差(MAE) 并且容易理解。

我更喜欢的一个度量标准是惩罚平均误差中没有出现的巨大差异。

为了惩罚较大的误差,我们得到每个月误差的平方,并将三个月的误差相加,得到平均值。该值的平方根是捕捉大误差的误差,称为均方根误差(RMSE)

平均平方误差= [(一月预测误差)^ 2 +(二月预测误差)^ 2+三月预测误差)^ 2 ] / 3

RMSE =的平方根(平均平方误差)

还有一个也很常见的误差是平均绝对百分比误差(MAPE) ,其中误差是一个百分比。

虽然这三种方法都是测量误差的有效方法,但我更喜欢第二种方法(RMSE),因为它会惩罚与实际值的较大偏差。

各种预测方法

让我们来看看预测销售的各种预测方法。

简单平均法

这里,我们取过去 3 年的平均值,并将其作为 2019 年 3 个月的预测。这意味着 2019 年 1 月、2 月和 3 月的预测将相同,并将等于过去 3 年的平均值。这是最简单的预测方法之一。

使用这种方法,我得到的均方根误差(RMSE)是 312500

移动平均线

这里我们取预测的移动平均值。我们可以做 6 个月移动平均线。我用的是最后一个移动平均值,并将其设置为 2019 年三个月的预测值。对 2019 年 1 月、2 月和 3 月的预测将是相同的,并将等于过去 6 个月的移动平均值。请注意,有些人可能会通过纳入 1 月份的预测来重新计算 2 月份的移动平均值。我宁愿不做那件事。我倾向于只包含预测输入的实际值。

使用这种方法,我得到的均方根误差(RMSE)是 347968

直线外推

在 2016 年 1 月和 2018 年 12 月的观察之间画一条简单的线,并在接下来的三个月里延续这条线。如果数据有一个好的趋势,这是可行的。如果数据中存在季节性,这往往表现不佳。

使用这种方法,我得到的均方根误差(RMSE)是 410171

上个月的收入与预测值一样,也就是天真的方法

2019 年 1 月、2 月和 3 月的预测将与 2018 年 12 月的收入相同。

使用这种方法,我得到的均方根误差(RMSE)是 373743

去年同月收入预测

2019 年 1 月、2 月和 3 月的预测将是 2018 年 1 月、2 月和 3 月的实际值(一年前的同一个月)

使用这种方法,我得到的均方根误差(RMSE)是 382058

将转换率应用于未结业务机会

我使用了 0.1 的转换系数,并使用每月初的开放机会来计算该月的预测。

使用这种方法,我得到的均方根误差(RMSE)是 292368

使用预测模型对机会进行评分

不要使用像 0.2 这样的历史转换系数,而是建立一个简单的分类模型来预测本月完成交易的概率。所有可能性大于 80%的交易我都在预测中做了标记。

使用这种方法,我得到的均方根误差(RMSE)是 163539

使用 Prophet 进行时间序列预测

这里我们用了 Prophet 算法,把 2016 年喂到 2018 年,来预测 2019 年三个月的营收。

使用这种方法,我得到的均方根误差(RMSE)是 132957

对比图

RMSE 越低,模型越好。

总结

从上面可以看出,对于我试图解决的销售预测问题,最后两种基于机器学习的方法比其他方法表现得更好。最初的几种方法很容易做到。如果这种准确性对于经营你的企业来说是可以接受的,那么你的情况就很好。如果需要更高的精度,最后一种方法更有益。例如,当预测订单数量或呼叫中心的呼叫数量时,这些预测与库存和人力资源投资相关联,以对预测做出反应。因此,当需要采取一项成本为$$$的行动时,客户倾向于使用具有良好精确度的方法(如上面的最后两种方法)来创建预测。

如何使用 SARIMA 模型用 Python 预测销售额

原文:https://towardsdatascience.com/how-to-forecast-sales-with-python-using-sarima-model-ba600992fa7d?source=collection_archive---------1-----------------------

从统计学和 python 到时间序列预测的分步指南

你想象过预测未来吗?嗯,我们还没有到那一步,但是预测模型(带有一定程度的不确定性)给了我们一个很好的方向,当我们展望未来时,可以更果断地规划我们的业务。在本帖中,我们将展示一种使用 SARIMA 模型预测汽车行业销售时间序列的方法。

解释模型

SARIMA 用于非平稳序列,即数据不会围绕相同的均值、方差和协方差波动。这个模型可以识别趋势和季节性,这使得它非常重要。SARIMA 由其他预测模型组成:

AR: 自回归模型(可以是简单、多元或非线性回归)

【马:】移动平均线模型。移动平均模型可以使用加权因子,其中观察值由修整因子加权(对于系列中最早的数据),并且最近的观察值具有较高的权重。

AR 和 MA 的组合一起携带 ARMA 模型,但该模型仅用于平稳序列(均值、方差随时间恒定)。

如果系列有趋势,就要用 ARIMA 型号。
ARIMA 用于非平稳系列。在该模型中,微分步骤 I (d)用于消除非平稳性。
用于微分的集成元素“I”允许该方法支持具有趋势的时间序列。但是这个模型仍然不能识别季节性。

最后,我们得到了 SARIMA 模型,它具有季节相关性,可以识别时间序列的季节性。现在我们可以去找密码了!

数据处理

我们将使用一组汽车销售数据,可以从这里下载。

import warnings
import itertools
import numpy as np
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
plt.style.use('fivethirtyeight')
import pandas as pd
import statsmodels.api as sm
import matplotlib
matplotlib.rcParams['axes.labelsize'] = 14
matplotlib.rcParams['xtick.labelsize'] = 12
matplotlib.rcParams['ytick.labelsize'] = 12
matplotlib.rcParams['text.color'] = 'G'df = pd.read_excel("Retail2.xlsx")

这一步只是导入库,比如 numpy、pandas、matplotlib 和 statsmodels,也就是包含 SARIMA 模型和其他统计特性的库。这部分代码用于设置 matplotlib 的图表。

原始数据集和代码有点复杂,但是为了使一切更容易,可供下载的文件只有一个日期和销售列,以避免数据预处理。

y = df.set_index(['Date'])
y.head(5)

set_index 命令将列 date 设置为索引,head 打印数据集的前 5 行。

y.plot(figsize=(19, 4))
plt.show()

分析图表,我们可以观察到时间序列有季节性模式。十月是销售的高峰期,至少过去三年是这样。这几年也有上升趋势。

from pylab import rcParams
rcParams['figure.figsize'] = 18, 8
decomposition = sm.tsa.seasonal_decompose(y, model='additive')
fig = decomposition.plot()
plt.show()

使用 pylab 库中的“sm.tsa.seasonal_decompose”命令,我们可以将时间序列分解为三个不同的部分:趋势、季节性和噪声。

SARIMA 到时间序列预测

我们用萨里玛吧。型号符号是SARIMA(p, d, q).(P,D,Q)m。这三个参数说明了数据中的季节性、趋势和噪声

p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]
print('Examples of parameter for SARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))

SARIMA…
的参数示例 SARIMAX: (0,0,1) x (0,0,1,12)
SARIMAX: (0,0,1) x (0,1,0,12)
SARIMAX: (0,1,0) x (0,1,1,12)
SARIMAX: (0,1,0) x (1,0,0,12)

for param in pdq:for param_seasonal in seasonal_pdq:try:mod = sm.tsa.statespace.SARIMAX(y,order=param,seasonal_order=param_seasonal,enforce_stationarity=False,enforce_invertibility=False)results = mod.fit()print('ARIMA{}x{}12 - AIC:{}'.format(param,param_seasonal,results.aic))except: continue

ARIMA(0,0,0)x(0,0,1,12)12—AIC:410.521537786262
ARIMA(0,0,0)x(1,0,0,12)12—AIC:363.03322198787765
ARIMA(0,0,0)x(1,0,1,12)12—AIC:348.1333310565

根据 Peterson,t .(2014)AIC(AK aike 信息标准)是对给定数据集的统计模型的相对质量的估计。给定一组模型的数据, AIC 估计每个模型相对于其他每个模型的质量。AIC值越低越好。我们的输出表明,AIC值为 223.43 的SARIMAX(0, 0, 1)x(1, 1, 1, 12)是最佳组合,因此我们应该认为这是最佳选择。

mod = sm.tsa.statespace.SARIMAX(y,order=(0, 0, 1),seasonal_order=(1, 1, 1, 12),enforce_stationarity=False,enforce_invertibility=False)
results = mod.fit()
print(results.summary().tables[1])

在“mod = sm.tsa.statespace.SARIMAX”命令中,我们需要设置所选的组合。

results.plot_diagnostics(figsize=(18, 8))
plt.show()

通过上述诊断,我们可以将重要信息可视化为分布和自相关函数 ACF(相关图)。值向上“0”在时间序列数据上有一些相关性。接近“1”的值表现出最强的相关性。

pred = results.get_prediction(start=pd.to_datetime('2018-06-01'), dynamic=False)
pred_ci = pred.conf_int()
ax = y['2015':].plot(label='observed')
pred.predicted_mean.plot(ax=ax, label='One-step ahead Forecast', alpha=.7, figsize=(14, 4))
ax.fill_between(pred_ci.index,pred_ci.iloc[:, 0],pred_ci.iloc[:, 1], color='k', alpha=.2)
ax.set_xlabel('Date')
ax.set_ylabel('Retail_sold')
plt.legend()
plt.show()

该步骤包括将真实值与预测值进行比较。我们的预测与真实值非常吻合。命令“pred = results . get _ prediction(start = PD . to _ datetime(' 2018–06–01 ')”确定您将预测的时间段与真实数据进行比较。

y_forecasted = pred.predicted_mean
y_truth = y['2018-06-01':]
mse = ((y_forecasted - y_truth) ** 2).mean()
print('The Mean Squared Error is {}'.format(round(mse, 2)))
print('The Root Mean Squared Error is {}'.format(round(np.sqrt(mse), 2)))

均方差为 595.97
均方根误差为 24.41

Obs:在 MSE 和 RMSE 中,值越接近零越好。它们是衡量准确性的标准。

pred_uc = results.get_forecast(steps=12)
pred_ci = pred_uc.conf_int()
ax = y.plot(label='observed', figsize=(14, 4))
pred_uc.predicted_mean.plot(ax=ax, label='Forecast')
ax.fill_between(pred_ci.index,pred_ci.iloc[:, 0],pred_ci.iloc[:, 1], color='k', alpha=.25)
ax.set_xlabel('Date')
ax.set_ylabel('Sales')
plt.legend()
plt.show()

在这里,我们预测未来 12 个月的销售额。该参数可以在代码的“pred _ UC = results . get _ forecast(steps = 12)”行修改。

y_forecasted = pred.predicted_mean
y_forecasted.head(12)

这一步显示了我们之前运行的测试的预测值。

y_truth.head(12)

这一步表明数据集的真值。我们可以比较上面的两个系列来衡量模型的准确性。

pred_ci.head(24)

在上表中,我们可以看到模型作为预测边界指示的下限值和上限值。

forecast = pred_uc.predicted_mean
forecast.head(12)

最后,这里我们有未来 12 个月的销售预测!

我们可以注意到销售随着时间的推移而增加。一月和二月是最糟糕的月份,比如最后几年。

这只是一个统计模型的实验。我真的推荐尝试递归神经网络来预测,我的建议是使用更多的数据。但这肯定是另一篇文章的主题。

参考:

Python 3 中的 ARIMA 时间序列预测指南

如何打造一个高效的人工智能团队?

原文:https://towardsdatascience.com/how-to-form-an-effective-a-i-team-bb14817910e7?source=collection_archive---------30-----------------------

19 世纪末,许多公司和企业都有高薪的电力副总裁职位。这样的职位持有者曾经被视为对一种被称为的迷人自然力有着深刻理解和控制的人。这是当时的流行语。企业和公司四处奔走,通过在工作场所的黑暗角落安装电线和电灯,使他们的运营更加合理化。随着时间的推移,所有发光的东西都被淘汰了,现在一年到头到处都有电已经不再是一个幻想了。类似的故事可以与时代的每一个重大突破性进展联系起来,无论是燃料发动机的发明,还是数字计算机在商业和个人生活中的应用。

如今,人们对用智能的人工智能解决方案来改变日常生活非常兴奋。随着像 FAANG (脸书、苹果、亚马逊、网飞和谷歌)这样的大型技术市场参与者的不断进步,这种人工智能的兴奋正在转化为一种狂热。消费者被深度学习(D.L .)驱动的图像、音频和文本数据处理产品的能力所淹没,如谷歌助手、谷歌照片、亚马逊 Alexa、亚马逊 Prime 和脸书门户。人工智能驱动的营销策略、基于机器学习的 I-o-T 解决方案和推荐系统正变得越来越普遍。许多小企业希望利用类似的机会,正在寻找将这些解决方案整合到现有软件基础设施中的方法。

小企业和初创公司大多面临资金问题,充分利用现有资源来生存变得至关重要。另一方面,人工智能的进步正在诱惑并重塑我们数字生活的方方面面。在这种情况下,设计一个紧凑的、以结果为导向的人工智能团队变得非常重要。所以问题是, 如何组建一个 5~10 人的人工智能团队,能够在 6~12 个月的时间框架内交付人工智能解决方案?这个问题的答案在于知道商业世界中人工智能的核心是什么。下面的文氏图展示了商业世界中围绕人工智能行业的各种角色,以及每个角色的核心是什么。

真正的人工智能开发的一个先决条件是对数学领域(如线性代数、概率和最优化)以及计算机技能的良好理解。从现代软件世界的当前趋势来看,这一要求也是显而易见的,在现代软件世界中,未来的开发预计不会基于硬编码程序,而是将涉及一种更加动态的数据集成方法。随着越来越多的数据流流入,未来的软件将是动态的和不断发展的。新的数据将需要新的框架、新的统计方法以及在快速变化的环境和需求下寻找最佳解决方案的现代方法。

有些角色对每个人工智能团队来说都是必不可少的,比如管理数据流、建立和训练数学模型以及理解业务需求。这些角色中的每一个角色都必须有一个或多个人。互补技能的良好平衡造就了一个适应性更强的团队,该团队能够以专注的方式完成严格限定时间的目标。从现代开发和部署平台的基本最小团队结构和能力来看,5~10 人的团队规模似乎是各种中型项目的神奇范围。以下流程图提供了特定角色及其主要职责的简要描述。根据业务团队参与的深度和开发操作的范围,可以在不同的类别中添加更多的工程师和开发人员。

人工智能的世界变化很快,这个领域有许多可能的发展方向。随着深度学习在过去几年中有望发展,技术行业巨头对此产生了巨大的兴趣。这一趋势将在未来几年渗透到其他中小型企业。这使得关键决策者了解这种转变发生的框架变得至关重要。

usmnmjd@gmail.com 穆罕默德·奥斯曼·马吉德

如何在第一份数据科学工作之前获得数据科学经验

原文:https://towardsdatascience.com/how-to-gain-data-science-experience-before-your-first-data-science-job-88bed5f9fee3?source=collection_archive---------4-----------------------

需要 3 年以上经验的入门级工作的答案

Photo by Lukas from Pexels

介绍

数据科学职业生涯中最困难的部分无疑是开始。获得第一个数据科学职位绝非易事。如果你的名字后面没有字母 PhD,那就更难了。如果你在互联网上搜索入门级的数据科学工作,你很可能会对你找到的几乎所有东西都有很高的要求感到沮丧。似乎你看到的每份工作描述都要求博士学位或至少 3 年机器学习经验。这就回避了一个问题,“没有数据科学家的经验,你怎么能胜任数据科学家的工作?”成千上万的人在线或在大学学习数据科学课程。这些课程对于培养技能很重要,但它们不会成为候选人被选中从事数据科学工作的原因。没有一种方法可以让你进入数据科学,但我想分享一些我做的事情,以获得经验,为抓住我梦想的工作做好准备。无论你是一名即将毕业的学生,还是一名打算从事数据科学的学生,都有很多方法可以获得数据科学方面的经验。

获得经验的方法

做研究

寻找机会与他人合作撰写学术论文是在数据科学的几个重要领域获得经验的绝佳机会。做研究的缺点是通常报酬不高,而且通常不涉及机器学习之类的东西。尽管如此,我还是强烈建议找机会做研究来充实你的数据科学简历。

为什么这是很好的经历

做研究应该看起来有吸引力有两大原因。首先是处理数据的机会。由于研究的性质,有机会参与数据的整个生命周期。其中一些,比如数据收集,可能并不适用于你未来的职业。其他部分,如分析和解释是有价值的技能。我想在这里强调能够解释数据并根据分析得出可靠结论的价值。这是一项至关重要的技能,但有时会被忽视,因为它很难作为一项技术技能来测试。理解如何解释结果是数据科学家和能够键入“from sk learn . ensemble import RandomForestRegressor”的人之间的区别。从事学术研究需要你完全基于数据得出结论,同样,你必须根据你的结果帮助行业做出决策。

研究也给你机会学习如何建立实验。你对实验的影响程度取决于你和谁一起工作以及有多少人一起写论文。提出一个好问题,并设置一个实验来回答它,几乎是每一篇学术论文的基础。这种技能可以很好地转化为数据科学,在数据科学中,你需要提出好的问题,并使用机器学习来回答这些问题。在至少有助于推动研究的领域获得研究经验,可以帮助你成为一名数据科学家,可以自主有效地工作,而无需有人告诉你要解决什么或如何解决。

怎么做

对于学生和非学生来说,寻找研究机会需要稍微不同的方法。我在这两个阶段都做得很成功。找到一个研究你感兴趣的东西的人是很重要的。将你的兴趣扩展到机器学习之外一秒钟,因为研究机器学习的人比研究其他学科的人少得多。一旦你决定了你想学什么,列出一份有相关兴趣的人的名单。这就是学生和非学生的不同之处。如果你是学生,我建议看你的大学。你通常可以找到一个研究助理的职位,这个职位会支付你做研究的费用。然而,这并不意味着你不应该去和那些不做招聘广告的教授交谈。仅仅一头扎进一个由 50 名研究助理组成的实验室,并不会给你与教授一对一进行研究同样的体验。如果你不是学生,我会联系任何你想联系的人。发送电子邮件解释你是谁,为什么你对他们的研究感兴趣,以及你如何看待自己的帮助。我和全国各地的一位教授一起远程工作,为研究做出贡献。真的没有限制。对每个人来说,最重要的是找到合适的衣服。找到你感兴趣的研究,你将能够为。

重写你的工作描述

在我找到一份全职工作之前,这是让我受到关注的最大帮助。秘诀是做数据科学不一定要有数据科学家这个职称。无论你现在在哪里工作,无论是实习还是全职,找个机会尝试一下机器学习。如果你用聪明的方法去做,没有人会因为你失败而生气,如果你成功了,你会交到很多朋友。最重要的是,你将获得一些真实世界的数据科学经验。

为什么这是很好的体验

没有比在数据科学领域实际工作更好的经验来为数据科学领域的工作做准备了。如果你能在你目前的职位上找到从事数据科学的方法,那基本上和从事数据科学工作是一样的。如果你能证明你在任何地方使用机器学习解决了一个问题,那么没人会在乎你的职称是什么。他们会请你告诉他们那个项目。

这是一次好经历的另一个原因是它展示了创造力和解决问题的能力。不会有人告诉你用机器学习做什么或者如何解决问题。类似于通过研究获得的经验,你可以表明你可以创造性地和自主地识别和解决问题。

怎么做

你如何着手做这件事将在很大程度上取决于你在哪里工作,你的经理是谁。因此,我不会试图向你展示如何在工作中开展机器学习项目的路线图,我只会告诉你我是如何做到的,并给你一些提示。

大三那年夏天,我被聘为分析实习生。我真的很想要一份数据科学的实习工作,但是我没有资格去做。我以为我只是接受了一份分析实习,我确信我最好的情况是整个夏天都在计算 p 值。我被分配了一个研究销售趋势的项目。在我实习的前 4 或 5 周,我整理数据并分析趋势。然后,我意识到我的项目远远超过了计划。我决定继续尝试我在数据上获得的一些机器学习技能,看看我是否能提出比趋势更好的东西。两周后,我去找我的经理,告诉她我在忙什么,并给她看了我的作品。对我来说,这是一个非常好的实习机会,公司得到的比原来预想的要多得多。

因此,以下是我的建议和建议:

  1. 确保你没有推迟你被雇佣去做的工作,而是去做你想做的事情。
  2. 确保你的经理同意你正在做的事情。
  3. 找到一个能为企业增加价值的问题,而不仅仅是你个人的机器学习游乐场。
  4. 如果你第一次尝试失败或不成功,不要放弃。想办法做自己喜欢的事。

做一个个人项目

利用自己的时间从事数据科学项目已经被宣传了一遍又一遍,听起来有点陈词滥调。这是老生常谈,因为这是事实。自己做一些很酷的事情显示了你处理来自任何地方的数据的热情和能力。它与 Kaggle 或学校项目有着不同的感觉,对你来说是非常好的体验。

为什么这是很好的经历

最好的员工是那些做自己喜欢的事情的人。一个雇主想要雇佣热爱研究难题并解决它们的数据科学家。唯一疯狂到把空闲时间花在编码和构建机器学习模型上的人,是那些真正喜欢这样做的人。如果做个人项目对你来说是一件苦差事,而你做这些只是为了得到一份工作,你可能会重新考虑你是否真的喜欢你正在做的事情。如果你确实喜欢做一些小项目,并建立了一个不错的项目组合,这就向你潜在的雇主展示了你的动力和能力。

个人项目也是展示技术技能的好方法。你应该一直努力学习新技能。基于你正在学习的东西做一个项目既能巩固你的学习,又能向别人展示你的能力。随着你做越来越多的项目,你的技能将会提高,你将能够做更多令人印象深刻的事情来增加你的投资组合。然后,您可以将您的 GitHub 添加到您的简历中,并让它作为微型技术简历来支持您的其他经验!

怎么做

开始一个项目是最难的部分。如果你想读一本很好的指南,告诉你如何找到并完成一个有价值的项目,并将其添加到你的投资组合中,请点击这里查看泰勒·福克曼的文章。我将只讨论我认为重要的几个要点。

当在一个项目中工作时,有三个大的部分。你有数据、模型和结果。首先,找到你感兴趣的数据。试着寻找那些没有在一百万个其他项目中使用过的数据,这些数据可能包含一些独特的见解。尽量避免模仿别人以前做过的项目。找到数据后,构建并评估几个模型来回答你的任何问题。然后,确保你用有趣的方式展示你的结果。这可以是通过一篇博客文章,一个漂亮的笔记本,或者一个幻灯片。用一种好的、可理解的方式展示你的项目和做一些酷的事情一样重要。

展示你的经历

在你做了所有这些事情以获得一些数据科学经验之后,你仍然需要很好地展示它以获得一份工作。无论你在做什么,你都可以让它听起来绝对无聊,或者有趣而独特。让我们以 LinkedIn 的个人资料为例。你决定和一位教授一起做一些关于防晒霜是否能预防皮肤癌的研究,并发表了一篇很酷的论文。现在你想把它放在你的 LinkedIn 个人资料上。您可以添加类似这样的内容:

研究助理

  • 我帮助进行了关于防晒霜对皮肤癌预防作用的研究。我帮助分析了这些数据,并撰写了现在发表在《美国防晒杂志》上的论文。

这是放在你的 LinkedIn 上的好东西。虽然我已经准备好成为一名数据科学家,但这可能并不确切。有过相同经历并试图获得数据科学工作的人可能会这样写:

研究助理

  • 作为一名研究助理,我参与了关于防晒霜和皮肤癌的假设的制定和测试。我积极参与准备数据和解释我进行的线性回归的结果。我以一种没有统计学背景的学者也能理解这项研究最重要的发现的方式展示了我的结果。我准备从这次经历中汲取实验思维,并将其应用于数据科学问题。

显然,这不是你可能写的完美版本。但我的观点是:如果你做了一些让你更有准备成为数据科学家的事情,不要羞于指出来。你必须清楚地表明,你已经有意识地寻找那些能让你成为优秀数据科学家的经历,并很好地展示出来。

最后的想法

在你找到第一份工作之前,有很多方法可以获得数据科学方面的经验。不要觉得局限于班级项目和 Kaggle 竞赛。发挥创造力,用你感兴趣的数据技能去做一些有趣的事情。一旦你获得了这些经验,确保它们被展示给人们看和阅读。然后,不要害怕去申请一份需要一两年经验的工作。你可以提出一个论点,你已经有了。

如果您有任何问题,请随时发表评论!

如何通过深度学习和嵌入层获得表格数据的最新结果

原文:https://towardsdatascience.com/how-to-gain-state-of-the-art-result-on-tabular-data-with-deep-learning-and-embedding-layers-d1eb6b83c52c?source=collection_archive---------8-----------------------

卡格尔蓝皮书推土机竞赛的另一种方法

Embeddings can be use other than word representations

动机

T 基于 ree 的模型,如 Random Forest 和 XGBoost,在解决表格(结构化)数据问题中非常流行,并在最近的 Kaggle 竞赛中获得了很多关注。这是有其充分理由的。然而,在本文中,我想介绍一种不同于 fast.ai 的表格模块的方法,它利用了:

深度学习和嵌入层。

这有点违背行业共识,即深度学习更多地用于图像、音频或 NLP 等非结构化数据,通常不适合处理表格数据。然而,分类数据的嵌入层的引入改变了这种观点,我们将尝试在蓝皮书推土机竞赛上使用 fast.ai 的表格模块,并看看这种方法能走多远。

你可以找到 Kaggle 笔记本📔 此处

加载数据

首先,让我们导入必要的模块。这里最核心的一个是**fastai.tabular**:

from fastai import *
from fastai.tabular import *

然后我们将数据读入熊猫数据帧。您可以在本文顶部的 Kaggle 笔记本链接中找到具体的代码,但在这里,我将只展示必要的代码片段,以尽可能保持简洁。我们将 CSV 文件读入train_df,这将是我们主要工作的数据帧。我们还将在test_df中读到测试集。

让我们简单看一下我们正在处理的数据:

len(train_df), len(test_df)
(401125, 12457)

对训练集排序

这是为了创建一个好的验证集。一个好的验证集对于一个成功的模型的重要性怎么强调都不为过。因为我们要预测未来的销售价格数据,所以我们需要建立一个验证集,确保所有数据都在训练集的“未来”收集。因此,我们需要首先对训练集进行排序,然后将“未来”部分拆分为验证集。

train_df = train_df.sort_values(by='saledate', ascending=False)
train_df = train_df.reset_index(drop=True)

数据预处理

比赛的评估方法使用 RMSLE(均方根对数误差)。所以如果我们取预测的对数,我们可以用老 RMSE 作为我们的损失函数。只是这样更容易。

train_df.SalePrice = np.log(train_df.SalePrice)

对于特征工程,由于我们将使用深度学习来解决问题,并且它非常擅长特征提取,所以我们将只在saledate进行。这是使用深度学习方法的优势,它需要更少的功能工程和更少的领域知识。我们将使用 fast.ai 的add_datepart函数来添加更多与销售日期相关的功能。

# The only feature engineering we do is add some meta-data from the sale date column, using 'add_datepart' function in fast.ai
add_datepart(train_df, "saledate", drop=False)
add_datepart(test_df, "saledate", drop=False)

add_datepart所做的是,它接受saledate列,并添加了一堆其他列,如day of weekday of month,无论是月、季、年的开始还是结束,等等。这些添加的功能将提供对日期的更多洞察,并与用户购买行为相关。例如,在年底,公司通常会开展促销活动,价格通常会降低。

让我们检查是否所有这些与日期相关的特征都被添加到我们的数据框架中:

# check and see whether all date related meta data is added.
def display_all(df):with pd.option_context("display.max_rows", 1000, "display.max_columns", 1000): display(df)display_all(train_df.tail(10).T)

他们确实被加了进去。很好。现在我们需要做一些数据预处理,因为这个数据帧有相当多的缺失数据,我们还想对列进行分类和规范化。有了 fast.ai 库,这就相当简单了。我们只需在 Python 列表中指定我们想要的预处理方法,就像这样:

# Defining pre-processing we want for our fast.ai DataBunch
procs=[FillMissing, Categorify, Normalize]

这个变量procs稍后将被用于创建用于训练的 fast.ai 数据束。

构建模型

L 让我们看看每一列的数据类型,以决定哪些是分类的,哪些是连续的:

train_df.dtypes
g = train_df.columns.to_series().groupby(train_df.dtypes).groups
g

结果如下:

然后,我们将所有分类列放入一个列表cat_vars中,所有连续列放入一个列表cont_vars中。这两个变量也将用于构造 fast.ai DataBunch。

# prepare categorical and continous data columns for building Tabular DataBunch.
cat_vars = ['SalesID', 'YearMade', 'MachineID', 'ModelID', 'datasource', 'auctioneerID', 'UsageBand', 'fiModelDesc', 'fiBaseModel', 'fiSecondaryDesc', 'fiModelSeries', 'fiModelDescriptor', 'ProductSize', 'fiProductClassDesc', 'state', 'ProductGroup', 'ProductGroupDesc', 'Drive_System', 'Enclosure', 'Forks', 'Pad_Type', 'Ride_Control', 'Stick', 'Transmission', 'Turbocharged', 'Blade_Extension', 'Blade_Width', 'Enclosure_Type', 'Engine_Horsepower', 'Hydraulics', 'Pushblock', 'Ripper', 'Scarifier', 'Tip_Control', 'Tire_Size', 'Coupler', 'Coupler_System', 'Grouser_Tracks', 'Hydraulics_Flow', 'Track_Type', 'Undercarriage_Pad_Width', 'Stick_Length', 'Thumb', 'Pattern_Changer', 'Grouser_Type', 'Backhoe_Mounting', 'Blade_Type', 'Travel_Controls', 'Differential_Type', 'Steering_Controls', 'saleYear', 'saleMonth', 'saleWeek', 'saleDay', 'saleDayofweek', 'saleDayofyear', 'saleIs_month_end', 'saleIs_month_start', 'saleIs_quarter_end', 'saleIs_quarter_start', 'saleIs_year_end', 'saleIs_year_start']cont_vars = ['MachineHoursCurrentMeter', 'saleElapsed']

我们将创建另一个数据帧df来馈入数据集中。我们还将因变量指定为dep_var

# rearrange training set before feed into the databunch
dep_var = 'SalePrice'
df = train_df[cat_vars + cont_vars + [dep_var,'saledate']].copy()

现在是时候创建我们的验证集了。我们通过从训练集中切掉一块最近的条目来做到这一点。街区应该有多大?嗯,和测试集一样大。让我们看看代码:

# Look at the time period of test set, make sure it's more recent
test_df['saledate'].min(), test_df['saledate'].max()# Calculate where we should cut the validation set. We pick the most recent 'n' records in training set where n is the number of entries in test set. 
cut = train_df['saledate'][(train_df['saledate'] == train_df['saledate'][len(test_df)])].index.max()
cut12621# specify the valid_idx variable as the cut out range.
valid_idx = range(cut)

我们首先查看测试集的时间段,并确保它比我们所有的训练集更近。然后我们计算需要剪下多少记录。

最后,让我们使用 fast.ai 的 datablock API 构建我们的 DataBunch 进行训练:

# Use fast.ai datablock api to put our training data into the DataBunch, getting ready for training
data = (TabularList.from_df(df, path=path, cat_names=cat_vars, cont_names=cont_vars, procs=procs).split_by_idx(valid_idx).label_from_df(cols=dep_var, label_cls=FloatList).databunch())

构建模型

我们将从刚刚创建的数据集中启动一个 fast.ai tabular.learner。我们希望将预测的价格范围限制在历史销售价格范围内,因此我们需要计算y_range。请注意,我们将SalePrice的最大值乘以 1.2,因此当我们应用 sigmoid 时,上限也将被覆盖。这是从模型中挤出更多性能的一个小技巧。

max_y = np.max(train_df['SalePrice'])*1.2
y_range = torch.tensor([0, max_y], device=defaults.device)
y_rangetensor([ 0.0000, 14.2363], device='cuda:0')

现在我们可以创建我们的学习者:

# Create our tabular learner. The dense layer is 1000 and 500 two layer NN. We used dropout, hai 
learn = tabular_learner(data, layers=[1000,500], ps=[0.001,0.01], emb_drop=0.04, y_range=y_range, metrics=rmse)

关于 fast.ai tabular_learner最重要的一点是为分类数据使用嵌入层。这是使深度学习在处理表格数据方面具有竞争力的'秘方'。由于每个分类变量都有一个嵌入层,我们为分类变量引入了良好的交互,并利用了深度学习的最大优势:自动特征提取。为了更好的正则化,我们还对密集层和嵌入层使用了 Drop Out。学习者的指标是 RMSE,因为我们已经记录了销售价格。我们来看看模型。

TabularModel((embeds): ModuleList((0): Embedding(388505, 600)(1): Embedding(72, 18)(2): Embedding(331868, 600)(3): Embedding(5155, 192)...(60): Embedding(3, 3)(61): Embedding(2, 2)(62): Embedding(3, 3))(emb_drop): Dropout(p=0.04, inplace=False)(bn_cont): BatchNorm1d(2, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(layers): Sequential((0): Linear(in_features=2102, out_features=1000, bias=True)(1): ReLU(inplace=True)(2): BatchNorm1d(1000, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(3): Dropout(p=0.001, inplace=False)(4): Linear(in_features=1000, out_features=500, bias=True)(5): ReLU(inplace=True)(6): BatchNorm1d(500, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(7): Dropout(p=0.01, inplace=False)(8): Linear(in_features=500, out_features=1, bias=True))
)

从上面可以看出,我们有分类列的嵌入层,然后是删除层。对于连续列,我们有一个批处理范数层,然后我们将所有这些列(分类嵌入+连续变量)连接在一起,并将其放入两个完全连接的层中,这两个层分别有 1000 和 500 个节点,中间有 Relu、batch norm 和 Dropout。很标准的东西。

现在我们有了模型,让我们使用 fast.ai 的学习率查找器来查找一个好的学习率:

learn.lr_find()
learn.recorder.plot()

我们将挑选学习率曲线斜率最大的一端的学习率:le-02

让我们使用 fast.ai 的单周期训练方法进行一些训练。注意,我们为正则化添加了一些权重衰减(0.2)。

learn.fit_one_cycle(2, 1e-2, wd=0.2)

我们可以用较小的学习率训练更多的周期:

learn.fit_one_cycle(5, 3e-4, wd=0.2)

在我们的验证集上,我们已经达到了 0.223的分数。由于竞赛不接受提交材料,我们只能通过查看排行榜来大致了解该模型的表现:

排名第一的是 0.229 。对比这款车型的 0.223 。我们不知道它在测试集上的表现如何,但总的来说,我认为我们得到的结果一点也不差。

关于嵌入层的更多内容

W 让一切点击这里的是嵌入层。嵌入只是一个把某物映射到一个向量的花哨说法。就像 NLP 中越来越流行的单词嵌入一样,它意味着使用一个向量(大小是任意的,取决于任务)来表示单词,这些向量是权重,可以通过反向支持来训练。

类似地,对于我们的例子,我们在分类变量上使用了嵌入。每一列都有一个可以训练的嵌入矩阵。每个唯一的列值都有一个映射到它的特定向量。这方面的美妙之处在于:通过嵌入,我们现在可以开发变量的“语义”,这种“语义”以权重的形式影响我们的销售价格,可以通过我们的深度神经网络提取和训练。该模型将具有“T2”深度,它需要很好地适应大数据集。

但是不要把我的话当真,还是只看我这个不起眼的小项目的成果吧。在一个更荣耀的例子中,有这篇论文,作者是在一个名为 Rossman (预测未来销售)的 Kaggle 竞赛中获得第三名的人。在排行榜上的顶级团队中,其他人都使用了某种重型功能工程,但通过使用嵌入层,他们以较少的功能工程获得了第三名。

更有趣的是,有了嵌入层,你实际上可以在嵌入矩阵空间中可视化变量投影。以罗斯曼项目为例。他们对德国各州的嵌入矩阵进行了二维投影。

如果你在嵌入空间上圈出一些州,在实际地图上圈出相同的州。你会发现它们惊人的相似。嵌入层实际上发现了地理。

觉得这篇文章有用?在 Medium 上关注我(李立伟)或者你可以在 Twitter @lymenlee 或者我的博客网站wayofnumbers.com上找到我。你也可以看看我下面最受欢迎的文章!

[## “这是 CS50”:开始数据科学教育的愉快方式

为什么 CS50 特别适合巩固你的软件工程基础

towardsdatascience.com](/this-is-cs50-a-pleasant-way-to-kick-off-your-data-science-education-d6075a6e761a) [## 一枚硬币的两面:杰瑞米·霍华德的 fast.ai vs 吴恩达的 deeplearning.ai

如何不通过同时参加 fast.ai 和 deeplearning.ai 课程来“过度适应”你的人工智能学习

towardsdatascience.com](/two-sides-of-the-same-coin-fast-ai-vs-deeplearning-ai-b67e9ec32133) [## 你需要了解网飞的“朱庇特黑仔”:冰穴📖

是时候让 Jupyter 笔记本有个有价值的竞争对手了

towardsdatascience.com](/what-you-need-to-know-about-netflixs-jupyter-killer-polynote-dbe7106145f5)

如何使用 Pandas 和 Googlemaps API 从地址栏生成经度和纬度坐标

原文:https://towardsdatascience.com/how-to-generate-lat-and-long-coordinates-from-an-address-column-using-pandas-and-googlemaps-api-d66b2720248d?source=collection_archive---------4-----------------------

Photo by Paula May on Unsplash

如果您想使用地址数据中的地理坐标绘制地图,Google 提供了一个名为 Geocoding 的 API,允许您将地址转换为地理坐标,反之亦然。

什么是地理编码?

地理编码是将地址(如“1600 amphetica Parkway,Mountain View,CA”)转换为地理坐标(如纬度 37.423021 和经度-122.083739)的过程,您可以使用地理坐标在地图上放置标记,或定位地图。如果你想深入了解,请点击这里阅读更多。

谷歌云地理编码 API 定价:

Google 为这个 API 提供每月 200 美元的免费积分(基于您拥有的帐户类型),所以请确保您了解自己运行这个 API 可能会产生的成本。

  • 定价详情 1
  • 定价详情 2

我们开始吧

我使用 Jupyter notebook 来运行本教程中的脚本。

首先,您需要导入 GoogleMaps 和 Pandas 包。如果您还没有安装,请确保已经使用 pip 将这些软件包安装到您的环境中。

from googlemaps import Client as GoogleMaps
import pandas as pd 

创建您的 API 密钥

现在,您需要在 Google Cloud Platform 帐户的凭证部分创建一个 API 密匙。这很简单。

  • 在你的控制台搜索栏中输入 API &服务
  • 点击 启用 API 和服务
  • 搜索 地理编码 API 并确保其已启用
  • 现在点击 凭证 > 创建凭证 并创建一个新的 API 密钥

在 Python 中创建新的 GoogleMaps 对象时,您将使用这个 API 键。

现在回到 Jupyter notebook,使用刚刚生成的 API 键创建一个 GoogleMaps 对象。

gmaps = GoogleMaps('YOUR_API_KEY')

下一步是导入 csv 文件,该文件包含一列您想要转换的完整地址。

addresses = pd.read_csv("YOUR_CSV_FILE.csv")
addresses.head()

添加两个空列来保存经度和纬度数据。

addresses['long'] = ""
addresses['lat'] = ""

地理编码响应

运行Google maps . geocode命令返回一个 JSON 对象,看起来像 this 。如果需要,您还可以利用更多的属性。然而,如前所述,我们将只关注经度和纬度地理坐标,它在 JSON 响应中有一个“geometry”和“location”的*键。
-几何形状>位置>横向
-几何形状>位置> lng
*

生成经度和纬度坐标

现在是时候遍历数据帧,为每个地址记录插入“lng”和“lat”。

for x in range(len(addresses)):try:time.sleep(1) #to add delay in case of large DFsgeocode_result = gmaps.geocode(addresses['FullAddress'][x])addresses['lat'][x] = geocode_result[0]['geometry']['location'] ['lat']addresses['long'][x] = geocode_result[0]['geometry']['location']['lng']except IndexError:print("Address was wrong...")except Exception as e:print("Unexpected error occurred.", e )addresses.head()

有了生成的坐标,您可以像这样绘制地图视图。

source: https://blog.exploratory.io/geocoding-us-zip-code-data-with-dplyr-and-zipcode-package-7f539c3702b0

最后,如果需要,将您的结果导出到 csv。

addresses.to_csv('address_coords.csv')

就是这样!希望这对你有帮助。如果你有任何问题或建议,请告诉我。

你可以成为中等会员享受更多这样的故事。

如何使用 Scikit-Learn 和 Python 生成预测区间

原文:https://towardsdatascience.com/how-to-generate-prediction-intervals-with-scikit-learn-and-python-ab3899f992ed?source=collection_archive---------0-----------------------

(Source)

使用梯度推进回归器显示机器学习估计中的不确定性

“所有的模型都是错误的,但有些是有用的”——乔治·博克斯。当我们提出机器学习预测时,记住这个明智的建议至关重要。所有的机器学习管道都有局限性:影响目标的特征不在数据中(潜在变量),或者模型做出的假设与现实不符。当我们显示一个预测的精确数字时,这些都被忽略了——房子将是 450,300.01 美元——这给人的印象是我们完全相信我们的模型是真实的。

显示模型预测的一种更诚实的方式是估计范围:可能有一个最可能的值,但也有一个真实值可能存在的较大区间。这不是数据科学课程中通常涉及的主题,但我们在预测中展示不确定性,并且不要过度吹嘘机器学习的能力,这一点至关重要。虽然人们渴望确定性,但我认为展示一个包含真实值的宽预测区间比一个远离现实的精确估计要好。

在本文中,我们将介绍一种在 Scikit-Learn 中产生不确定性区间的方法。完整的代码可以在 GitHub 的上找到,在 nbviewer 上有一个互动版的 Jupyter 笔记本。我们将主要关注的实现,在最后有一个简短的部分和理解理论的资源。生成预测区间是数据科学工具箱中的另一个工具,对于赢得非数据科学家的信任至关重要。

Prediction intervals we’ll make in this walkthough.

问题设置

在这次演练中,我们将使用在 DrivenData 上举办的机器学习竞赛中的真实建筑能源数据。你可以在这里获得原始数据,但是我已经在 GitHub 中提供了一个清理过的版本,它具有以 15 分钟为间隔测量的能量和八个特征。

data.head()

Cleaned building energy data

目标是从特征中预测能量消耗。(这是我们在 Cortex Building Intel 每天都要做的实际工作!)。毫无疑问,我们的数据中存在未捕捉到的影响能源消耗的隐藏特征(潜在变量),因此,我们希望通过预测能源使用的上限和下限来显示我们估计中的不确定性。

# Use plotly + cufflinks for interactive plotting
import cufflinks as cfdata.resample('12 H').mean().iplot()

Building energy data from DrivenData (hosting machine learning competitions for good!)

履行

为了在 Scikit-Learn 中生成预测区间,我们将使用梯度推进回归器,从文档中的这个示例开始工作。基本想法很简单:

  1. 对于较低的预测,使用GradientBoostingRegressor(loss= "quantile", alpha=lower_quantile)和代表下限的lower_quantile,比如 0.1 代表第 10 个百分位数
  2. 对于上限预测,使用带有代表上限的upper_quantileGradientBoostingRegressor(loss= "quantile", alpha=upper_quantile),比如 0.9 代表第 90 百分位
  3. 对于中间预测,使用预测中间值的GradientBoostingRegressor(loss="quantile", alpha=0.5),或预测平均值的默认loss="ls"(对于最小二乘法)。文档中的例子使用了后一种方法,我们也将这样做。

在高层次上,损失是由模型优化的函数。当我们将损失改变为分位数并选择α(分位数)时,我们能够得到对应于百分位数的预测。如果我们使用较低和较高的分位数,我们可以产生一个估计范围。(我们不会在这里讨论分位数损失的细节——参见下面分位数损失的背景。)

在将数据分成训练集和测试集之后,我们构建模型。我们实际上必须使用 3 个独立的梯度推进回归器,因为每个模型都在优化不同的函数,并且必须单独训练。

from sklearn.ensemble import GradientBoostingRegressor# Set lower and upper quantile
LOWER_ALPHA = 0.1
UPPER_ALPHA = 0.9# Each model has to be separate
lower_model = GradientBoostingRegressor(loss="quantile",                   alpha=LOWER_ALPHA)
# The mid model will use the default loss
mid_model = GradientBoostingRegressor(loss="ls")upper_model = GradientBoostingRegressor(loss="quantile",alpha=UPPER_ALPHA)

训练和预测使用熟悉的 Scikit-Learn 语法:

# Fit models
lower_model.fit(X_train, y_train)
mid_model.fit(X_train, y_train)
upper_model.fit(X_train, y_train)# Record actual values on test set
predictions = pd.DataFrame(y_test)# Predict
predictions['lower'] = lower_model.predict(X_test)
predictions['mid'] = mid_model.predict(X_test)
predictions['upper'] = upper_model.predict(X_test)

就这样,我们有了预测区间!

Prediction intervals from three Gradient Boosting models

Prediction intervals visualized

用一点点 plotly 的,我们可以生成一个很好的交互剧情。

Interactive plot produced with plotly

计算预测误差

与任何机器学习模型一样,我们希望在测试集(我们有实际答案的地方)上量化我们预测的误差。测量预测区间的误差比点预测稍微复杂一点。我们可以计算实际值在该范围内的时间百分比,但这可以通过使间隔非常宽来容易地优化。因此,我们还需要一个考虑到预测值与实际值有多远的度量,比如绝对误差。

在笔记本中,我提供了一个函数来计算下、中和上预测的绝对误差,然后对“区间”绝对误差的上下误差进行平均。我们可以对每个数据点都这样做,然后绘制误差的箱线图(边界内的百分比在标题中):

有趣的是,对于这个模型,较低预测的中值绝对误差实际上小于中间预测。这个模型没有很高的精度,可能会受益于优化(调整模型超参数)。实际值有一半以上的时间处于下限和上限之间,我们可以通过降低下分位数和提高上分位数来提高这个指标的精度。

可能有更好的指标,但我选择了这些,因为它们计算简单,易于解释。您使用的实际指标应该取决于您试图解决的问题和您的目标。

预测区间模型

用 3 个独立的模型进行拟合和预测有些繁琐,因此我们可以编写一个模型,将梯度推进回归量包装到一个类中。它源自 Scikit-Learn 模型,因此我们使用相同的语法进行训练/预测,只是现在它在一个调用中:

# Instantiate the class
model = GradientBoostingPredictionIntervals(lower_alpha=0.1, upper_alpha=0.9
)# Fit and make predictions
_ = model.fit(X_train, y_train)
predictions = model.predict(X_test, y_test)

该模型还带有一些绘图工具:

fig = model.plot_intervals(mid=True, start='2017-05-26', stop='2017-06-01')
iplot(fig)

请按照您认为合适的方式使用和调整模型!这只是进行不确定性预测的一种方法,但我认为它很有用,因为它使用了 Scikit-Learn 语法(意味着一条浅的学习曲线),我们可以根据需要对它进行扩展。一般来说,这是解决数据科学问题的好方法:从简单的解决方案开始,只在需要时增加复杂性!

背景:分位数损失和梯度推进回归变量

梯度推进回归器是一个集合模型,由单独的决策树/回归树组成。(模型的原解释见弗里德曼 1999 年的论文《贪婪函数逼近:一种梯度助推机》。)与并行训练树的随机森林相反,梯度增强机器顺序训练树,每棵树从当前集合的错误(残差)中学习。树对模型的贡献是通过最小化模型预测和训练集中实际目标的损失函数来确定的。

Each iteration of the gradient boosting machine trains a new decision/regression tree on the residuals (source)

使用默认损失函数-最小二乘法-梯度推进回归器预测平均值。理解的关键点是最小平方损失同等地惩罚低误差和高误差:

Least squares loss versus error

相反,分位数损失基于分位数以及误差是正(实际>预测)还是负(实际<预测)来惩罚误差。这允许梯度推进模型不是针对平均值而是针对百分位数进行优化。分位数损失为:

其中 α 是分位数。让我们快速地看一个例子,实际值为 10,分位数为 0.1 和 0.9:

  1. 如果 α = 0.1,预测值= 15,那么损失=(0.1–1)*(10–15)= 4.5
  2. 如果 α = 0.1,预测值= 5,那么损失= 0.1 *(10–5)= 0.5
  3. 如果 α = 0.9,预测= 15,那么损耗=(0.9–1)*(10–15)= 0.5
  4. 如果 α = 0.9,预测值= 5,那么损失= 0.9 *(10–5)= 4.5

对于分位数< 0.5, if the prediction is greater than the actual value (case 1), the loss is greater than for a prediction an equal distance above the actual value. For a quantile > 0.5,如果预测小于实际值(情况 4),则损失大于低于实际值相等距离的预测。如果分位数== 0.5,那么高于和低于实际值的预测会产生相等的误差,并且模型会针对中值进行优化。

(对于 mid 模型,我们可以使用loss="quantile", alpha=0.5表示中值,或者使用loss="ls"表示平均值)。

分位数损失最好用损失与误差的关系图来说明:

Quantile loss versus error for different quantiles

分位数< 0.5 drive the predictions below the median and quantiles > 0.5 驱动预测高于中位数。这是一个很好的提醒,机器学习方法的损失函数决定了你要优化什么!

根据我们想要的输出,我们可以优化平均值(最小平方)、中值(alpha == 0.5 的分位数损失)或任何百分位数(alpha ==百分位数/ 100 的分位数损失)。这是分位数损失的一个相对简单的解释,但它足以让您开始通过模型演练生成预测间隔。为了更进一步,查看这篇文章或者从维基百科页面开始并查看源代码。

结论

从机器学习模型预测单个数字会给人一种错觉,即我们对整个建模过程有很高的信心。然而,当我们记住任何模型都只是一个近似值时,我们看到了在进行估计时需要用来表示不确定性。一种方法是使用 Scikit-Learn 中的梯度推进回归器生成预测区间。这只是预测范围的一种方法(例如,参见线性回归的置信区间),但它相对简单,可以根据需要进行调整。在本文中,我们看到了一个完整的实现,并了解了分位数损失函数背后的一些理论。

解决数据科学问题就是在你的工具箱中有许多工具可以根据需要应用。生成预测间隔是一项有用的技术,我鼓励您阅读本演练并将其应用于您的问题。(学习任何技术的最好方法是通过实践!)我们知道机器学习可以做一些非常不可思议的事情,但它并不完美,我们不应该这样描述它。为了获得决策者的信任,我们通常需要给出的不是一个单一的数字作为我们的估计,而是一个预测范围,表明所有模型中固有的不确定性。

我写数据科学,偶尔也写一些其他有趣的话题。你可以在 twitter 上关注我以获得有用的技术和工具。如果拯救世界同时帮助底线对你有吸引力,那么请联系我们 Cortex。

如何在没有神经网络的情况下为评论文本生成“摘要”

原文:https://towardsdatascience.com/how-to-generate-summaries-for-review-text-without-neural-networks-568f14dbe835?source=collection_archive---------22-----------------------

获取带有相关术语的可解释关键词,以理解消费者评论

作为一名在 Clorox 消费品行业工作的数据科学家,我的“日常挑战”之一是从大量关于特定产品的用户评论中快速而简洁地提取有用的信息。从表面上看,这个任务需要对大量文本进行某种形式的摘要。说到生成文本摘要,我们通常会想到复杂的深度学习相关模型和解决方案——序列到序列模型、编码器-解码器 RNNs、注意力机制等。然而,尽管这些深度学习模型需要花费巨大的努力来训练,但它们的性能对于特定的任务来说并不总是令人满意的。更重要的是,如果我们的目标是从文本内容中提取有见地的信息,有时我们实际上并不需要文本的语言摘要。在这篇博客中,我想介绍一种方法,它可以通过基于频率的计数从评论文本中生成“摘要”。

举个例子,我将使用亚马逊的公共用户评论的子集来评价家用清洁产品之一的 Clorox 湿巾。此链接将带您进入评论页面。下面是我从这些评论中总结出来的“总结”。

它是这样工作的:

词性标注

第一步是用词性来标记评论文本中的每个标记。当我们考虑用户对某个产品的评论以及文本的词性成分时,提供最有洞察力的信息的术语或标记很可能是名词或形容词就不足为奇了。名词有助于解释“是什么”的问题(消费者谈论的产品是什么,主题是什么。它可以是包装、送货、气味等),而形容词有助于“关于什么”的问题。(包装呢;交付呢;气味呢)。标记后,我们将提取前 15 个最流行的名词和前 15 个最流行的形容词。

相关术语搜索

现在我们有了名词和形容词的频率,下一步将是找到它们之间的关系。

具体来说,对于一个流行名词,如何才能知道最靠前的相关形容词?同样对于一个形容词,怎么才能知道最上面的相关名词呢?了解相关术语可能有助于我们加深从文本中获得的信息,但这项任务本身并不像看起来那么简单。

以“价格”这个术语为例。它在上面的图中显示为第三个流行名词,现在我想通过查看我们的消费者使用的最相关的形容词来了解价格。那么我们就有一个问题——如何定义相关?更具体地说,如何构造一个搜索算法来找到并显示最相关的形容词?

让我用下面的评论作为例子来帮助说明我的方法:

在这种情况下,我们将术语“价格”称为目标术语,因为我们想要获得关于“价格”的信息。在特定的审查中,我们对目标术语的每次出现重复以下步骤。

1.确定目标术语的位置(以黄色突出显示)

2.查找与目标术语具有相同 POS 标签的最近术语。称它们为“边界条件”(用蓝色突出显示)。在这种情况下,由于“价格”是一个名词,边界项将是最接近的名词。

3.找出边界术语中的所有形容词,并将它们保存到列表中

然后,我们重复上述相同的过程,将“价格”作为所有评论的目标术语。最终,我们会有一个与价格这个术语潜在“相关”的形容词列表。通过这种方式,我能够得到如下的前 15 个相关形容词:

像“好”和“伟大”这样的术语非常流行。这实际上是真的,因为我们可以在亚马逊上找到很多评论,上面写着“价格合理”和“价格优惠”最后,我们对所有提到最多的名词和形容词重复整个相关术语搜索过程,我们最终将得到我在开始时提供的汇总表。

这不是一个复杂的方法,但它非常有效且易于使用。它就像构建单词云一样简单,但也提供了更多的见解和更好的解释。要阅读更多关于这种技术的内容,它是如何实现的,有哪些缺点,这里是我为它写的原始博客的链接。

在这里你可以找到我上面提到的方法的代码。下面是如何使用它:

我希望这个博客对你有所帮助,我希望听到你的反馈

感谢您通读!

如何获得数据科学实习机会——技术专长与个性

原文:https://towardsdatascience.com/how-to-get-a-data-science-internship-technical-expertise-vs-personality-c68d3a117eaa?source=collection_archive---------12-----------------------

对于每个数据科学爱好者来说

任何领域的专家都曾是初学者——海伦·海丝

之前我还是一个还在读大学的学生的时候,就想去搞一个数据科学的实习。我太想得到它了,所以我申请了这么多公司,但只得到他们的几个回复。

更具体地说,只有不到 10%的公司回复了我的申请。不仅如此,当我看到实习职位的描述时,要求是具有很强的技术技能,优秀的成绩,深入的机器学习知识等。

我迷路了。我既没有很强的技术背景,也没有数据科学实习的经验。我只是在寻找我的第一份数据科学实习。

以下是我从 LinkedIn 收到的一些关于如何获得数据科学实习的问题。

我知道努力工作却没有得到想要的东西是什么感觉。

但如果我告诉你,经验或技术背景对获得数据科学实习可能并不那么重要,你会感兴趣吗?

在本文中,我将分享如何获得第一份数据科学实习。

现在,让我们问自己下面的问题。

为什么需要获得数据科学实习?

然后,从招聘经理的角度出发。

为什么需要雇佣实习生?

问完这两个问题,你是否找到了你和你的招聘经理都在寻找的共同答案?

第一个问题的答案之一是学习数据科学,了解数据科学家应该具备哪些技能,以便您可以学习。然而,你能拿出什么样的资格、技能等让招聘经理雇佣你呢?

现在,让我们描绘两个场景。

第一种情况

想象一下,招聘经理正在寻找实习生,他们可以帮助完成一些数据标注任务,还可以评估各种机器学习模型。也就是说他或她不是在寻找一个有很强技术背景的人。

她可能只是想找一个愿意从事一些与机器学习无关的任务的人。换句话说,招聘经理正在寻找一个拥有她所寻找的个性的人。

例如,给定一个数据标记任务,您可能认为这是一个非常手工的过程。当你的导师在你的数据集上训练模型,发现你标注的大部分标签都是不正确的时候,她会觉得自己浪费了时间去信任你的工作。

但是如果她想找一个很有个性的人一起工作呢?一旦她对交给你的任务感到满意,我相信她会愿意教你你感兴趣的东西。

第二种情况

假设招聘经理正在寻找一个人来帮助她解决她面临的一些最困难的问题。换句话说,她想引进一个有很强技术能力和机器学习知识的人。

在这种情况下,她要求的候选人必须有能力阅读研究论文,提出解决问题的好主意,清理代码,使当前的代码更有效等等。

因此,招聘经理会对候选人有更高的期望。简而言之,候选人应该具备很强的技术能力。

个性与技术专长

现在,我想你对招聘经理的期望有了更清晰的了解。因此,让我来分享你应该如何准备自己,以便获得你的第一个数据科学实习机会!

如果你是一个没有很强技术背景的人,这里有一些我的建议。首先,你应该在面试中表现出良好的个性。什么被认为是好的性格?例如,努力工作,愿意学习,对机器学习充满热情,独立等等。

从招聘经理的角度来看,如果你没有技术背景,但只要你愿意学习并努力工作,大多数时候,他或她会愿意给你一个机会。前提是你申请的不是需要很强技术背景的实习。

此外,不要对公司或工作范围挑剔。如果你得到了数据科学实习,也许你的大部分时间将花在手工任务上。然而,如果你设法更快地完成任务,并且你表现出你的技术技能在短时间内确实提高了很多,你的经理会给你机会尝试训练一些模型。另一方面,别忘了这次实习会给你以后带来更多的实习机会。

而且,有一个很棒的项目来论证也很重要。我这里说的不是学校的项目,而是有趣的现实世界的项目。如果你有兴趣知道展示哪种项目,请在下面评论!

你可以请你的同学或朋友来帮助你。将您的代码发布到 GitHub 并不是故事的结尾。你应该找一个对数据科学一无所知的人,你以一种他或她知道你在说什么的方式向你的朋友介绍这个项目

另一方面,花一些时间在社交活动上。如果你能给他们留下很好的第一印象,你就有很大的机会获得面试机会。

如果你确实有技术专长,但仍然找不到实习机会,这里有一些你可以注意的方法。如果你的目标是那些顶级公司,练习你的编程技能

有很多网站可以参考,比如 Leetcode 、 Topcoder 、 Coderbyte 等。如果你是懒人类型的人,问问你的学长,朋友,甚至去查一下 glassdoor 看看有没有人分享面试的问题。你会感到震惊,有时你甚至可以在那里找到面试问题的答案。

此外,练习,练习,练习你的演讲。不要让你的演示搞砸了你的大项目。我怎么强调这一点都不为过,因为我看到太多的实习生在实际面试中因为他们的陈述而搞砸了。他们可能有有趣的项目要展示,但在他们完成演示后,我仍然不明白他们想展示什么。请记住,数据科学不仅仅是编码,还包括清楚地展示你的发现。

如果你知道你总是无法回答与机器学习知识相关的问题,那么花时间复习你的知识

不仅如此,展示有趣的项目。记得清理你的代码并插入整洁的注释。此外,一定要注意你的简历。有一次我面试一个实习生,他或她的简历中显示的作品集链接无法访问。

性格还是很重要的在这种情况下。展示出你很有个性,这样你潜在的老板就会接受你。

最后的想法

获得数据科学实习没有完美的公式,但有一些方法可以让你得到它!

你会得到你为之工作的东西,而不是你希望得到的东西——丹尼尔·米尔斯坦

非常感谢你一直读到最后。如有疑问,欢迎在下方评论!

相信我,如果你听从我的建议,你会得到一个!

祝你顺利获得第一份数据科学实习,并祝你早日圣诞快乐!🎄

关于作者

低魏宏是 Shopee 的数据科学家。他的经验更多地涉及抓取网站,创建数据管道,以及实施机器学习模型来解决业务问题。

他提供爬行服务,可以为你提供你需要的准确和干净的数据。你可以访问 这个网站 查看他的作品集,也可以联系他获得的抓取服务

你可以在 LinkedIn 和 Medium 上和他联系。

[## ●伟鸿-中等

在媒体上阅读低纬鸿的作品。数据科学家|网络抓取服务:https://www.thedataknight.com/.每…

medium.com](https://medium.com/@lowweihong?source=post_page-----6bef8cb1477a----------------------)

你可能喜欢的故事

[## 如何学习机器学习

由数据科学家分享

towardsdatascience.com](/how-you-can-learn-machine-learning-5991dee49362) [## 进入数据科学领域之前你应该知道的 5 件事

数据科学家日常生活的幕后

towardsdatascience.com](/5-things-you-should-know-before-getting-into-data-science-f4312f06ea73)

如何获得 2019 年数据科学面试

原文:https://towardsdatascience.com/how-to-get-a-data-science-interview-in-2019-d6df63231d43?source=collection_archive---------14-----------------------

你能做的几乎没有什么能保证你在数据科学领域获得面试或工作。另一方面,你可以做很多事情来增加你被关注的可能性。我制作了这个循序渐进的指南,来帮助数据科学的希望者展现出他们最好的一面,并对公司和招聘人员产生影响。

在过去的三年里,我浏览了数百份招聘信息,面试了一系列公司。当我完成研究生学业时,我想知道我未来的选择是什么。在这个过程中,我把求职周期分解成了一门科学。

此外,在过去的 6 个月里,我花了大量时间面试数据科学候选人。我在相对较短的时间内经历了桌子的两面,我相信我对什么能真正引起你的注意有独特的理解。这些建议是基于我在这个行业看到的趋势以及我的个人经验。

第一步:照照镜子

为了在面试过程中为自己做好准备,思考下一步你想扮演什么样的角色是很重要的。我建议浏览招聘启事,以确定你想要的目标角色类型。问自己几个关键问题:

  • 我最擅长的技能是什么?
  • 为了得到我想要的角色,我需要提高哪些技能?
  • 我如何展示这些“关键”技能领域的能力?
  • 我会考虑为了工作而搬迁吗?
  • 我想为哪种类型的公司工作(规模、行业、文化)?

带着这些问题,你可以开始思考如何识别机会,展示自己的价值。

第二步:创建高质量的内容

数据科学就业市场的最大趋势是关注未来员工创造的内容。我特别留意候选人的简历中是否有以下链接:

  • 个人网站
  • 饭桶
  • 卡格尔
  • Tableau Public
  • 博客
  • YouTube

这是让自己与众不同的最简单的方法。如果你已经在两个或更多的资源上发布了内容,这真的会大有帮助。你应该根据你的目标角色来提供这些资源。如果你最感兴趣的工作列表都有 tableau 组件,我强烈建议创建一个 tableau 公共帐户。如果你正在寻找 ML 工程师角色,那么拥有一个包含你个人工作的 Git 账户是有意义的( Github 、 Bitbucket 和 GitLab )。

虽然这些资源极其宝贵,但如果做得不好,它们也会伤害你。我建议在你申请之前更新这些资源。像对待简历或正式邮件一样仔细地修改它们。

从事个人项目会让雇主对你有更多的了解。这表明你有在自己的时间里从事项目的主动性,并且你对数据科学充满热情。项目也向他们展示你对什么类型的数据感兴趣。如果你是在某个行业内部申请,我建议你做一些与该领域相关的项目。

第三步:准备你的电子简历

很明显,简历是获得关注的重要部分。此时,你应该更新两份简历:传统简历和你的 LinkedIn 个人资料。

在更新这些简历之前,我喜欢浏览 5-10 个我觉得有吸引力的职位。如果他们大多需要相同的技能,我会寻找始终不变的关键词和主题。通过突出与工作要求相关的经验和技能,使你的简历适合这些职位是很重要的。如果你申请了几个不同类型的职位,我建议你为每种类型的职位准备不同版本的简历。事实上,我不建议为你申请的每个职位都制作一份简历。

如果这些职位需要你目前不具备的技能,我建议你做一个项目来培养这些技能。你将学到证明你能力的技能和证据。

很多人在 LinkedIn 或者网上发布简历。我建议看看其他数据科学家是如何格式化简历的。以下是提供有用的最佳实践的简历模板和在线服务的链接:

  • 例 1
  • 例 2

我的传统简历推荐:

  • 从你的技术技能开始。
  • 展示相关的项目和你使用的工具。
  • 强调黑客马拉松中的任何团队工作(一定要做黑客马拉松)。
  • 链接到您创建的内容!
  • 美学和适当的编辑很重要,让其他人通读一下语法错误。
  • 对于每个项目,确定你做了什么以及它所带来的影响(如果适用)。尽可能具体()例如,建立一个随机福里斯特分类器来识别顾客是否会购买。这导致了上个月 1320 次额外的转换。)
  • 对于学校作业或个人项目,项目部分会很有帮助。如果你只有不到 2-3 年的全职经验,突出你的项目经验。

我的 LinkedIn 个人资料推荐:

  • 在“关于我”的陈述中加入一些有意义的内容。如果你申请的是一个特定类型的职位,确保这份声明突出了该职位所需的技能。
  • 社会证明很重要。请别人认可你的技能或推荐你
  • LinkedIn 让你提供比简历更多的辅助内容。加入志愿者工作、有趣的项目或你感兴趣的事情。
  • 加入社区或在这个平台上发布与工作相关的内容会向雇主暗示你关心你的职业关系网。

第四步:仔细考虑你的沟通渠道

你如何让自己进入一家公司的视野可能是你获得面试机会的最重要因素。由一个活跃的员工推荐会大大增加你的机会。Jobvite 和卧底招聘人员的一项民意调查显示,只有约 7%的候选人通过推荐申请,但约 40%的雇员来自推荐。如果你不考虑这种方法,你会让自己处于很大的劣势。

浏览你的社交网络还有其他积极的好处。你可能在机会发布之前就听说了,而且有积极的激励措施在为你工作。许多公司提供推荐奖金,如果面试官与你的推荐人关系良好,他们可能会表现出偏好。

大量资料表明,70-85%的求职者实际上是通过某种形式的网络找到工作的。与某人至少有一个相似度会大有帮助。联系你的校友网络、LinkedIn 网络,甚至你的社交网络。如果你朋友的父母在你感兴趣的行业工作,问问他/她的想法也无妨。当你在找工作的时候,友好地问问题不会有坏处。

其他人可以从你找到工作中受益。大多数招聘人员的薪酬是基于他们将候选人安置到角色中的能力。接触技术招聘公司可能是外包你一些工作的好方法。他们可以帮助你发现机会,让你很好地理解当前的市场趋势。

公司也有招聘团队,他们通过将销售线索转化为工作来获得报酬。在申请的时候,或者在申请之前,我建议联系公司的技术招聘人员,建立关系。更多的是关于你应该如何与这些人交流。

总之,你应该列出一个你想联系的人的名单。这份名单应该包括你的人际网络(学校、LinkedIn 和社交网络)中的人,或者有动机在组织中提拔你的招聘人员。

第五步:做作业

在你接近一家公司之前,尽可能多的了解它是很重要的。很少有什么事情比一个对面试的公司没有基本了解的应聘者更让我反感的了。我建议在向您在上一步中确定的联系人发送邮件之前,彻底调查一家公司。

你应该了解以下与公司有关的事情:

  • 该行业
  • 业务线和产品
  • 竞争对手
  • 高层领导
  • 价值观和使命宣言
  • 历史
  • 规模和增长轨迹
  • 最近有什么新闻吗

您可以在以下几个地方找到此信息:

  • 玻璃门
  • 领英
  • 公司网站
  • 公司新闻稿
  • 【Angel.co

与你感兴趣的职位上的人进行信息面试。同样,我会通过你的关系网联系这些人。这是询问必要技能的好机会,他们希望自己已经学会的东西,以及他们是如何找到工作的。我不建议询问这个人所在公司的工作或机会。如果他们认为你是一个好的候选人,他们会提出空缺职位,并主动推荐你。

信息面试技巧:

  • 在他们附近见面喝咖啡
  • 将会议时间设定为 30 分钟(尊重他们的时间)
  • 策划一些好的问题,这样你就有话题可聊了。我喜欢问:

他们生活中的一天是怎样的?

他们公司的文化是什么样的?

他们希望在面试时知道什么?

他们喜欢在这个领域工作吗?

他们会给想进入这个领域的人什么建议?

第二天通过电子邮件感谢他们。根据您的对话进行定制。这是记住你们谈论的内容并留下持久印象的好方法。

第六步:伸出手,仔细选择你的信息

当你联系招聘人员时,传达一些信息是很重要的:

  1. 为什么你对这个职位、市场和/或公司感兴趣。一定要为每个公司定制这个。
  2. 引起你注意的关于公司的最新消息。
  3. 你能为公司提供的价值。请提供一些背景资料,说明你在这个职位上取得成功所需的技能。
  4. 你的简历。

在这种情况下,招聘人员可能会要求你申请这个职位。如果你给他们留下了印象,他们会给你的申请打上标记。

在他们回应后,一定要感谢他们。当候选人付出额外的努力来继续对话时,对我来说是有意义的。即使招聘人员没有决定给你面试机会,他们也可能会把你的简历发给他们关系网中的某个人。

如果你在一周内没有收到招聘人员的回复,仍然申请这个职位并提交你的简历。申请之后再跟进也无妨。

最后的想法

我知道这个过程看起来很艰难,相信我,我也经历过。然而,我可以想象你在之前的工作中已经采取了类似的措施。希望这篇文章能给你一些如何提高你在公司和招聘人员眼中的价值的建议。如果您遵循这一流程并继续发展您的技能,我相信您将能够开始并保持成功的数据科学职业生涯!

如何更全面地了解模型的准确性

原文:https://towardsdatascience.com/how-to-get-a-fuller-picture-of-a-models-accuracy-e3e6f45becb2?source=collection_archive---------21-----------------------

交叉验证的案例以及如何实现一个版本(k-fold)

使用单个训练测试分割给你一个机器学习模型或算法的性能的单个快照。这就像根据一场比赛来评价一支足球队(美国队或其他球队)。如果你真的想知道一个团队总体表现如何,你需要的不仅仅是这张快照。同样,我们不应该在一次随机分割中评估我们的算法。幸运的是,有更好的方法。我给你带来 k 倍交叉验证。

当火车测试分裂使你误入歧途

今天,我使用的是 Gareth James 的经典广告数据集,其中有 200 条电视、广播和报纸广告支出的记录以及相应的销售数据。

我创建了一个线性回归模型来预测基于 TV*Radio 的销售,并在测试数据集上进行验证:

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as npdf = pd.read_csv(‘data/advertising.csv’) # import data
df[‘TVxradio’] = df[‘TV’] * df[‘radio’] # create featurex = np.array(df[‘TVxradio’]).reshape(-1, 1)
y = np.array(df[‘sales’])x_train, x_test, y_train, y_test = train_test_split(x1, y1, test_size=0.3, random_state=54546)model = LinearRegression()
model.fit(x_train, y_train)
print(f’model accuracy on test set: {model.score(x_test, y_test)}’)

结果:

model accuracy on test set: 0.9721866564067523

厉害!!模特太棒了!

Kevin Jarrett CC 2.0

或者是?

Image by htuuli from Pixabay

这个分数不能向你展示模型的真正预测能力。在这种情况下,你是在根据一场比赛来评判足球队。你不知道这是不是一种‘幸运’train_test_split。在这种情况下,是的。我作弊了。选择新的random_state (71464)使我们的模型精度下降到 0.80。

有一种更好的方法来优化模型,而不是随心所欲。一种提供对分数分布的洞察并降低过度适应测试数据集的风险的方法。

为什么/何时使用 k-fold 交叉验证

  • 在较小的数据集上。如果你有一个庞大的数据集,你可以将它分成三个有代表性的部分——训练、测试和最终评估。不幸的是,你并不总是有这种奢侈;您的数据集可能不够大,无法分成三个有代表性的部分。这就是交叉验证的用武之地。K-fold 交叉验证可以防止过度拟合测试数据,而不会进一步减小训练数据集的大小。
  • 让你的模型得到一个不那么偏颇(理解:乐观)的评价。 K-fold 交叉验证报告模型在来自训练集的几个(K)样本上的性能。这使您能够洞察模型中可能看到的精度分布。
  • 当你有足够的计算资源/时间。K-fold 交叉验证比将数据分割成三部分的计算量更大。它重新拟合模型,并在每次迭代中测试 k 次,而不是一次。因此,对于运行时/计算成本不显著的小数据集,它更有价值,并且额外的分区会显著减少训练数据集。

了解 k 倍交叉验证

Image from Scikit-learn Developers

当您在交叉验证分割策略(cv)设置为整数的情况下运行cross_val_score时,它会执行以下操作:

  1. 将数据集随机分割成 k 个“折叠”(又名。较小的数据集)
  2. 留出一个切片,并在其他切片上训练模型。
  3. 在保存的集合上验证模型并记录分数。
  4. 重复第二步和第三步,每次折叠一次。

然后,您可以使用这些分数来获得模型准确性的平均值、标准偏差和 95%置信区间的估计值。

如何使用 k 倍交叉验证

scikit-learn 的cross_val_score的基本用途包括以下参数:

  • 估计值-用于拟合数据的模型
  • x-要拟合的数据
  • y —目标变量(如果使用监督学习)[可选]
  • cv-您想要的折叠次数[默认为三次]

注意:没有一个“正确”的折叠次数。您需要考虑每个文件夹中数据集的大小。理想情况下,折叠的大小应该相等,这在非常小的数据集中尤其重要,因此可以考虑选择一个 k 值来均匀划分数据集。斯坦福大学的 Hastie 和 Tibshirani 指出 k=5 或 k=10 是典型的 k 值。

还要注意:cross_val_score不会自动洗牌。如果你想多次运行它(类似于引导),确保包含一个 shuffle。

一如既往,查看文档和用户指南了解更多信息。

例 1:单一回归

回到广告数据集,同样的单因素线性回归模型(电视花费*电台花费),只需要几个变化就可以实现 k 倍cross_val_score

# import necessary python modules and classes
**from sklearn.model_selection import cross_val_score**
from sklearn.linear_model import LinearRegression # your model here
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np# import data
df = pd.read_csv('data/advertising.csv')# engineer feature of interest
df['TVxradio'] = df['TV'] * df['radio']# slice data
x = np.array(df['TVxradio']).reshape(-1, 1)
y = np.array(df['sales'])# train-test split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=0)# select model
model = LinearRegression()**# k-fold cross validation
scores = cross_val_score(model, x_train, y_train, cv=10)
print(scores)
print(f"95% CI Accuracy: "f"{round(scores.mean(), 2)} "f"(+/- {round(scores.std() * 2, 2)})"
)**# test model on test set
model.fit(x_train, y_train)
print(f'model accuracy on test set: {model.score(x_test, y_test)}')

结果:

[0.87595678, 0.97943611, 0.8740311, 0.93150634, 0.94679878, 0.89219105, 0.91211392, 0.97882041, 0.8539725, 0.95655506]95% CI Accuracy: 0.92 (+/- 0.09)model accuracy on test set: 0.9041657637532045

在这里,你得到了比单一快照更多的东西:重复试验的精确度的平均值和标准偏差。在这种情况下,我打印了大约 95%的置信区间。这才是值得兴奋的。

Eric Danley via Flickr CC 2.0

示例 2:使用预处理

当使用预处理时,交叉验证需要多一点额外的代码,但是仍然是完全可行的,并且为了更好地理解模型的准确性是值得的。

通常,当使用预处理时,您不应该包含您的验证数据,这样这些数据在测试阶段对模型来说是“新的”,而不是通过预处理泄露进来。为了在使用 k-fold 交叉验证时避免这种情况,您需要使用一个Pipeline将这些数据转换传递给第一个参数中的cross_val_score。尽管这增加了代码的复杂性,但它相当简单,并且对于生成模型性能的有效评估是必不可少的。

在这个例子中,我使用了同样的广告数据集和多元回归。这些特征包括电视消费、广播消费、报纸消费和电视消费*广播消费,并且该模型预测产品销售。随着管道进入cross_val_score,该功能将首先将数据分成训练和验证,然后按照make_pipeline指示的顺序使用转换器转换训练数据集,在这种情况下,在拟合到LinearRegression()之前使用StandardScaler()

# import necessary python modules and classes
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression # your model here
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn import preprocessing
import pandas as pd
import numpy as np# import data
df = pd.read_csv('data/advertising.csv')# engineer additional feature of interest
df['TVxradio'] = df['TV'] * df['radio']# slice data
X = np.array(df[['TV', 'radio', 'newspaper', 'TVxradio']])
y = np.array(df['sales'])# train-test split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=5)**# setup pipeline with preprocessing transformers
lr = make_pipeline(preprocessing.StandardScaler(),LinearRegression())**# k-fold cross validation
scores = cross_val_score(lr, X_train, y_train, cv=10)
print(scores)
print(f"95% CI Accuracy: "f"{round(scores.mean(), 2)} "f"(+/- {round(scores.std() * 2, 2)})"
)# test model on test set
model = LinearRegression().fit(X_train, y_train)
print(f'model accuracy on test set: {model.score(X_test, y_test)}')

结果:

[0.9859427, 0.97482388, 0.97914505, 0.82607816, 0.97520017, 0.98505002, 0.96018605, 0.973842, 0.984283, 0.8727062]95% CI Accuracy: 0.95 (+/- 0.11)model accuracy on test set: 0.9715483746381636

您在这里可以看到,随着这些特征的增加,平均模型精度增加,并且 95%的精度置信区间也变宽了。与我上面的更简单的模型相比,这个模型的准确性随着训练数据集的变化而变化。

期末笔记

K-fold 交叉验证是一种很好的方式,通过提供更广泛的评估,而不是单一的高度调整的试验,来提供对团队真实质量和机器学习模型准确性的洞察。它允许你最大限度地利用你的训练集,同时仍然避免由于过度适应测试集而导致的偏差。

请随意查看这个博客的 GitHub 库。

有关更多信息:

[## k-fold 交叉验证的简单介绍

交叉验证是一种统计方法,用于评估机器学习模型的技能。它通常用于…

machinelearningmastery.com](https://machinelearningmastery.com/k-fold-cross-validation/)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/71092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

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

TowardsDataScience 博客中文翻译 2019(六十)原文:TowardsDataScience Blog 协议:CC BY-NC-SA 4.0堆叠分类器以提高预测性能原文:https://towardsdatascience.com/stacking-classifiers-for-higher-predictive-performance-566f963e4840?source=collection_archive------…

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)—简介及…