TowardsDataScience-博客中文翻译-2020-二十七-

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

猫与狗——5 分钟内你的第二个端到端 CNN 分类器

原文:https://towardsdatascience.com/cats-vs-dogs-your-second-end-to-end-cnn-classifier-in-5-minutes-9adfbde08a09?source=collection_archive---------53-----------------------

Unsplash 上由 Tran Mau Tri Tam 拍照

第二个分类器?!

听起来很奇怪吗?所以,这是我 DIY CNN 模型系列的第二篇博客。你可以在这里查看第一个分类器。如果你没有读过我以前的文章,我强烈建议你读一读,因为我将在它的基础上进行构建。这个博客的格式将保持不变。我会给你一个 Colab 文件,你必须运行它(没有如果没有但是),然后再继续。

所以现在开始吧— 运行它!🏃‍♀️

是的,我知道这需要一些时间来运行。在那之前,请随意阅读。我总是希望你在前进之前运行它的原因是——它让你感觉更依赖于手头的问题陈述,并且倾向于给出更好的见解。所以更多的钱!

猫的人还是狗的人?

猫和狗的数据集没有和 Keras 打包在一起。它是由 Kaggle 在 2013 年的一次计算机视觉比赛中提供的。当时他们能够达到 95%的准确率。很酷,是吧?

在本文中,我们将重点关注 3 种不同的模型和实现更高精度的方法。酷吗?让我们开始吧。

模型 1 —基本模型

结果:~74%准确率

这和我们之前的分类模型一模一样。不过,根据问题的性质,会有一些变化。让我们简单讨论一下。

数据预处理

你有图像,但是模型在矩阵上工作!对!因此,这是几乎所有基于 CNN 的模型都需要的一步。上一篇文章中已经讨论了其中的大部分内容,所以不再赘述。所以:

1。加载图像
2。将 JPEG 内容解码为 RGB 像素网格。
3。将图像大小调整为 150
150 像素(以缩小图像大小)。
4。将像素值(0 到 255 之间)重新缩放到区间(0,1)区间*

Keras 图像数据生成器

通常,我不会深入研究实现逻辑,但这一点需要特别提及。上面的部分可能看起来工作量很大,对吗?!但是,这个美丽的 Keras 构造真的可以帮助你完成你的工作。

它在 Python 生成器上工作。如果你不熟悉它,强烈建议你这么做。简而言之,生成器是一种特殊的迭代器,工作起来很慢。与列表不同,它们不将内容存储在内存中,而是在需要时生成内容。这些迭代器不会阻塞你的内存,而是在需要的时候使用它。很神奇的东西,对吧?

卷积层++

有人可能会说——不,这个模型和之前的不一样。它有 3 层以上的回旋。罪名成立!是的,你能想出一个理由吗?

我们的手写分类器具有[28 * 28]的矩阵大小,而这里我们处理的是[150 * 150]的矩阵大小。所以,因为我们处理更大的图像和更复杂的问题,我们倾向于增加更多的层。这主要是为了在输入到达展平图层时减小输入的大小。

此外,随着越来越深入卷积层,该模型可以检测到更加复杂的模式。因此,这也增加了网络的容量。

准确率:~74%

模型 2 —解决过度拟合问题

结果:84%准确率

如果你看到上图中的结果,你会怎么想?这是一个经典的过度拟合案例。随着时间的推移,训练精度呈线性增长,但测试精度却停滞在 70%左右。让我们分析一些处理过度拟合的常用方法。

脱落层

这是一种正则化技术,其中随机选择的神经元在训练过程中被完全忽略。他们只是被随机“丢弃”。因此,一旦训练开始,模型就开始基于所提供的数据学习专门的特征。可能发生的情况是,这些特征对于训练数据可能变得过于具体,并且可能在测试数据上完全失败。因此,为了增加一层随机性并使其更通用,采用了这种方法。

数据扩充

过度拟合通常发生在学习的训练样本太少的时候。因此,我们可以合理地假设,给定无限量的数据,我们的模型永远不会过度拟合,因为它已经通过接触各种图像学习得很好。

因此,通过这种技术,我们试图通过将我们的训练数据随机转换成其他可信的图像来创建更多的训练数据。您可以旋转图像、翻转图像、缩放图像等,并创建一个全新的不同图像,为您的模型提供更多不同的训练数据集。

准确度— 84%

模型 3 —预训练的 CNN

结果:94%准确率

为什么要重新发明轮子?!当有人已经做到了,为什么还要从头开始呢?这是这种方法背后的主要直觉。

特征抽出

正如我们前面提到的,表现最好的网络是那些经过无限数据训练的网络。比方说,某个很有权力的人,在 ImageNet 上训练了一个网络(这个数据集包含数百万张动物图片)。我们应该能够直接重用这个在许多动物身上训练的特定模型来检测我们的猫和狗的用例。

但通常情况下,只建议重用卷积层,而不是内部 FC 层。主要原因是在卷积层学习的内核可能有点通用,可以很容易地重用。比方说,检测眼睛和鼻子的能力可以很容易地被我们的系统重用。

但是,在 FC 层中学习的权重可能更具体地针对问题的性质,并且可能对我们的特定用例没有太大价值。比方说,当需要检测 100 类动物时,这些 FC 砝码可能表现良好,但当只需要检测 2 类动物时可能会失败(根据我们的用例)。

微调

随着卷积层深度的增加,检测复杂特征的能力也增加。因此,我们可以说,在初始层中,它可能只是检测一条垂直线或水平线或某种颜色,但随着你向前移动到层中,它可能最终会检测到更复杂的特征,如猫的胡须或狗的尾巴或斑马的鳞片等。

因此,在使用预训练的网络时,而不是复制所有的卷积层,可以认为只是按原样采用初始层,并训练(微调)另一个深度卷积层。复杂的内核可能不适合我们的用例。

比方说,一个内部卷积层,当对数百万只动物进行训练时,学会了一个可以检测斑马纹的内核,但在我们的猫和狗的用例中,我们可能根本不需要它。因此,我们可能应该重复使用初始层,但可以微调内部回旋。

准确度— 94%

我希望这给你一个很好的概述,可以部署的想法,以提高 CNN 网络的准确性。今天就到这里吧,伙计们!

大部分内容都受到了《用 Python 进行深度学习》这本书的极大启发。这是一本免费的书。如果有机会,一定要把这本书读完。

Python 中的因果影响 R 包

原文:https://towardsdatascience.com/causal-impact-r-package-in-python-bc005f63f4c2?source=collection_archive---------20-----------------------

因果关系

如何在您的 Python 环境中运行 Google 的 CausalImpact R 包

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash拍摄的照片

CausalImpact 是 Google 开发的一个 R 包,用于使用贝叶斯结构时间序列模型进行因果推断。这里可以找到 R 版

简而言之,这个软件包所做的是做出反事实的预测。换句话说,如果干预从未发生,在平行宇宙中会发生什么?这里有一个直接来自谷歌网站的快速示例:“给定一个响应时间序列(例如,点击量)和一组控制时间序列(例如,在未受影响的市场上的点击量或在其他网站上的点击量),该软件包构建了一个贝叶斯结构时间序列模型。然后,该模型被用于尝试和预测反事实,即,如果干预从未发生,那么干预后的反应指标将如何演变。”

因果影响 1.2.1,Brodersen 等人,《应用统计学年鉴》(2015)。http://google.github.io/CausalImpact/

图像描述:图像(原始)的 A 部分用连续的黑线显示了我们正在监控的事物的时间序列。蓝色虚线部分是反事实预测。垂直灰线是进行干预的时刻。我们可以观察到,从那时起,蓝线和黑线逐渐分开。B 部分(逐点)说明了这些线随时间的差异,这实质上是我们感兴趣的因果效应,而 C 部分(累积)是随时间的累积差异。

我知道您可以使用 R,但是对于 Python 爱好者来说,我不知道有什么等价的包。当然,有一些库实现了原始论文的一部分。通过检查一些 Python 实现,我注意到了结果的不同。长话短说,在这里您可以查看如何从 python 运行这个包。类似地,这种方法可以推广到任何 R 包。

对我有用的是创建一个新的 Conda 环境,预装了 Python 库和 core R 包。这里有一个例子:conda create -n r_env numpy pandas statsmodels r-essentials r-base

创造环境需要一些时间。另外,请注意,Jupyter notebook 需要进一步配置,所以我倾向于在任何编程编辑器中编辑代码,并从命令行运行。

我们还需要的是为我们做所有工作的rpy2。它是 R 语言的 python 接口。pip install rpy2就行。

如下加载所有库:

**#rpy2 lib**
from rpy2.robjects.packages import importr
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
from rpy2.robjects import Formula
import rpy2.robjects.packages as rpackages
import rpy2.robjects.vectors as StrVector
from rpy2.ipython.ggplot import image_png**#typical python libs**
import numpy as np
import pandas as pd
import datetime**#arma**
from statsmodels.tsa.arima_process import ArmaProcess

创建一个至少有 3 列的 Pandas dataframe,1 列用于datetime(下面我们将使其成为一个索引),一个预测值x1或更多(x2,x3,x4,…,xn)和一个响应变量y。这假定您已经准备好数据供使用,否则,您可以如下创建一些数据:

**# Creating synthetic data - skip this if you are running it on your # own data - The data generation is taken from #**[**https://github.com/dafiti/causalimpact**](https://github.com/dafiti/causalimpact)ar = np.array([1, 0.9])
ma = np.array([1])
arma_process = ArmaProcess(ar, ma)
X = 100 + arma_process.generate_sample(nsample=100)
y = 1.2 * X + np.random.normal(size=100)
y[70:] += 5base = datetime.datetime.today()
dt = [base - datetime.timedelta(days=x) for x in range(100)]df = pd.DataFrame({'y': y, 'x1': X,'date':dt}, columns=['y', 'x1','date'])

如上所述,确保将datetime作为索引。

**#make datetime an index to the df**
df.set_index('date',inplace=True)

根据dataframe中的索引datetime定义干预前的时间段和干预后的时间段。

**#Set pre and post intervention periods**
pre_period = [0, 69]
post_period = [70, 99]**#R conversion**
pre_period=robjects.FloatVector(pre_period)
post_period=robjects.FloatVector(post_period)

这将为您提供从周期开始到干预(pre_period)和从干预到数据中最后一天(post_period)之间的时间间隔。

**#Load R libraries from within Python - R interface** utils=rpackages.importr('utils')
utils.chooseCRANmirror(ind=1)
packnames=('CausalImpact','bsts') # any other R library required
names_to_install = [x for x in packnames if not rpackages.isinstalled(x)]**#Load package required to install R packages**
from rpy2.robjects.vectors import StrVectorif len(names_to_install) > 0:
    utils.install_packages(StrVector(names_to_install))

这可能需要一些时间;喝点咖啡,再来点。

但是现在我们在这里。准备对我们的数据进行因果推断。

robjects.numpy2ri.activate()
pandas2ri.activate()
rdf=robjects.conversion.py2rpy(df)
causalimpact=importr('CausalImpact')
impact=causalimpact.CausalImpact(rdf,pre_period,post_period)summary_func=robjects.r('function(x) summary(x)')
summary_func(impact)**#Summary with descriptive report**
summary_report_func=robjects.r('function(x) summary(x,"report")')
summary_report_func(impact)**#Create causality plot**
img_file='causalimpact.png'
rstr="""
library(ggplot2)
function(x,y){
p<-plot(x)
ggsave(y,plot=p)
}"""rfunc=robjects.r(rstr)
rfunc(impact,img_file)

有关因果影响包的更多选项和讨论,请参见以下内容:

[## 包含“因果影响”的帖子

搜索类型搜索语法标签[tag]确切的“单词在此”作者用户:1234 用户:我(你的)得分得分:3 (3+)得分:0…

stats.stackexchange.com](https://stats.stackexchange.com/search?q=causalimpact) [## 因果影响

这个包是做什么的?这个 R 包实现了一种方法来估计因果效应的设计…

google.github.io](http://google.github.io/CausalImpact/CausalImpact.html)

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

数据科学家的因果推理备忘单

原文:https://towardsdatascience.com/causal-inference-cheat-sheet-for-data-scientists-a1d97b98d515?source=collection_archive---------35-----------------------

为什么因果洞察力对商业很重要,以及如何使用你的数据来推断因果关系

对于任何数据科学团队来说,无论其规模大小,能够做出因果声明都是一个关键的商业价值。快速分析(换句话说,描述性统计)是任何优秀数据分析师的面包和黄油,他们与产品团队一起快速循环,以了解他们的用户。但有时会出现一些需要更精确答案的重要问题。商业价值有时意味着区分什么是真正的洞察力,什么是偶然的噪音。与临时营销材料相比,见解将站得住脚。换句话说因果关系

回答这些问题时,需要绝对的严谨。未能理解关键机制可能意味着错过重要的发现,推出错误版本的产品,并最终使您的企业损失数百万美元或重要的机会。
微软实验团队前主管罗恩·科哈维有一个的著名例子:改变 Amazon.com 上展示信用卡优惠的地方为公司带来了数百万的收入。

在过去的 6 年中,科技行业已经开始接受这一趋势,使得因果推理成为数据科学中的一个热门话题。网飞微软和谷歌都围绕因果方法的一些变体建立了完整的团队。因果分析也是(终于!)在纯 AI 领域获得大量牵引力。因此,了解因果推理方法能为你和你的企业做些什么变得越来越重要。

证据阶梯的因果推理层次

因此,因果推理阶梯小抄!除了对数据科学家本身的价值,我过去还成功地向内部客户展示了这张幻灯片,以解释我们是如何处理数据并得出结论的。

“阶梯”分类解释了每种方法将提供给你的级证据。越高,就越容易确保您的方法得到的结果是真实的和可重复的——缺点是实验的设置会更复杂。例如,设置 A/B 测试通常需要专门的框架和工程资源。
沿着阶梯往下走的方法在设置上需要较少的努力(想想:观察数据),但在分析的严密性上需要更多的努力。确保你的分析有真实的发现,而不仅仅是评论一些噪音(或者更糟,完全是错误的),这是一个叫做稳健性检查的过程。这可以说是任何因果分析方法中最重要的部分。如果我是你的评审,你的方法越靠下,我需要的健壮性检查就越多🙂

我还想强调的是,较低级别的方法并没有降低价值——事实恰恰相反!它们是允许使用观察数据得出结论的卓越方法,如果像过去 10 年中为这些方法做出重大贡献的苏珊·阿塞圭多·因本斯这样的人有一天被授予诺贝尔奖,我也不会感到惊讶!

梯级 1 —科学实验

阶梯的第一级是典型的科学实验。你可能在中学甚至小学都学过的那种。为了解释科学实验应该如何进行,我的生物老师让我们从一个盒子里取出种子,把它们分成两组,然后把它们种在两个罐子里。老师坚持让两个罐子里的条件完全相同:同样数量的种子,同样湿润的土地,等等。我们的目标是测量光对植物生长的影响,所以我们把一个罐子放在窗户附近,把另一个锁在壁橱里。两个星期后,我们所有靠近窗户的罐子都长出了漂亮的小芽,而我们放在壁橱里的那些几乎没有长出来。
暴露在光线下是这两个罐子的唯一区别,老师解释道,我们被允许得出结论光线不足导致植物无法生长。

听起来够简单吧?当你想确定原因时,这基本上是最严格的了。坏消息是,只有当你对你的治疗组(接受光线的那个)和你的对照组(橱柜里的那个)都有一定程度的控制时,这种方法才适用。足够的控制至少所有的条件都是严格相同的但是你正在试验的一个参数(在这种情况下是光)。显然,这不适用于社会科学,也不适用于数据科学。

那么你可能会问,为什么我要把它放在这篇文章里?因为这是参考方法。所有的因果推断方法在某种程度上都是为了重现这种简单的方法,如果你严格遵守中学老师解释的规则,你就不能得出结论。

梯级 2 —统计实验(又名 A/B 测试)

可能是科技界最著名的因果推断方法:A/B 测试,也就是我们生物统计学朋友的随机对照试验。统计实验背后的想法是依靠随机性和样本大小来减轻无法将你的治疗组和对照组置于完全相同的条件下。基本统计定理,如大数定律中心极限定理贝叶斯推理保证了这一点,并提供了一种从您收集的数据中推断估计值及其精度的方法。

可以说,实验平台应该是任何数据科学团队应该投资的第一批项目之一(当然,一旦所有的基础水平都到位)。在科技公司建立实验文化的影响已经被很好地记录下来,并为谷歌、亚马逊、微软等公司带来收益。数十亿美元。

当然,尽管理论上相当可靠,A/B 测试也有自己的一套警告。罗恩·科哈维和微软实验平台的其他创始成员撰写的这份白皮书非常有用。

梯级 3 —准实验

尽管 A/B 测试(或 RCT)可能很棒,但在某些情况下,它们就是无法执行。这可能是因为缺乏工具(技术中的一个常见情况是当一个特定的框架缺乏适当的工具来超级快速地建立一个实验,并且测试变得适得其反),道德问题,或者仅仅是因为你想事后研究一些数据。幸运的是,如果你处于其中一种情况,有些方法仍然能够得到一个因素的因果估计。在第三章中,我们谈论了准实验(也称为自然实验)的迷人世界。

准实验是这样一种情况,你的治疗组和对照组被一个自然过程分割,这个过程不是真正的随机的,但可以被认为足够接近于计算估计值。在实践中,这意味着你将有不同的方法,这些方法将对应于关于你有多“接近”A/B 测试情形的不同假设。自然实验的著名例子包括:利用越战征兵彩票来估计成为一名老兵对你收入的影响,或者利用新泽西州和宾夕法尼亚州的边界来研究最低工资对经济的影响。

现在让我给你一个公平的警告:当你开始寻找准实验时,你会很快被它迷住,并开始考虑在不可能的地方聪明地收集数据…现在你不能说你没有被警告过😜我有不少朋友因为对自然实验的热爱而被计量经济学的职业所吸引。

准实验世界中最流行的方法是:差异中的差异(最常见的方法,根据因果推理混合磁带的作者 Scott Cunnigham 的说法);回归不连续设计匹配工具变量(这是一个绝对出色的构造,但在实践中很少有用)。如果你能够观察(即收集数据)解释治疗和控制如何分离的所有因素,那么一个简单的线性回归包括所有因素将会给出好的结果

梯级 4——反事实的世界

最后,你有时会想尝试从纯粹的观察数据中发现因果因素。技术领域的一个经典例子是,在没有进行 A/B 测试的情况下,评估一项新功能的效果,并且没有任何一组人没有收到您可以用作对照的功能:

略微改编自因果影响的文档

也许你在想:等等……你是说我们可以简单地查看前后的数据,然后做出结论吗?嗯,诀窍在于,通常做一个严格的分析或者甚至计算一个估计都不是那么简单。这里的想法是创建一个模型,允许计算一个反事实控制组。反事实意味着“如果这个特征不存在,会发生什么”。如果你有一个用户数量的模型,你有足够的信心做出一些稳健的预测,那么你基本上拥有了一切

不过有一个问题。当使用反事实方法时,你的预测的质量是关键。在不涉及太多技术细节的情况下,这意味着你的模型不仅要足够准确,还需要“理解”什么潜在因素在驱动你目前观察到的情况。如果一个与你的最新部署无关的混杂因素发生了变化(例如经济气候),你不希望把这种变化归因于你的特性。如果你想做出因果关系的声明,你的模型也需要理解这一点。

这就是为什么在使用反事实时鲁棒性检查如此重要。一些很酷的因果推理库,比如微软的道为什么会自动为你做这些检查😲像在 R 包 tipr 中实现的灵敏度方法对于检查一些假设也非常有用。最后,我怎么能在不提及 DAGs 的情况下写一篇关于因果推理的完整文章呢?它们是一种广泛使用的工具,用来陈述你的假设,尤其是在梯级 4 方法的情况下。

(快速补充说明:现在,由于前所未有的新冠肺炎危机,很可能各种应用中使用的大多数预测模型都已经过时了。显然,那些不能用于反事实的因果分析)

从技术上讲,梯级 4 的方法看起来很像梯级 3 的方法,只是做了一些小的改动。例如, synthetic diff-in-diff 是 diff-in-diff 和 matching 的组合。对于时间序列数据来说, CausalImpact 是一个非常酷的知名 R 包。 causalTree 是另一个值得关注的有趣方法。更一般地说,由领域专家精心制作并经过严格测试的模型是仅使用反事实控制组进行因果推断的最佳工具。

希望这份备忘单能帮助您找到正确的因果分析方法,并对您的业务产生影响!请在我们的 Twitter 上或评论中告诉我们您的最佳#causalwins!

原载于 2020 年 4 月 29 日 http://nc233.com**的

钢铁厂的因果推理

原文:https://towardsdatascience.com/causal-inference-for-a-steel-mill-1e4dff991501?source=collection_archive---------40-----------------------

如何为钢铁厂创建一个结合了人类专业知识和因果推理原理的数据科学产品。

照片由 severstal.com 谢维尔斯塔尔拍摄

我们的项目

我想分享我为圣彼得堡附近的谢韦尔钢铁厂创建数据科学产品的经验。我们在这家工厂生产 5 米宽的钢卷。例如,您可以用这种钢制造石油和天然气管道。作为输入,你发送一个 20 吨重的钢板,经过 15-30 次迭代后,钢板就变成了预期厚度的钢板。

下面是您可以观看的视频,以便更深入地了解这一过程:

在我们的项目之前,一个操作员习惯于为每次迭代手动选择一个速度,我们的目标是自动化这个过程。我们的模型现在工作在实时模式下,我们可以观察到模型的速度比人的速度快 5+ %。

为什么不能在每次迭代中选择最大可能的速度?速度越高,发动机上的电流(I)越高,如果电流超过阈值,发动机将停止工作以防止故障。因此,操作员选择速度时要考虑厚度、delta(迭代前后的厚度差)和其他参数。

数据

为简单起见,我们假设我们的数据中只有厚度、增量、速度和电流。

让我们的数据集中有 20000 次迭代。让我们从最小值等于 5、最大值等于 15 的均匀分布中生成厚度,并从最小值等于 1、最大值等于 4 的相同分布中生成增量。这意味着迭代前的金属厚度将在 5 到 15 之间,并且该厚度将在每次迭代中减少 1-4 点。

假设操作员根据以下规则选择速度:

df['speed'] = np.round(25 - 0.1 * df['thickness'] ** 0.9 - 4 * df['delta'] ** 1.1

此外,操作员可以以 5 %的概率选择高 1 个单位的速度,或者以相同的概率选择低 1 个单位的速度。

因此,我们的速度在 4.61–21.47 范围内。

让我们的电流服从这个规则:

df['I'] = 3000 + 1500 * (df['thickness'] ** 0.8 + 5 * df['delta'] ** 1.4) + 2000 * df['speed']

此外,让我们给电流增加一些噪声。噪声取自标准偏差等于 500 的正态分布。

因此,我们可以将数据集分成三个部分:训练集中的 15000 个观察值,2500 个开发,2500 个测试。

让电流过剩从 78647 个单位开始——这是一种罕见的情况,在我们的数据集中频率约为 0.3 %。

我们的研究都准备好了=)

直接法

你可以选择错误的方式来处理这个问题:选择一个强大的算法,在你的数据上训练它。例如,您可以使用梯度推进,训练它,改变速度,以提高生产率,不要超过电流。

我们选择了一个具有 12 个叶子、0.1 学习率和 500 棵树的算法,我们的 RMSE 在所有数据集(训练、开发和测试)上都是 500 50。该度量非常接近实际误差(500),因此我们可以说我们的算法接近完美。

但是只有当我们在同一个发行版中工作时,这才是正确的=)

让我们为测试集中的每个观察值选择一个速度。我们将从我们的分布中以最大速度开始,并且如果我们的电流预测小于临界速度减去三个标准偏差,我们将停止。作为标准差,我们取 600(我们的 500 50 和小保):

我们的新速度比旧速度提高了 30 %以上!伟大的结果!

让我们看看我们的引擎是如何工作的。由于我们知道虚拟世界中速度和电流之间的真实依赖关系,我们可以模拟我们的实验结果:

0.3168

因此,我们有 31.7 %的情况下,我们的电流高于临界,这是 100 倍以上的手动控制期间的频繁事件。这怎么可能呢?当我们训练我们的算法时,它没有任何关于速度和厚度与δ之间因果关系的信息。因此,我们的算法记住了速度、厚度和δ的每种组合的电流。如果我们改变速度,模型仍然看到旧的厚度和增量,并认为一切都会好起来。在这种情况下我们能做什么?

也许我们应该预测一个速度?

我们的目标是加快我们的工厂。我们知道,在类似的情况下,操作员可以做得更好或更差。因此,我们可以根据过去的最佳速度来预测速度!

对于这些类型的问题,k-NN 是一个完美的算法(我们可以通过它从过去准确地选择一个速度):

使用该算法,我们可以在电流过剩率仅为 0.24%的情况下实现 1.2 %的生产率增长:

1.0110062977330752
0.0024

伟大的结果!但是我们能做得更好吗?

因果推理

为了达到比我们从 k-NN 得到的更好的速度,我们应该提取速度和电流之间的真实相关性。当我们的数据集只包含相互依赖的观察值时,我们该如何做呢?我们可以开始一个实验,但是在真正的工厂里这是一个昂贵的方法。然而,我们可以使用因果推理方法来处理相互依赖关系。

我们想演示一种最简单的因果推理方法。这个方法很简单,但也很有效:

1)让我们创建一个模型,通过厚度和增量来预测速度。这个模型不应该太精确,但应该包含变量之间的依赖关系:

2)让我们根据该模型的预测来分割我们的数据集,因此在该数据集的每个部分都将有相似的预测。然后,我们在每个数据集上训练不同的线性回归模型:

3)现在我们的系数更接近 2000 年:它们从 1924 年到 2031 年变化。如果我们创建一个没有这种分裂的线性回归,我们将得到一个等于 1404 的系数,这将导致我们低估速度的影响,结果,电流过剩。为什么这种方法有效?我们可以假设,通过这些箱对我们的原始数据集的分割允许我们检测相对于速度具有相似厚度和增量值的集合。因此,我们可以更好地确定速度和电流之间的关系。

4)现在,我们可以取这些系数的最大值,并根据这些信息选择速度:

0.0004
1 . 56687 . 68686868661

电流过剩比以前少!我们已经实现了 30 %的速度提升!

5)我们看到结果与我们的测试集一致:

0.0008
1 . 58681 . 38686868661

它比直接方法好得多=)

结论

在这个虚拟例子中,我们有一个不公平的优势,因为我们知道速度和电流之间的真实依赖关系,所以我们可以看到当速度增加时,电流实际上会发生什么。在现实世界中,它是未知的。我们可以根据历史数据来测试我们的模型,但是在现实世界中,我们的模型可能会导致电流过剩并使工厂停止运转。所以,我们可以做两件简单的事情来防止风险:

1)我们可以从一小步一小步的速度开始改进。因此,当它明显不同时,我们可以足够接近我们的历史分布和轨迹。

2)此外,我们可以从一个不直接控制磨机速度的推荐系统开始。因此,运营商应在试点的第一阶段确认我们的建议。

在很短的时间内,操作员将开始对所提出的系统有信心,并且它可以随着速度的逐渐增加而转换到全自动化模式。今天,我们工厂的最大速度比一年前提高了约 33 %,平均速度提高了 5 %以上。

对了,如果你想了解更多的因果推断,可以从这个教程开始。

这篇文章的完整代码可以在这里找到。

数据科学家的因果推理:一种怀疑的观点

原文:https://towardsdatascience.com/causal-inference-for-data-scientists-a-skeptical-view-f8c294cfea0?source=collection_archive---------38-----------------------

因果推理如何以及为什么让我们失败

UnsplashNeONBRAND 拍摄的照片

介绍

这篇文章的目的是展示为什么因果推理是困难的,它如何让我们失败,以及为什么 DAGs 没有帮助。

机器学习从业者关心的是预测,很少关心解释。这是一种奢侈。我们甚至研究那些没有数据生成过程可以记录下来的问题。没有人相信一个根据莎士比亚戏剧训练出来的 LSTM 模式会奏效,因为它接近莎士比亚。然而它是有效的。

近年来,因果推理的新工具已经为更广泛的受众所用。这些工具承诺帮助非专家不仅预测,而且解释数据中的模式。有向无环图和 do-calculus 是其中最有影响力的。

人们喜欢闪亮的工具,这里面有危险。新工具的出现伴随着采用它们的热潮,伴随着一种处于先锋地位的感觉,伴随着新的机遇。这往往使它们变得不可靠:它们被误用,被更好的理论、设计或数据所替代。

在这篇文章中,我将重点放在有向无环图和 Python 库上,因为 Dag 在机器学习社区中非常流行。我提出的观点同样适用于潜在结果框架,或者任何其他表达因果关系的正式语言。

为什么理论上因果推理很难

因果推理依赖于因果假设。假设是允许从统计关联到因果关系的信念。

随机实验是因果推断的黄金标准,因为治疗任务是随机的,并且是物理操纵的:一组得到治疗,一组没有。这里的假设是简单明了的,通过设计是安全的,并且可以方便地进行辩护。

当无法控制治疗分配时,比如说观察数据,研究人员试图对其建模。这里的建模相当于说“我们假设在对年龄、性别、社会地位和吸烟进行调整后,跑步者和非跑步者彼此如此相似,就好像他们被随机分配到跑步中一样。”然后一个人可以在跑步上回归预期寿命,宣称‘跑步增加了 n %的预期寿命’,然后收工。

这种方法背后的逻辑是笨拙的。它隐含地假设我们确切地知道为什么人们开始跑步或长寿,唯一缺少的是我们试图估计的东西。一个不太可信、有点绕口的故事。此外,一个令人高兴的巧合是,我们模型的所有部分都有可用的经验代理,测量无误。最后,由于没有原则方法来检验选择模型在多大程度上接近真实的分配机制,所以它的所有假设都可以永远争论下去。

Jaas Sekhon [1]很好地总结了这种情况:

“如果没有实验、自然实验、不连续性或其他强有力的设计,再多的计量经济学或统计模型也无法让从相关性到因果关系的转变具有说服力”

为什么因果推理在实践中很难

实际例子更好地说明了上面提出的问题。虽然有很多,但我坚持三个,其中一个来自经济学、流行病学和政治学。

1986 年,罗伯特·拉隆德展示了计量经济学程序如何不能复制实验结果。他利用了一个实验,在这个实验中,个人被随机挑选到工作项目中。随机化让他能够估计一个项目对收入的无偏影响。他接着问:如果没有随机化,我们会得到同样的估计吗?为了模拟观察数据,拉隆德建立了几个非实验对照组。在比较估计值后,他得出结论,计量经济学方法无法复制实验结果[2]。

流行病学也有同样的问题。想想高密度脂蛋白胆固醇和心脏病的故事。人们认为“有益的胆固醇”可以预防冠心病。研究人员甚至宣称观察性研究对协变量调整是稳健的。然而几年后,随机实验证明高密度脂蛋白并不能保护你的心脏。对于流行病学来说,这种情况并不独特,许多流行病学的发现后来被随机对照研究推翻[3]。

民主增长研究是当年政治学的热门话题。研究人员将人均 GDP 或类似的指标放在等式的左边,民主放在右边,为了避免过于简单,他们在左边放了一堆控制指标:预期寿命、受教育程度、人口规模、外国直接投资等等。从 2006 年之前发表的 81 篇论文中的 470 个估计值来看,其中 16%显示了民主对增长的显著和负面影响,20%是负面但不显著的,38%是正面但仍然不显著的,38%的估计值是正面和显著的[4]。

这种模式很明显:无论研究人员对他们的观察研究多么自信,也不一定能让他们更接近真相。

为什么 DAGs 理论上不能解决问题

狗很棒。它们具有强大的表达能力和很好的推理特性:考虑到 do-calculus 的完备性,如果一个效应不能用 do-calculus 来识别,那么它在别处也不是不可定义的,至少在没有额外假设的情况下是如此。它们也是有教育意义的:试着画一个简单的仪器变量设置自己去看。

但这不是重点。关键是,dag 提供的好处发挥得太晚了,无法将我们从观察数据中的因果推断的恐惧中解救出来。的确,给定一个特定的图形,微积分告诉我们什么可以估计,什么不可以。然而,它没有告诉我们如何构建一个有意义的 DAG。

有一句乔治·博克斯的名言[5]:

“既然所有的模型都是错误的,科学家必须警惕什么是严重错误。国外有老虎,关心老鼠是不合适的。”

这里的可怕的老虎有太多可观察的变量来推理,天知道有多少不可观察的变量,我们用噪音测量的东西,我们甚至不能测量的东西。在这种情况下,真实的图形是未知的,当真实的图形是未知的时候,我们的推论是否正确的答案是“不知道”或者“不知道”。

考虑到这一点,当我们添加“如果正确的 DAG 为他们所知”[6],[7]时,关于 DAG 的许多事情变得不那么令人困惑:

“选择一组适当的协变量来控制混杂的任务已经简化为一个简单的“路障”难题,可通过简单的算法进行管理,【如果正确的 DAG 已知】

“如果我们能够从我们的观察数据中生成用于这个图的相同数据,但使其成为因果关系,这不是很好吗?借助现代因果推理方法,我们可以!【如果已知正确的 DAG】

为什么 Dag 在实践中不能解决问题

道为什么是一个伟大的图书馆。作者尽一切努力提醒用户因果推断是困难的。然而,根本问题依然存在。考虑下面的引用:

从概念上讲,DoWhy 是遵循两个指导原则创建的:明确询问因果假设,并测试估计值对违反这些假设的稳健性。

核心假设是所选择的 DAG 是众多可选 DAG 中的正确一个——这个假设没有健壮性检查。也很容易被侵犯。

让我们违反它。我将使用 DoWhy:因果推断的不同估计方法中描述的设置。有 5 个共因 W ,2 个仪器 Z ,一个二元处理 v0 ,其他所有效应都有界在[0,0.5 × βv0 以内,结果 y 完全由可观测变量集合决定。真实治疗效果 βv0 为 10。

来自https://Microsoft . github . io/dowhy/dowhy _ estimation _ methods . html

虽然有很多方法可以错误地指定一个模型,但是我将模拟一个非常简单的方法:缺少一个变量 U 。即使少了一个变量,人们也能画出 511 种不同的箭头组合。我将只坚持可能情况的子集: U →结果, U →结果和治疗, U →结果和随机常见原因, U →治疗和随机常见原因 U →随机仪器和治疗, U →随机仪器和结果。

在该教程中,作者使用了六个估计值,并设法通过线性回归、倾向得分分层、倾向得分匹配、倾向得分加权和工具变量五次接近 10。在我的模拟中,我将使用所有五种方法。我将单独分析 IVs,因为它们不依赖于后门标准。

后门估计量与未观测协变量 U

首先要注意的是,当违反后门标准时,就像在 U 影响治疗和结果的情况下,所有的估计都有明显的偏差。这并不奇怪——我们不能故意违反一个假设,并期望依赖它的程序能够工作。然而,给定的图离真正的图只有一个节点和两条边。这仍然足以扭曲估计。事实上,这个玩具示例是稳健的:所有其他影响都明显小于治疗影响,一次只有一个共同原因受到影响,只有一个不可观察的变量丢失,一切都测量无误。实际上,这种情况很少见。

另一件要注意的事情是,回归估计比倾向得分估计做得更好。这是因为回归更简单。例如,当治疗和共同原因受 U 影响时,回归是无偏的,因为在治疗和结果之间仍然没有开放路径。这不适用于倾向得分估计,因为倾向得分估计是两阶段过程,需要两组假设。为了估计倾向分数本身,一组可观察值 W 必须满足关于治疗的后门标准。因为在 W 和通过 U 的处理之间有一个开放路径。

现在,让我们转向工具变量。拥有一件好的乐器是很难得的。拥有两种乐器是前所未有的奢侈。在本教程的玩具示例中,有两个有效的乐器: Z0Z1 。我将设置 U 随机影响乐器,即使只有 Z0 用于估算。我还将设置 Z0Z1 为连续。

IV 估计量与未观察到的协变量 U

这里,与后门相反,当 U 影响治疗和结果时,估计值不会有显著偏差。IV 估计器如此稳健的原因是只有一个箭头从 Z0 指向 v0 。这有助于满足两个假设:(I)在 Z0v0 之间存在联系,以及(ii)从图中移除 v0 使得 Z0y 之间没有联系。那么,如果 Cov[ UZ0 ] = 0,Cov[ yZ0 ] ≠ 0,那么处理效果就是简单的 Cov[ yZ0 ]/Cov[ v0Z0

然而,如果从 UZ0 的箭头存在,那么 Cov[ UZ0 ] ≠ 0,这违反了排除限制假设(ii)——即 Z0 影响结果的唯一路径是通过治疗。在这个模拟中,这就是当 U 影响仪器 Z0 和结果的情况。

结论

有向无环图和 do-calculus 很可能是最有效的工具。它们不会帮助你从数据中获得因果结论,而这些结论并不存在。

参考

[1] J. S. Sekhon,用于比赛的鸦片制剂:因果推理的匹配方法 (2009),《政治学年度评论》,12,487–508。

[2] R. J. LaLonde,《用实验数据评估培训项目的计量经济学评估》 (1986),《美国经济评论》,604–620 页。

[3] N. Krieger 和 G. Davey Smith,回应:面对现实:我们的流行病学问题、方法和任务之间的生产性紧张 (2016),《国际流行病学杂志》,45(6),1852–1865。

[4] H. Doucouliagos 和 m . a . ulubaolu,民主和经济增长:一项荟萃分析 (2008 年),美国政治科学杂志,52(1),61-83。

[5] G. E. P. Box,科学与统计 (1976),美国统计协会杂志,71 (356),791-799

[6] J. Pearl,因果革命七次火花对机器学习的理论障碍 (2018),arXiv 预印本 arXiv:1801.04016。

[7] A. Kelleher 和 A. Sharma,介绍用于因果推断的 do 采样器 (2019),中

通过因果影响进行因果推理

原文:https://towardsdatascience.com/causal-inference-via-causalimpact-b0551b6dae92?source=collection_archive---------25-----------------------

CausalImpact 简介 Google 的一个开源包

图片由 PixaBay 上的 Jarmoluk 拍摄

什么是因果推断?

维基百科对它的定义是,根据一个结果发生的条件,得出一个关于因果联系的结论的过程。简而言之,因果推断是关于确定事件/变化对期望结果指标的影响。例如,如果一个新推出的营销活动对公司的销售产生了影响,或者一项新的法律对人们的行为产生了影响。虽然查看图表并比较前期和后期可以给出一个好主意,但在大多数情况下,这还不够好。尤其是在风险很大的情况下,例如数百万美元的营销预算。在医学或公共政策领域,确定事件的因果影响变得更加重要,因为这样的决定会影响数百万人。

因果推理的局限性:

假设发生了一个事件/处理,例如营销事件。让我们用这个药片来代表它:

治疗(由 Kate HliznitsovaUnsplash 拍摄)

通过观察我们知道这是治疗后的结果:

快乐的顾客(照片由 Lidya NadaUnsplash 上拍摄)

同样重要的是知道如果事件没有发生会发生什么。让我们用这个来表示否则会发生的结果:

悲伤的顾客(照片由马太·亨利Unsplash 上拍摄)

现在,通过比较两种可能的结果,我们可以推断或衡量事件的影响。我们可以说顾客高兴而不是悲伤是治疗的影响。

但现实世界中的问题是,我们如何做到这一点?我们如何同时知道发生了什么和可能发生了什么?在这种情况下,我们如何确定这种事件的因果推断?

让我们通过列表和比较各种场景来使其更加清晰:

表 1

假设有两个人,1 和 2,他们都暴露在治疗/事件中。通过让他们都接受治疗,我们也可以观察到所呈现的结果。但是我们不知道否则会有什么样的结果。

因为不可能知道它,我们能做的下一个最好的事情是估计其他可能的结果。

随机对照试验:

随机对照试验是确定治疗对预期结果的影响的科学实验。这通常用于医疗领域,并被视为黄金标准。在 RCT,人们被随机选择并分成两组,一组接受治疗,另一组不接受。由于所涉及的随机性,两组被认为是相似的,结果的任何差异都可以归因于治疗的差异。

再次将上述内容列表,以便更清楚地理解:

表 2

现在有四个人,随机抽取,分组。一半接受治疗,另一半不接受。两组的潜在结果是根据另一组的结果来估计的。

表 3

这种估计的结果就是通常所说的反事实。

RCT 的局限性:

虽然 RCT 是估计因果推断的最佳方法,但它并不一定适用于所有情况。也许指挥 RCT 太昂贵或太困难了。例如,在一个小国家进行 RCT 可能太困难,因为很难将其分为测试和控制。或者可能根本没有进行 RCT,现在正在进行回顾性研究以了解其影响。

在这种情况下,我们如何估计结果或反事实。

因果影响:

这是谷歌发布的一个库,用于在这种情况下进行因果推理。这个库只在 R 中可用,所以我将介绍它背后的逻辑以及它是如何工作的。它在合成控制的帮助下处理这种情况。

以这张瑞士法郎对欧元的图表为例。在很长一段时间里,瑞士法郎与欧元挂钩,币值稳定。但在 2015 年取消挂钩后,人民币汇率出现了大幅波动。在这种情况下,我们是否需要一个 RCT 来确定瑞士法郎如果没有与美元脱钩会是什么样子?

瑞士法郎/欧元

号码

简单地说,它将继续保持相对稳定,波动很小。这就是所谓的合成控制。这是可能的,因为这是一个简单的时间序列。

瑞士法郎/欧元

以这张图表为例:

这是一个受多种因素影响的更复杂的时间序列图。即使是像 LSTM 这样最先进的技术也很难准确预测。在这种情况下,我们如何预测反事实/合成控制?

协变量:

我们可以利用其他变量或协变量来帮助估计综合控制。这里的技巧是找到与期望指标相关的协变量,但不受处理的影响。

在上图中,y 是期望的指标,下面的 x1 和 x2 代表两个协变量。

在前期,我们训练并测试一个 ML 模型,以使用协变量预测所需的指标。

在后期,我们使用相同的模型来预测使用协变量的期望指标。预测的结果是这里的合成控制。然后将实际结果与合成对照进行比较,两者之间的差异被估计为事件对结果的影响。

型号选择:

以上就是 Google 的 CausalImpact 的工作原理简而言之。现在,您可以用各种模型进行试验,看看哪种模型有效。这可以通过将数据的前期划分为训练和验证部分以确定最佳模型来实现。

Google 软件包使用贝叶斯结构化时间序列模型。对于那些不知道贝叶斯统计如何工作的人,我写了一篇文章,你可以通过这个链接获得。简而言之,贝叶斯统计的工作原理是结合一个关于事物如何表现的先验信念,并随着时间的推移基于新的数据更新信念。

大多数时间序列模型,只是一个时间序列模型。他们不能考虑影响变化和波动的外部因素。贝叶斯时间序列模型的优势在于,它既考虑了时间序列方面,也考虑了影响结果的外部因素。在这种情况下,它通过将外部因素或协变量作为模型的先验来合并它们。通过这种方式,它可以在预测时考虑时间演变以及外部因素。

演示:

让我们看看 CausalImpact 包和一些虚拟数据的用法。

library(CausalImpact)set.seed(1)
x1 <- 100 + arima.sim(model = list(ar = 0.999), n = 100)
x2 <- 25 + arima.sim(model = list(ma = 0.246), n = 100)

我正在导入包,并在 arima.sim 命令的帮助下模拟两个时间序列。这些将是协变量。

y <- 1.2 * x1 + 0.8*x2 + rnorm(100)
y[71:100] <- y[71:100] + 10

这里我创建了一个新的时间序列 y,它是我们两个时间序列 x1 和 x2 的函数。对于最后的 30 次观察,我在数值上加了一个额外的数值来模拟一个事件/治疗的效果。

time.points <- seq.Date(as.Date("2020-01-01"), by = 1, length.out = 100)data <- zoo(cbind(y, x1, x2), time.points)matplot(data, type = "l")

将日期部分添加到序列中并绘制它。

数据图

pre.period <- as.Date(c("2020-01-01", "2020-03-10"))
post.period <- as.Date(c("2020-03-11", "2020-04-09"))impact <- CausalImpact(data, pre.period, post.period)

我根据添加治疗效果的位置定义前期和后期,然后将数据和信息传递给包。

plot(impact)

输出

第一个图叠加了原始数据和每个点的预测以及置信区间。

第二个图显示了每个点的原始数据和预测数据之间的差异以及置信区间。

第三个图通过对逐点差异求和来显示治疗的累积效果。

“summary(impact)”命令可用于提供表格形式的概述,而“summary(impact,“report”)则提供调查结果的书面报告。

一览表

总结报告

从上面我们可以更好的了解治疗的效果以及置信区间。该摘要甚至给出了由于治疗本身引起的变化的概率,以便我们知道它不是任何虚假的关系或变化。

结论:

因果推断是一个棘手的问题,我们数据科学家很少谈论。虽然这可能是因为我们通常不需要处理这个问题,但是知道如何解决这样的问题总是好的。在我们的工具箱里多一件工具,在我们的军火库里多一件武器,总不会有坏处。如果找到不受治疗影响的协变量的条件得到满足,这确实是在这种情况下使用的一种强有力的技术。

奖金:

我在参加 2019 年新加坡国立大学-NUHS 大学-麻省理工学院医疗保健数据马拉松时遇到了这项技术。我们的问题陈述围绕着估计一个事件对结果的影响,即因果推理。通过使用这个软件包,我们能够成功地完成我们的任务,并在数据马拉松比赛中获得第一名。下面是我们由最好的队友组成的团队的照片,没有他们,这一切都是不可能的:

你也可以在 LinkedIn 上和我联系。

回归的因果模型

原文:https://towardsdatascience.com/causal-models-for-regression-96270bf464e0?source=collection_archive---------7-----------------------

从相关到因果

回归是社会科学中应用最广泛的统计工具,并且在大多数现成的软件中都很容易得到。因为回归背后的统计数据非常简单,它鼓励新人在确保为他们的数据建立因果模型之前点击运行按钮。然而,理解数学是必要的,但不足以恰当地解释回归输出。事实上,回归从未揭示变量之间的因果关系,而只是解开了相关性的结构。

为了看到这一点,让我们考虑二元回归模型ŷ= a+bx。系数 b 揭示了相关系数 r(Y,X) 的相同信息,并捕获了 YX 之间的无条件关系∂ŷ/∂x
多元回归是一个完全不同的世界。多元系数揭示了 YX 之间的条件关系,即 Y 与其他回归变量的相关性被剔除后,两个变量的剩余相关性。在简单多元回归模型ŷ= a+bx+cz中,系数 b = ∂(Y|Z)/∂X 代表 YX 之间的条件或偏相关关系。我们通常的解释是“在保持 Z 不变的情况下, X 每增加一个单位,Y 就改变 b 个单位”。不幸的是,开始在回归模型中添加回归变量来解释因变量的更多变化是很诱人的。如果我们的目标是预测因变量的值,而不是对自变量和因变量之间的关系做出判断,这是好的——或者有点好,正如我们将看到的那样。逐步回归等算法将选择回归变量的过程自动化,以提高模型的预测能力,但这是以“可移植性”为代价的。通常情况下,所选择的回归变量并不依赖于因果模型,因此它们的解释能力是特定于特定的训练数据集的,并且不容易推广到其他数据集。因此,该模型不是“可移植的”。

偏相关和维恩图

为了理解为什么因果模型如此重要,我们需要理解回归系数是如何计算的。维恩图表示很方便,因为集合可以用来表示每个变量 YXZ 的总变化。对于二元回归,使用代表 YX 共变的区域 Y⋂X 计算系数 b 。两个回归量完全相关的情况是两个集合重叠的情况。
在多变量情况下,使用协变区域的子集 Y⋂X — (Y⋂Z)⋂X )计算回归系数 b 。同样, (Y⋂Z)⋂X 不计入 c 系数的计算中,尽管 YZ 都有这种变化。这是因为三个区域的交集 (Y⋂Z)⋂X 捕捉到了 Y 的总变化量,这是由两个回归量共同解释的。将接合区归属于任一系数都是任意的。

多元回归的文氏图表示

从这个回归的图解中有两个重要的收获。首先,由两个回归量 bc 解释的 Y 的总变化量不是总相关量 ρ(Y,X)ρ(Y,Z) 之和,而是等于或小于该值。当 (Y⋂Z)⋂X = ∅ 时,等式条件成立,这要求 XZ 不相关。在这种情况下,几乎没有实际可能性,二元回归中的回归系数bŷ= a+bx与多元回归的系数ŷ= a+bx+cz相同。
这让我们想到了维恩图的第二点,也是最重要的一点。回归只是数据集中变量之间静态关系的数学映射。增加模型的复杂性不会“增加”协变区域的大小,而只是决定了它们的哪些部分用于计算回归系数。没有变量之间关系的因果模型,将任何关系解释为因果总是没有根据的。实际上,多元回归中的系数 b 只代表 Y 中被 X 唯一解释的那部分变化。同样,多元系数 c 代表 Y 的变化,这是通过 Z 唯一解释

因果模型

为了从数据关系的静态表示转移到动态解释,我们需要一个因果模型。在社会科学中,因果模型通常是基于对人类行为的某种高级解释的理论。然而,一个因果模型不一定是一个理论,而是可以是任何一个在变量之间施加等级的地图。一个“层次结构”必须是沿着连接目标解释变量 X 和因变量 Y 的路径的变量的时间顺序和逻辑推导。请注意这里的推理哲学与预测哲学的不同之处:在推理中,我们总是对两个个体变量之间的关系感兴趣;相比之下,预测是在给定一组未定义的预测因子的情况下,预测一个变量的值。为了建立这种等级制度,需要解决以下问题(请注意提及的时间顺序):

  1. 在 X 确定之前确定的变量以及对 X 产生影响的变量有哪些?
  2. 在确定 X 的同时确定并对 Y 产生影响的变量有哪些?
  3. X 确定后确定的变量有哪些,对 XY 都有影响?

当定义了三种类型的变量时,因果模型是详尽的(请注意对相关性的引用):

  • 前件:X 之前定义的与 X 相关的所有变量,无论是否与 Y 相关;
  • 调节者:与 X 定义相同且与 XY 都相关的所有变量;
  • 中介:所有在 X 定义后定义的,与 XY 都相关的变量。

调解人和主持人之间的区别有时有点棘手,但我不会在这里讨论它。
使用回归估计 XY 的影响,必须在估计方程中指定 X 的所有前因和所有调节变量;相反,调解人不能被包括在内。指定中介会将 b 折叠成对 XY 的直接影响的估计,这有时很有趣,但不应与 XY 的总体影响混淆。这种效应是通过多种途径产生的,这些途径有助于协方差区域 Y⋂X

因果模型:示例

是时候介绍一个例子了。教育研究人员对学生在标准化考试中成绩的决定因素感兴趣,如 SAT、ACT、GRE、PISA 等。SAT 考试是在 400 到 1600 分之间的连续范围内评估的,特别适合回归分析。一名研究人员可能认为在 12 年级上预科班对 SAT 成绩有积极的影响,并希望验证这一假设。她认为——这是非常需要理论的地方——还有两个潜在的变量驱动着这种关系,父母的收入和 12 年级的班级排名。为了简单起见,她假设父母的收入从出生到 12 年级没有变化。因为班级排名和预科班几乎是同时进行的,所以很难说哪个决定了另一个。在她的模型中,父母收入(图中的 SES)首先被确定,它与其他变量的关系显示在下面的因果模型中(图中的 GitHub 代码)。较高的社会经济地位提供了更多的教学资源,因此决定了班级排名和预科班的参与程度。此外,SES 对 SAT 考试成绩有直接影响,因为早期天赋决定了更高水平的认知能力——如果你对这个主题感兴趣,我建议查看 Hanushek 等人,2015 。因此,收入对 SAT 考试成绩有直接影响,也通过班级排名和考试预科班有间接影响。此外,研究人员假设班级排名影响学生参加预科班的可能性,因为那些对自己的能力越不确定的学生更有可能去上课。在这个模型中,SES 和班级排名是先行变量,因此应该在估计方程中指定。

因果模型:示例(1)

第二位研究人员认为,这种关系反过来也是如此。参加预科班的学生更有可能在他们 12 年级的班级中排名更高。SES 仍然是先行词,而班级排名调节预科班对 SAT 考试分数的影响。因此,为了获得预科班对 SAT 成绩的总体影响,班级排名必须从估计方程中忽略。如果班级排名被包括在内——并且假设没有其他的中介变量——研究者将会估计一个直接效应而不是一个总效应。

因果模型:示例(2)

这是一个简单的例子,它忽略了教育生产函数中的许多维度。此外,我们还可以有更多的方式来思考这些变量之间的关系,以及支持一个或另一个因果模型的不同理由。然而,这个例子表明,在进行回归分析之前,研究人员将手绑在因果模型上是多么重要。回归只不过是一种工具,用来部分剔除数据中的变异,但并不能说明变量之间关系的本质。

下图比较了两个因果模型确定的协方差区域,作为预科班对 SAT 考试分数影响的因果估计。重要的是,它们不会改变协方差的基本结构,而只是决定哪些部分与推断相关。因此,因果模型是变量之间关系的静态(相关)表示和它们的动态(因果)表示之间的映射。

因果模型:文氏图表示法(1)

因果模型:文氏图表示法(2)

结论

上面粗略的例子的好处是,它警告从业者不要使用逐步回归算法和其他选择方法进行推理。这些对机器学习来说都重要吗?答案是肯定的,确实如此。尽管回归在机器学习中的典型用途是用于预测任务,但数据科学家仍然希望生成“可移植”的模型(查看约万诺维奇等人,2019 了解更多关于可移植性的信息)。可移植模型是那些不过度特定于给定训练数据并且可以扩展到不同数据集的模型。确保可移植性的最佳方式是在可靠的因果模型上操作,这不需要任何牵强的社会科学理论,只需要一些合理的直觉。

因果影响和 R:分析时间序列干预

原文:https://towardsdatascience.com/causalimpact-and-r-analysing-time-series-interventions-27a5dfaec999?source=collection_archive---------25-----------------------

分析 R 中的时间序列干预

来源:图片来自 Pixabay

免责声明:本文是在“原样”的基础上编写的,没有担保。它旨在提供数据科学概念的概述,不应被解释为投资建议或任何其他类型的专业建议。

干预(或独立于时间序列的外部因素)通常会影响所述序列。

例如,营销活动可以影响公司未来的销售额。政府政策的改变会对经济活动产生重大影响。

分析干预的主要问题是,不可能分析如果干预没有发生会发生什么——至少不可能直接分析。

R 中的因果影响库允许通过使用单独的系列(不受干预影响的系列)作为协变量来分析干预效应。

我们的例子

2017 年 11 月,英国央行决定加息。当一个国家的中央银行决定以这种方式操纵利率时——货币的价值可能会受到影响——因为这种决定会影响投资者通过持有特定货币可以获得的收益率。

资料来源:tradingeconomics.com

在这方面,我们想研究一下利率上升是否会影响英镑/美元的价值。

为此,选择欧元/美元货币作为协变量——假设该货币不受干预的影响——因为欧洲央行在此期间没有加息。

资料来源:tradingeconomics.com

相关数据来自使用 Quandl 的 FRED 数据库。

这是两种货币的曲线图:

set.seed(1)
x1 <- eurusd$Value
y <- gbpusd$Value
data <- cbind(y, x1)dim(data)
head(data)
matplot(data, type = "l")

资料来源:RStudio

处理金融时间序列时,通常会将数据转换为对数格式。虽然这在分析具有显著不同价格范围的股票价格时是有意义的,但是在这个例子中数据是“按原样”分析的。

原因是货币数据的规模比大多数其他资产价格小得多,使用对数规模会使这些值非常接近,以至于在使用对数规模时,可以在原始系列中检测到的任何干预都可能无法检测到。

使用该数据,定义了前期后期,然后绘制数据。

pre.period <- c(1, 230)
post.period <- c(231, 249)impact <- CausalImpact(data, pre.period, post.period)
plot(impact)

资料来源:RStudio

将生成影响摘要:

> summary(impact)
Posterior inference {CausalImpact}Average           Cumulative     
Actual                   1.3               25.5           
Prediction (s.d.)        1.3 (0.0099)      25.4 (0.1878)  
95% CI                   [1.3, 1.4]        [25.1, 25.8]   

Absolute effect (s.d.)   0.0014 (0.0099)   0.0275 (0.1878)
95% CI                   [-0.018, 0.02]    [-0.349, 0.38] 

Relative effect (s.d.)   0.11% (0.74%)     0.11% (0.74%)  
95% CI                   [-1.4%, 1.5%]     [-1.4%, 1.5%]Posterior tail-area probability p:   0.44186
Posterior prob. of a causal effect:  56%For more details, type: summary(impact, "report")

我们看到,预测值与实际值(平均值)在 1.3 处是相同的,累积值之间只有微小的差异(25.5 比 25.4)。

因果效应的后验概率为 56%。

让我们仔细看看生成的摘要报告。其中一部分指出:

Although the intervention appears to have caused a positive effect, this effect is not statistically significant when considering the entire post-intervention period as a whole. Individual days or shorter stretches within the intervention period may of course still have had a significant effect, as indicated whenever the lower limit of the impact time series (lower plot) was above zero. The apparent effect could be the result of random fluctuations that are unrelated to the intervention. This is often the case when the intervention period is very long and includes much of the time when the effect has already worn off. It can also be the case when the intervention period is too short to distinguish the signal from the noise. Finally, failing to find a significant effect can happen when there are not enough control variables or when these variables do not correlate well with the response variable during the learning period.The probability of obtaining this effect by chance is p = 0.442\. This means the effect may be spurious and would generally not be considered statistically significant.

与 pycausalimpact 的比较 Python 版本

当用 pycausalimpact 分析同一个例子时,结果略有不同。

该模型定义如下:

>>> ci = CausalImpact(data, pre_period, post_period)
>>> print(ci.summary())
>>> print(ci.summary(output='report'))
>>> ci.plot()

下面是生成的输出:

Posterior Inference {Causal Impact}
                          Average            Cumulative
Actual                    1.34               25.46
Prediction (s.d.)         1.32 (0.0)         25.17 (0.08)
95% CI                    [1.32, 1.33]       [25.01, 25.33]Absolute effect (s.d.)    0.02 (0.0)         0.29 (0.08)
95% CI                    [0.01, 0.02]       [0.13, 0.45]Relative effect (s.d.)    1.15% (0.32%)      1.15% (0.32%)
95% CI                    [0.52%, 1.77%]     [0.52%, 1.77%]Posterior tail-area probability p: 0.0
Posterior prob. of a causal effect: 100.0%

与 R 中的模型不同,该模型预测了因果效应的 100%后验概率。

来源:Jupyter 笔记本输出

这个库的 R 和 Python 版本在分析干预的方式上有所不同。具体来说,R 更多地依赖于先验概率,从而将先前的知识纳入模型假设中,而 Python 更多地依赖于结构性时间序列组件的分析,以便最大化似然函数。

也就是说,假设先验现在设置为,即先验 _ 级别 _ sd =无

ci = CausalImpact(data, pre_period, post_period, prior_level_sd=None)
print(ci.summary())
print(ci.summary(output='report'))
ci.plot()

结果如下:

Posterior Inference {Causal Impact}
                          Average            Cumulative
Actual                    1.34               25.46
Prediction (s.d.)         1.35 (0.02)        25.57 (0.3)
95% CI                    [1.31, 1.38]       [24.98, 26.15]

Absolute effect (s.d.)    -0.01 (0.02)       -0.11 (0.3)
95% CI                    [-0.04, 0.02]      [-0.7, 0.47]

Relative effect (s.d.)    -0.45% (1.17%)     -0.45% (1.17%)
95% CI                    [-2.72%, 1.86%]    [-2.72%, 1.86%]

Posterior tail-area probability p: 0.37
Posterior prob. of a causal effect: 63.34%

该模型确实预测了比率从 1.34 到 1.35 的变化,但是该模型指出:

The probability of obtaining this effect by chance is p = 36.66%.
This means the effect may be spurious and would generally not be
considered statistically significant.

在这点上,先验的选择可以显著影响模型的假设,从而影响干预最终是否会被检测到。

结论

在本文中,您已经看到:

  • 因果关系在预测干预中的应用
  • R 和 Python 版本之间的区别
  • 先验假设在确定干预检测中的作用
  • 干预分析和总结报告的生成

非常感谢您的阅读,欢迎任何问题或反馈。

参考

因果关系和贝叶斯网络

原文:https://towardsdatascience.com/causality-and-bayesian-networks-fcd959d4c80a?source=collection_archive---------25-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

思考因果关系是行动的必要条件,因此可以预测、预测、设计、监督、评估和诊断组织。由此产生的问题是:因果关系的本质是什么?因此,我们有一个可能性的宇宙,因果关系描述了必然发生的结果 E ,当某个原因 C 发生时。因此,我们对因果关系有一个确定的和普遍的方法。这种方法受到概率方法和贝叶斯逻辑的挑战。

概率方法:

“澳斯必须能够以此为特征,增加他们 effets 的概率”(德鲁埃,2007)。我不知道原因 c 的发生是否是影响 e 必然发生的必要条件,但是我可以说,以我有限的知识所带来的谨慎“原因 c 增加了其 effet E 的概率,因为条件概率 P(E|C)高于绝对概率 p(E )

我可以在不知道所有原因的情况下分析因果关系,或者假设所有原因的有限集都存在。我们不知道作为一个吸烟者的属性会属于 suffirait 产生肺癌的一组因素。最重要的是,不能保证这样一套存在”

这并不意味着所有的原因都是平等的,而是说它们是有条件的,我们对它们的了解是有限的。

贝叶斯网络的特征

BN 的独创性在于将图(因果)和概率耦合起来。贝叶斯网络由除了单向图之外的东西组成,并且一组箭头在作为图的顶点的一组变量上构成二元关系。在这篇文章中,我提出了进一步的解释:

[## 贝叶斯思维导论:从贝叶斯定理到贝叶斯网络

假设世界上存在一种非常罕见的疾病。你患这种疾病的几率只有千分之一。你想要…

towardsdatascience.com](/will-you-become-a-zombie-if-a-99-accuracy-test-result-positive-3da371f5134)

所以 BN 是:

  • 功能,BN 被顾问、项目负责人、管理者用于诊断或预测;
  • 专注于一个领域和一个功能。BN 允许我们在 effet 推断一组变量的因果关系
  • 一个 因果图(形式对象、逻辑等。)和基于特定人群(RB 的特定方面)的概率目标测试
  • 一个描述性模型,一个 BN 由引用不变量的节点组成,因此是一个宇宙、领域、专业等的描述性模型。它所关注的。这个描述模型由类别、属性、实例、集合关系组成。
  • 基于数据,BR 必然链接到数据源,而数据源又指的是描述性或概念性模型。换句话说,BN 和数据库之间需要一些互操作性;
  • 动态,BN 既是固定模型(机器学习)又是学习模型,在某种意义上,它可以随着时间的推移更好地学习其功能。

一个 BN 的例子,由我创作

BN 的优势在哪里?

  • have “因果经济学”:知道一个表示概率分布的无环定向图,可以大大减少定义这个分布所需的参数数量
  • 易读性:贝叶斯图中包含的信息如果用这种图形形式表示,而不是用自然语言表达,会更容易理解。应该注意的是,图形可读性与 BN 的整体形式以及其中确定的因果路径同样相关
  • 原因的可追溯性:[……]在 V 【变量集】中的任何变量,相对于其在 V 中的直接原因集而言,独立于 V 中的所有变量,它不是这些变量的因果祖先。这个假设被称为:因果马尔可夫条件”。这种情况使得通过构建 BN 来追溯原因(因此我提出了术语“可追溯性”)到独立的根本原因成为可能。但是,请注意,路径分析的目的不是首先确定一个变量是否引起另一个变量,而是量化一个变量对它引起的另一个变量的影响”
  • 代表性,BR 各组成部分的值指的是给定的人口(频率方法);
  • 可修改性,尽管具有通用性,但 BR 的组成部分的值可能会随着新数据的出现而改变。它们的外围成分可能也是如此,因为 rbd 是相加的(相对于相减);
  • 原因的共同性:通用描述模型使得将原因与类别和种类联系起来成为可能,这使得有可能通过聚类实现模块化因果方法,从而获得经济性和可读性。这就是你所做的,菲利普,通过将你的 BR 分层;

因果关系

因果关系的概率理论是概念分析。这是一个确定 A 导致 b 意味着什么的问题。

这些概率理论是对因果关系概念的一个方面的分析。换句话说,概率因果理论回答了一个关于一般因果关系的问题。这个问题可以这样来表达: 因果之间的共现关系是什么? 这个问题特别不同于 effet 的因果关系属于哪种现实的问题 (Drouet,2007)。

正如我们刚刚描述的那样,概率因果关系理论主要是作为一般因果关系的理论,而不是作为单一因果关系的理论(Drouet,2007)。一般因果关系和单一因果关系之间的区别是“吸烟导致肺癌”“彼得的吸烟导致了他的肺癌”之间的区别,或者是“跌倒导致骨折”和“我今天早上从楼梯上摔下来导致我的右手腕骨折”之间的区别。因此,一般因果关系是属性之间的关系——例如,坠落的属性和骨折的属性。

贝叶斯因果网络专门用于研究一般因果关系,而不是单一因果关系。这意味着 RB 箭头表达了一种通用的因果关系,必须有一组通用的原因和结果,这种通用保证了 RB 在时间上的结构不变性,其组成部分的量化只能用一定量的数据来完成;

使用 BN 建模时的挑战

第一个挑战与数据有关,其结构并不独立于国民银行。BN 相关算法旨在从概率中推断原因,并且独立于任何实验。事实上,通过贝叶斯网络推断因果知识的概率数据是概率观察数据。此外,根据定义,BN 被认为是从特定的前提中得出一般结论,而不管理论假设的形成。正是因为它不是从因果假设的公式化出发,所以 BN 推论可以是演绎的。当 BN 是从先前的一般描述性模型中推断出来时,情况就不是这样了。

所以我们有一个问题:BN、描述性模型和底层数据都是基于对世界的某种概念化的构造。我们并不是为一个特定世界之外的观察者提出一个通过客观数据可获得的 BN,而是为一个明确的行为者提供一个实用的工具。总之,正确的 BN 背后确实有理论模型。解决方法可能是将 BN 视为验证建模问题的一般模型的元素之一。BN 然后在这个一般模型设定的界限内,在一个微观宇宙中运作。

下一个挑战涉及 BN 作为有效推理工具必须满足的形式约束,即因果马尔可夫条件(因果关系中的所有变量都独立于所有其他变量,除了它们的父母或后代)。同样,拥有一个抽象的描述模型有助于满足这些约束。伊莎贝尔·德鲁埃(Isabelle Drouet)经过特别深入的逻辑推理,得出以下结论:“[……]使用贝叶斯网络进行因果推理只能有以下含义:将 BN 算法集成到一个假设演绎过程中[……]因果假设的说明最终总是基于理论考虑 s”。

结论

因此,BN 是检验由演绎工作产生的假设的特殊工具。这正是我们所做的:

[## 使用贝叶斯网络进行项目管理评估

这篇文章展示了五篇论文的工作,其中项目管理指标与项目绩效指标相关…

towardsdatascience.com](/using-bayesian-networks-for-project-management-evaluation-13a6eda50605)

因此,BN 并不代表一些倡导者提出的因果革命。然而,它们改变了我们构建和测试人工智能因果模型的方式。

参考书目

这篇文章是我对伊莎贝尔·杜洛埃作品的解读

如果你想继续阅读这样的故事,你可以在这里订阅!

加州消费者隐私法,PII 和 NLP

原文:https://towardsdatascience.com/ccpa-pii-and-nlp-b4165a92dc6d?source=collection_archive---------44-----------------------

CCPA 和隐私的 NLP

来源

加州消费者隐私法(CCPA)或 AB 375 于 2020 年 1 月 1 日生效,这是加利福尼亚州保护加州居民个人信息的法律。个人身份信息(PII)是可用于识别用户/客户的任何数据。通用数据保护条例(GDPR) 是 2018 年通过的一项欧盟法律,赋予欧盟居民类似的权利。随着世界各地企业收集用户数据的规模越来越大,我认为世界各地的不同政府将会通过更多这样的法律。

CCPA

CCPA 给予加州居民以下权利(按原样取自此处,第 2 节)→

**(1) The right of Californians to know what personal information is being collected about them.****(2) The right of Californians to know whether their personal information is sold or disclosed and to whom.****(3) The right of Californians to say no to the sale of personal information.****(4) The right of Californians to access their personal information.****(5) The right of Californians to equal service and price, even if they exercise their privacy rights.**

在数据泄露和其他违规的情况下,企业也必须支付罚款。

PII

来源

CCPA 的目标之一是保护消费者的 PII 信息,这意味着公司需要开发工具,以安全的方式理解和存储 PII 信息。自然语言处理(NLP)和自然语言理解(NLU)技术将发挥关键作用,因为收集的数据中有很大一部分是文本形式的,如姓名、电子邮件、地址、社会保险号、健康信息等。上图来自 Imperva 展示了 PII 的各种例子。PII 可以进一步细分为 PHI(受保护健康信息)数据和 PCI(支付卡行业)数据。

命名实体识别(NER)

NER 的任务是识别姓名、组织、地点、日期/时间等。NER 可用于识别文本数据中包含的一些个人信息。

Example- John moved from Arizona to California in December. 
Above sentence has below three entities -Person → JohnLocation → Arizona and CaliforniaDate/Time → December

因此,人们可以训练一个深度学习模型,将句子中的每个单词分类为命名实体之一或不是。然而,有几个库提供了用于 NER 任务的预训练模型。识别 PII 信息非常重要,因为它有助于快速检索此类信息、适当保护信息(通过加密等)以及控制对此类信息的访问。以下是一些可用于 NER 的库→

斯坦福核心 NLP

Stanford core NLP 是一个用 Java 编写的流行的 NLP 库,并附带了针对各种 NLP 任务的预训练,如英语和其他几种语言的 POS(词性)、NER 等。还有一个更新的项目 StanfordNLP 是一个 python 库,目前支持 POS、lemmatization 等,但不支持 NER。

空间

Spacy 是一个非常流行的 NLP 库,它的一些核心组件是用 C 语言编写的,这使得它非常快。它还带有针对 NER 的预训练模型以及针对英语和其他几种语言的其他任务。根据您的应用,Spacy 有不同尺寸的型号可供选择。模型在on notes 5 数据集上接受训练。这里我使用的是最大的英语语言模型——en _ core _ web _ LG(让我们看看如何使用 NER 的 Spacy

来源

在识别出实体之后,我们可以屏蔽它们(在上面的例子中,用“xxxx”得到“我的名字是 xxxx xxxx,我住在 xxxx ”),以保存用户的个人信息。基于本体注释 5 的空间预训练模型可以识别以下类型的实体→

空间本体注释 5 个实体— 来源

对于电话号码、电子邮件等 spacy 无法识别的信息,可以使用 regex。除了屏蔽 PII 信息,还可以加密以进一步保护它。

Presidio

Presidio 是微软专门为保护 PII 数据开发的库。它检测文本(以及图像)中的 PII 数据,然后通过编辑或加密来匿名化数据。它实际上默认使用空间 NER 模型来检测某些实体,也支持检测信用卡号码等。您还可以创建自定义的 PII 识别器。

来源

特定领域的 NER

然而,当我们想要识别特定领域的实体时,问题就来了,例如,如果您想要识别疾病或药物,在这种情况下,我们必须为自定义 NER 数据训练或微调现有模型。对于仅包含少量单词的实体,简单的查找可能有效,但是拼写错误等仍然会导致该方法失败!定制的 NER 模型可以使用空间天赋来训练。

联合学习

来源

联合学习 —联合学习是一种以分布式方式训练模型的技术,同时将原始数据保存在各个设备上以保护数据隐私。例如,在移动电话的情况下,设备下载现有的模型并针对设备特定的数据对其进行微调,因此设备数据永远不会被共享,所有个人训练数据都保留在设备上,并且更新也不会被共享。这也可以用树莓酱或其他设备来完成。分割学习是另一种无需共享任何原始数据即可训练模型的技术,与联合学习的区别在于模型是分割的,一些训练可以在服务器上完成。使用 Coral Edge TPU 或 NVidia Jetson Nano 等边缘设备也有助于保护用户数据的安全。

差分隐私 —差分隐私是一种在不共享用户个人信息的情况下共享数据集的技术。来自维基百科

***an algorithm is differentially private if an observer seeing its output cannot tell if a particular individual’s information was used in the computation***

苹果谷歌等各种公司使用差别隐私技术来保护用户隐私,同时改善用户体验。

露天开采和库

最近,人们对隐私以及如何在不损害用户隐私的情况下使用数据来训练深度学习模型有了很多关注。 Openmined 是一个开源社区,其目标是让每个人都能轻松地进行保护隐私的机器学习。Openmined 开发了 PySyft 库,支持联邦学习差分隐私多方计算,同时支持 Pytorch 和 Tensorflow。OpenMined 还开发了 PyGrid ,这是一个基于 PySyft 构建的 P2P 平台,用于在分布式/云环境中运行 PySyft。

CrypTen —它是一个隐私保护的机器学习框架,来自脸书,构建在 Pytorch 之上。将 CrypTen 与 PySyft 集成的工作正在进行中。

tensor flow Privacytensor flow Privacy是一个开源库,用于训练具有隐私的 ML 模型。

由 Udacity 和脸书提供的免费课程由 Andrew Trask 教授(Trask)——[安全和私人 AI](http://Secure and Private AI)

随着如此多的数据泄露和各种公司收集越来越多的个人信息,对机器学习中的安全和隐私的需求越来越多,尤其是在医疗保健领域。CCPA 现在很活跃,看看它对 2020 年及以后的商业的影响将会很有趣。要了解更多关于自然语言处理和人工智能的信息,你可以在推特上关注我——https://twitter.com/MSuryavansh

[## 用 PyTorch + PySyft 加密深度学习分类

总结:伟大的理论需要伟大的实践。我们在这个博客中展示了如何使用一个私人神经网络来…

blog.openmined.org](https://blog.openmined.org/encrypted-deep-learning-classification-with-pysyft/) [## 一种递归神经网络在树莓 PIs 上的联邦学习

在本教程中,您将学习如何在 Raspberry PI 上设置 PySyft,以及如何训练递归神经…

blog.openmined.org](https://blog.openmined.org/federated-learning-of-a-rnn-on-raspberry-pis/) [## PySyft 上的分裂神经网络

总结:在这个博客中,我们将介绍一种新的分散式学习方法,叫做…

medium.com](https://medium.com/analytics-vidhya/split-neural-networks-on-pysyft-ed2abf6385c0) [## 10 行联合学习

总结:简单的代码示例使学习变得容易。在这里,我们使用 MNIST 培训任务来介绍联合学习…

blog.openmined.org](https://blog.openmined.org/upgrade-to-federated-learning-in-10-lines/) [## 加州消费者隐私法(CCPA):合规所需了解的内容

2018 年 6 月下旬,加利福尼亚州通过了消费者隐私法案 AB 375,这可能会对美国产生更多影响…

www.csoonline.com](https://www.csoonline.com/article/3292578/california-consumer-privacy-act-what-you-need-to-know-to-be-compliant.html) [## 2019 —伯特和变压器年

关于 2019 年 BERT 和 NLP 项目的简短帖子

towardsdatascience.com](/2019-year-of-bert-and-transformer-f200b53d05b9)

CDFs:使用 spacepy 方便地读写数据

原文:https://towardsdatascience.com/cdfs-using-spacepy-to-read-and-write-your-data-conveniently-9490f0bfee4a?source=collection_archive---------46-----------------------

Spacepy python 库是存储和读取复杂文件的有用工具,同时还存储数据的描述。

图片来自美国宇航局 Unsplash

任何组织最重要的方面是拥有一种读取和存储数据的机制。存储数据最常见的方式是通过格式。csv ','。tsv '或'。' txt '。虽然这些文件使用标准的稀疏器或定制的分隔符可以方便地读取信息,但是存储多维数据及其相应的信息(关于单位、数据收集方法等)变得很困难。).

存储数据及其信息的一种新方法是使用。文件的 cdf 格式。CDF 代表通用数据格式,它接受最通用的数据类型,而不管其维度和形状。由 Wolfram Research 创建的 CDF 可以轻松存储和传输信息。CDF 文件被许多组织使用,最著名的是 NASA,用来将多维数据存储到分离的、容易理解的符号中。

在本文中,我将指导您一步一步地创建. cdf 文件,以及如何在实践中使用它。同样的详细文档可以在这里找到:https://spacepy.github.io/_modules/spacepy/pycdf.html

导入库

用于此问题的库

用于创建和读取。cdf 文件是 spacepy 库,嵌入了 pycdf 函数。要顺利运行库,请确保您的处理器具有与库相同的体系结构(32 位/64 位)。

样题

在本文中,我们将考虑一个简单的问题。如果你有一个数组或者。csv 文件,存储不等长的尺寸变得很困难。让我们假设,手头的问题是存储 2 年期间的美国原油价格(日平均)和 2 年期间的美国天然气价格(周平均)。因此,在这种情况下,原油和天然气的数据点数量会有所不同,分别为 730 和 104 个点。为了以易于阅读的格式存储数据,我们将使用。cdf 格式。

第一步是生成一些随机数据。我们假设美国原油价格波动超过 20-100 单位,而天然气价格波动超过 5-30 单位(数值是随机选取的,没有相关性)。

我们将变量 tcrude 和 tng 视为时间步长,前者为每日,后者为每周。原油和天然气价格是随机生成的。

随机数据生成

编写一个 CDF 文件

这个问题最关键的一步是正确地编写一个新的 cdf 文件,它包含我们所拥有的所有必需的属性。相同的示例代码如下:

将数据写入. cdf 文件

在上面的步骤中,完成了以下事情:

  1. 我们产生了。使用 pycdf 中的 write 方法的 cdf 文件,指示用于写入新文件的空引号。
  2. 我们存储数据的方式类似于 pandas 数据帧,但是,在这种情况下,数据没有索引,而是存储在一个单独的变量中
  3. 的’。attrs 的方法用于添加关于数据的信息。在本例中,我们添加了以下内容:作者姓名、数据来源、采样方法。除此之外,我们还为数据添加了属性,例如价格的单位。

阅读。cdf 文件

现在我们已经创建了一个. cdf 文件,我们将使用同一个文件作为要读取的输入。这将带我们读一个文件,并验证我们写的数据。

的。cdf 文件有两个方面,我们存储的数字数据和属性。我们希望知道数据文件包含什么,以及作者是否希望传达任何附加信息。这可以通过导入。cdf 为只读,然后打印所需的数据。

写入的 cdf 文件的输出代码

这段代码的输出如下:

的输出。cdf 文件,包含所有的变量及其属性。

处理来自。cdf 文件

中处理数据很简单。cdf 文件。这可以通过与熊猫数据帧相同的方式来完成。示例绘图如下所示:

用于从绘制数据的代码。cdf 文件

该图与绘制数组或熊猫数据框的图相同。但是,使用的便利性。cdf 文件的一个优点是,你可以轻松地从同一个文件中取出不同维度的变量。此外,某些属性,如单位和作者姓名,也可以直接从文件中读取,无需任何额外的过滤。

示例图来自统一生成的数据,从。cdf 文件。

。cdf 很方便,不是吗?它们是数据帧的完美组合,但是允许不均匀的维度,并且可以使用键轻松地引用它们。唯一的缺点是。cdf 文件的一个缺点是它可能比正常文件大。csv 或。txt 文件,但有一个权衡。这种轻松。cdf 文件提供的很高!

jupyter 的整个笔记本都在这里:https://github . com/yashgokhale/Miscellaneous/blob/master/netcdf _ tutorial . ipynb

CDF 非常有趣。数据分析也是如此。你可以打电话到 ashsgokhale@gmail.comy回复我,以获得任何进一步的澄清或建议,无论是关于这篇文章还是一般的。

参考资料:

[1]https://spacepy.github.io/pycdf.html

[2]https://CDA web . gsfc . NASA . gov/pub/software/CDF/doc/CDF 360/CDF 360 ug . pdf

数据科学家如何获得最被低估的认证

原文:https://towardsdatascience.com/cdmp-exam-d65e1255016b?source=collection_archive---------13-----------------------

数据策略越来越被视为数据科学职业发展的一项关键技能。

2020 年,我们数字世界的规模是 40 万亿千兆字节。这比 2010 年增长了 3000%。多兰·埃里克森在 Unsplash 上的照片

认证数据管理专家(CDMP) 考试授予数据策略领域的优秀,这是我们这个数据丰富的世界急需的学科。

考试包含 100 道选择题需在 90 分钟内作答。通过一级考试需要 60% 的分数。可与在线** 监考一起进行开卷。这意味着你可以用你的笔记和 数据管理知识体系(DMBOK) 作为参考。**

CDMP 在当今的就业市场中非常重要。该证书与高级领导职位相关联。商业和政府领域的潜在客户也认为这表明他们对数据管理有很深的了解。如果你刚刚开始与数据相关的职业旅程,CDMP 是一个开始的好地方

2020 年 10 月初,我以 87/100 的分数完成了数据管理基础考试,获得了 CDMP 的认可。在这篇文章中,我将带你浏览我复习 DMBOK 并成功参加考试的步骤。

在本指南中:

  1. 学习小贴士
  2. 动机
  3. 数据科学家的数据策略

免责声明 :本帖非达马国际赞助——所反映观点仅属我个人。我在亚马逊上添加了一个链接到 DMBOK 的附属链接。通过此链接购买您的阅读材料有助于支持我关于数据科学和数据策略的写作以及 CDMP 研究小组的管理。我的目标是帮助数据科学家、分析师、工程师和其他技术人员获得 CDMP 证书,以推进他们的目标预先感谢您的支持。

我推荐的所有为 CDMP 而学习的事情

📘购买 DMBOK 第二版。 此时。考试是开卷并且 DMBOK 作为数据管理工作的参考是非常有用的。DMBOK 占据了我桌子上的首要位置——我经常参考我的要点和便利贴来回答客户的问题。

现在就买 CDMP 考试。您有无限的时间来安排考试日期,并且支付考试费用可以让您访问包含 200 个问题的题库,模拟真实考试。

🔖高亮显示并粘贴 DMBOK。好吧,这显然是开卷考试。你肯定想用荧光笔和便利贴来表明关键概念。我把所有的便利贴都放在书的一面,方便参考。我还建议你在标签页上写的东西要横着,这样它们就不会伸出书本太远。

❗️ 指示每章的开始。使用宽便利贴或特定颜色的笔记来标记每一章的开始。在测试中,这对于快速找到与特定主题相关的内容是非常宝贵的。

🔨使用章节框架DMBOK 的所有章节都遵循以下结构简介、活动、工具、技术、实施指南、治理、引用/推荐的作品。将学习重点放在概述和技术部分上,相对于实施和组织部分,它们在考试中发挥的作用更大。

💙按顺序阅读,然后按优先级复习DMBOK 的主题以直观的顺序排列,即您在数据管理项目中评估这些主题的顺序。然而,考试中测试的 14 个主题的比例从数据治理等基础领域的 11%到大数据等高级活动的 2%不等。在你第二次阅读 DMBOK 的时候,我推荐按照本文 中的 优先顺序学习。

⭐️ 加入 CDMP 学习小组 。使用这个社区来交换意见、提问和寻找学习伙伴。

质量差的数据会威胁到一个组织的生存

—乔·佩帕德,麻省理工学院斯隆管理学院首席研究科学家

动机

对于技术专业人士来说,参加 CDMP 非常简单而且有益。没有技巧性的问题,考试是开卷的,而且只需要 311 美元。希望这篇文章能让你思考获得 CDMP 奖会如何促进你的职业发展——例如:

  • 您是一名数据科学家、数据工程师或软件开发人员,希望进入领导岗位
  • 你是一名顾问,正在寻找一份证书,向你的客户展示你对数据管理有着深刻的理解
  • 您是一名数据科学专业的学生,希望从端到端的角度了解数据相关主题
  • 你是一个被驱使去学习有用的东西的人!

如果你对 CDMP 的好处有任何疑问,考虑一下从 2010 年到 2020 年的十年间,我们数字世界的数据量增长了 3000%,从 1.2 兆字节增长到 40 兆字节。那就是 40 万亿千兆字节

随着时间的推移,组织产生的数据比以往任何时候都多。这创造了重大机遇和巨大风险。一个强大的数据战略可以支持促进比较优势的实验。薄弱的数据策略会危及组织的生存,将客户、利益相关者和员工置于风险之中。

急需能够将数据作为战略资产进行管理的专业人士。CDMP 是唯一培训和评估端到端数据战略能力的认证

这些学习小贴士,再说一遍:

  1. 购买第二版的 DMBOK。 为开卷考试
  2. 购买 CDMP 考试获得 200 道练习题
  3. 高亮显示便签并放入 DMBOK
  4. 用特殊的便条纸标明每章的开始
  5. 使用章节框架,重点关注简介、活动、工具、技术
  6. 按顺序阅读章节,然后按优先级复习
  7. 加入 CDMP 学习小组

奖金—数据科学家的数据战略

仍然不相信为什么数据策略对机器学习工程师可能很重要?

艾肯金字塔经由 DMBOK

作为一项高级业务职能,数据科学位于艾肯金字塔的顶端。它得到了数据战略基础领域的支持,如果没有这些领域的支持,它就无法取得成功。

提升您的数据战略能力将使您能够在您的组织中倡导更好的数据基础设施。反过来,这将提高您的数据科学计划的质量。获得 CDMP 不仅能为领导角色提供证书,还能让你获得对知识生成过程的深刻洞察。

你获得的每一项技能都会让你成功的几率翻倍

——斯科特·亚当斯如何在几乎所有事情上都失败的情况下仍然大获全胜

****如果你喜欢阅读这篇文章,请关注我的媒体LinkedInTwitter 以获得更多提升你的数据科学技能的想法。加入 CDMP 考试学习小组。购买 DMBOK

提升技能的其他文章

** [## 10 项被低估的 Python 技能

使用这些技巧来改进您的 Python 编码,以获得更好的 EDA、目标分析和功能,从而提升您的数据科学水平

towardsdatascience.com](/10-underrated-python-skills-dfdff5741fdf) [## 如何不费吹灰之力通过 AWS 云从业者认证

预测:多云,第一次尝试有 100%的机会通过。

nicolejaneway.medium.com](https://nicolejaneway.medium.com/how-to-ace-the-aws-cloud-practitioner-certification-with-minimal-effort-39f10f43146) [## 数据仓库综合指南

了解数据仓库作为分析就绪数据集的主存储库的角色。

towardsdatascience.com](/data-warehouse-68ec63eecf78) [## 你的机器学习模型有可能失败吗?

规划过程中要避免的 5 个失误

towardsdatascience.com](/data-science-planning-c0649c52f867) [## 如何让您的数据科学项目经得起未来考验

ML 模型选择和部署的 5 个关键要素

towardsdatascience.com](/model-selection-and-deployment-cf754459f7ca) [## 5 篇必读的数据科学论文(以及如何使用它们)

让您在数据科学领域保持领先的基本理念。

towardsdatascience.com](/must-read-data-science-papers-487cce9a2020)**

名人脸一代与深卷积甘斯

原文:https://towardsdatascience.com/celebrity-face-generation-with-deep-convolutional-gans-40b96147a1c9?source=collection_archive---------23-----------------------

深度学习

用 DCGANs 生成新的人脸图像

约翰·杰克逊Unsplash 上拍照

在本文中,我将带您完成一个有趣的项目,在这个项目中,您将实现一个用于人脸生成的 DCGAN。

我们将利用大规模名人面孔属性(celebA)数据集来训练我们的对抗网络。

如果您不熟悉 GANs 及其工作方式,请阅读这篇关于走向数据科学的文章。

[## 生成对抗网络

用解读甘博弈

towardsdatascience.com](/generative-adversarial-networks-6a17673db367)

大规模名人面孔属性(celebA)数据集

名人脸属性数据集(CelebA) 是一个大规模的人脸属性数据集,拥有超过 200K 张名人图片,每张图片都有 40 个属性标注。

数据可以从这里下载。

我们将使用深度卷积 GANs。如果你想了解 DCGANs,可以看看这篇文章。

[## 深度卷积生成对抗网络

生成对抗网络最有趣的部分之一是生成网络的设计。的…

towardsdatascience.com](/dcgans-deep-convolutional-generative-adversarial-networks-c7f392c2c8f8)

预处理和数据加载

我们不需要注释,所以我们将不得不裁剪图像。这些是彩色图像。因此,深度为 3(RGB-3 个颜色通道)。

我们可以调整和裁剪图像到 32x32 的大小。这可以在以后转换成张量。

注意,我们在这里使用图像文件夹包装函数。

作者代码。

可视化我们的训练数据

我们现在将生成一批数据,并将其可视化。请注意,np.transpose 函数按照指定的顺序转换图像尺寸。例如,在调用以下函数时,形状 3x32x32 的 RGB 图像将转换为 32x32x3:

np.transpose(img,(1,2,0))

我们的批次大小是 128,所以在这种情况下,我们只绘制 20 个图像,而不是绘制一个批次的所有 128 个图像。

作者代码。

一批训练图像。图片由作者提供。

缩放图像

缩放图像是很重要的,因为 Tanh 函数的值在-1 到 1 的范围内,所以我们需要将我们的训练图像重新缩放到-1 到 1 的范围。(目前,它们在 0-1 的范围内。)

作者代码。

辅助函数—卷积和转置卷积

为了简化我们的代码,我们将定义帮助函数来定义我们的鉴别器和生成器网络。

这些助手功能的原因是什么?回答——干!😅

卷积辅助函数

注意:要阅读 CNN,请查看下面的斯坦福笔记。

[## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](https://cs231n.github.io/)

作者代码。

转置卷积辅助函数

注意:如果你想了解转置卷积,可以看看下面的文章。

[## 转置卷积去神秘化

转置卷积对于图像分割、超分辨率等应用来说是一个革命性的概念

towardsdatascience.com](/transposed-convolution-demystified-84ca81b4baba)

作者代码。

鉴别器架构

我们现在将定义我们的鉴别器网络。正如我们所知,鉴别器负责将图像分类为真或假。因此这是一个典型的分类器网络。

作者代码。

发电机架构

生成器网络负责生成假图像,这些假图像可以欺骗鉴别器网络将其归类为真实图像。随着时间的推移,生成器在欺骗鉴别器方面变得相当不错。

作者代码。

参数初始化

我们将通过从正态分布中抽取随机值来初始化网络的权重和偏差。这导致更好的结果。我们为其定义了一个函数,将一个层作为输入。

对于权重,我使用 0 均值和 0.02 标准差。

对于偏差,我使用 0。

现在这应该被替换,所以函数后面的 _(下划线)也是如此。

作者代码。

损失函数和优化器

我们将使用学习率为 0.002 的 Adam 优化器。这与 DCGANs 的原始研究论文一致。你可以在下面查看一下。

[## 深度卷积生成对抗网络的无监督表示学习

近年来,卷积网络的监督学习(CNN)在计算机视觉领域得到了广泛应用…

arxiv.org](https://arxiv.org/abs/1511.06434)

作者代码。

我们使用 BCEwithLogitsLoss(),它结合了一个 sigmoid 激活函数(我们希望鉴别器输出一个 0–1 的值来指示一个图像是真的还是假的)和二进制交叉熵损失。

Binar 交叉熵损失方程。图片由作者提供。

培训阶段

我们将定义一个函数来训练我们的模型。这些参数将是鉴别器、发生器、纪元编号。

作者代码。

策划损失

作者代码。

图片由作者提供。

样本生成

现在让我们生成几个样本。重要的是,我们要将这些值重新调整回像素范围(0–255)。

作者代码。

最后,下面是我们生成的人脸。👀

生成的图像。图片由作者提供。

嗯,对于一个小型网络来说,这是相当不错的!

外卖食品

  1. 人脸包含多个特征,其中一些特征非常复杂,例如雀斑和胡须。为了生成合适的图像,我们可能需要高分辨率的图像。
  2. 为训练提供了高分辨率图像,我们可能需要建立一个更好、更深的模型,以获得更高的精确度。
  3. 基于输入图像,我们可以进一步增加模型的深度和层数。
  4. 提高分辨率肯定有助于我们改进模型并精确捕捉更多特征。
  5. 生成的样本可以通过调整参数,如学习率、批量大小和更多次数的训练来进一步改进。发电机的损耗是波动的,而不是减少的。
  6. CelebA 数据主要包含不同名人在不同角度和光照条件下的图像。

结论

我们已经看到了如何在 celebA 数据集上使用 DCGAN 实现生成逼真的人脸。通过调整超参数,可以进一步改善生成的图像。你也可以选择比这里更深的层次。然而,这样做将导致参数数量的增加,这又将花费大量时间来训练。现在打开你的 Jupyter 笔记本,执行同样的操作。在下一篇文章中,我将带您浏览使用 SVHN 数据集生成街景房屋号码的过程。下一场见。干杯!

谢谢你。

细胞自动机和深度学习

原文:https://towardsdatascience.com/cellular-automaton-and-deep-learning-2bf7c57139b3?source=collection_archive---------21-----------------------

智能系统

细胞自动机(CA)是基于网格的计算系统,它模拟复杂性的增长。简而言之,细胞自动机是单向和混乱的进化模式。进化的规则是非常基本和简单的,然而,进化产生了高度复杂的结构和行为。CA 被认为是物理混沌系统中复杂性增长的模型,也是对称性如何从简单的定律中产生的模型。我喜欢将 CA 与统计力学进行比较:对于气体来说,温度的概念在分子/原子水平上是不存在的。温度不是单个分子的属性。然而,当你把数百万/数十亿个分子放进一个盒子里时,分子之间的动力学和运动学会产生温度。我们称温度为系综的“突发”属性。CA 的行为方式相似——它们遵循非常简单的局部规则,CA 的集合产生“涌现”的对称性和复杂的行为。

在这篇博客中,我们将关注 2d CA 最著名的例子,即“生活游戏”(GOL)。这是康威在 20 世纪 70 年代发现的。一个细胞的进化依赖于它的邻居。细胞有两种状态——死亡(黑色)或存活(白色)。自动机遵循这些简单的规则,

  1. 一个邻居都死了的牢房因为孤独而死。
  2. 一个有 3 个以上邻居的牢房死于饥饿
  3. 由于复制,具有 3 个或更多活邻居的死细胞变得有活力
  4. 具有 2 或 3 个活邻居的细胞保持相同的状态— 停滞

我们在下图中代表了所有这些状态,

GOL 规则(n =邻居)

我们让 CA 的 2d 网格随时间演化,并获得有趣的结构。初始起点通常是随机的。某些固定的起点产生了特定的结构。人们试图对可能出现的结构进行动物学分类。让我们看一些随机初始状态的进化例子,

GOL 进化

有时(基于初始条件)会出现如下非常有趣的结构,

一个有趣的模式出现了:滑翔机枪

维基百科上关于 CA 的文章包含了许多这些复杂结构的例子。注意上图有一个与之相关的对称性,而规则是局部的,没有对称性。这是“突现”对称的一个例子。

说够了。深度学习和这有什么关系?

实施

规则是局部的(它们只看邻居)这一事实意味着 CA 与卷积运算非常相似。受此链接的启发提出了以下架构作为 CA 模型,

我们从一个 50x50 的图像(这是我们的世界网格)开始,执行翻转填充,使其成为 52x52。翻转填充意味着我们识别左右和上下边缘,以使整个网格连续。52×52 的图像被送入 100 个 3×3 的过滤器。该过滤器的数量随着您想要建模的 CA 的种类而变化。至少可以用 5 个滤波器来模拟 GOL。最后,我们实施 1x1 卷积,为下一个时间步获得 50x50 的图像。我们想要强调的是,这个网络类似于 CA 的单时间步进化。仅用一层卷积,不可能模拟任意长时间步长的演化。为了建模,CA 需要不断重用网络来生成 n 步进化。现在,让我们看看 TensorFlow 中的实现,

TF 2 中的两个简单实现

我们训练 CA 在随机产生的初始状态上进行一步进化。训练和评估模型的完整代码在这里给出。

现在让我们看看 CA 在现实世界中的各种应用。

应用

  1. 纠错。
    CA 可以从很少的例子中快速学习。CA 可以在图像上被训练,以作为自校正网格来去除杂质。图像误差校正的一些例子是,

  1. 单向函数:
    CA 的传播不是双射函数,因此给定一个时间步长的状态,实际上不可能找到初始配置。可能的先前状态的数量呈指数增长。我尝试了深度和广度 conv 网来映射一个反向函数,但找不到初始配置。这表明寻找逆是一项重要的任务,也许根本不可能。

  2. ARC(抽象推理挑战赛)
    Keras 的创造者弗朗索瓦·乔莱(Franç ois Chollet)最近出了一篇论文,关于如何衡量智力。他提出了大量的任务,包括不同种类的抽象解决技术。每个任务只有很少的(通常 2-3 个)训练样本和一个测试样本。目标是实际学习解决任务所需的逻辑,而不是学习某种转换。由于可用的训练样本非常少,基于神经网络的方法容易过度拟合。SOTA 方法使用决策树,并且有大约 50/400 的成功率(非常糟糕)。让我们看一些任务的例子,

寻找反射光线

将红色贴在蓝色上

正如你所看到的,任务是非常不同的,需要全局物理,拓扑等知识。设计一个可以概括所有可能情况的单一神经网络几乎是一项不可能的任务。基于 CA 的方法是针对以下任务的建议解决方案。我的一些初步实验给出了 20/400 的成功率。如果你想让我用 CA 来解决 ARC 任务,请在下面的评论中告诉我。

参考文献

  1. 代码: Github
  2. 生命的游戏:https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
  3. CA as Conv 网:https://arxiv.org/abs/1809.02942
  4. 智力测量:https://arxiv.org/abs/1911.01547

药物开发中的细胞图像分类:逐步指南

原文:https://towardsdatascience.com/cellular-image-classification-with-intelec-ai-a-step-by-step-guide-7ebbc804371f?source=collection_archive---------43-----------------------

荧光显微镜:可视化细胞及其组成部分。图片由作者使用 rxrx 库制作

你有没有想过,在没有任何深度学习知识的情况下,你是否可以对图像进行分类?如今,已经有了很棒的免费库,比如 Python 中的 Kerasfastai ,或者已经成功抽象出深度学习的 Intelec AI 软件,任何人都可以开始他们的深度学习之旅,即使你只有一年的编码经验。

这篇文章将向你展示我如何参加一个复杂的关于细胞图像分类的竞赛,只使用了熊猫和智能。

概述和背景

药物和医疗方法通常需要很多年才能开发出来,因此价格昂贵,公众无法获得。递归制药公司。相信人工智能有能力减少生产新药的时间和成本。

用人工智能帮助制药公司的一个具体方法是能够对接受特定遗传扰动的不同细胞图像进行分类(称为 siRNAs )。如果你能在给定图像的情况下,以很高的准确度猜出药物,这意味着药物以某种方式与细胞相互作用。

这正是我们 kaggle 挑战的问题:递归细胞图像分类。给定一些图像,我们应该能够预测哪个 siRNA 应用于它。

理解数据:荧光显微镜

左图:6 个通道上的荧光显微镜。右图:变形图像。图片由作者提供。

荧光显微镜的原理是使用不同的蛋白质,这些蛋白质只在特定的光谱颜色范围内发出荧光,并且倾向于附着在细胞的某些特定部分。

上面左边部分的图像代表了从同一台相机在同一地点通过六个不同的光谱颜色范围拍摄的照片。由于荧光显微镜的原理,这是可能的。每个频率都表示为黑白图像。第一个目标是能够将它们表示成一个单一的 RGB 图像,如右边部分所示。

挑战简介

[## 递归细胞图像分类

细胞信号:从细胞图像的实验噪音中分离生物信号

www.kaggle.com](https://www.kaggle.com/c/recursion-cellular-image-classification/overview)

Kaggle 发布了一个艰难的分类挑战:一个超过 750,000 张图像(代表几乎 50 GB)到超过 1100 个可能类别的分类任务。图像数据集以如下方式排列:有 51 个批次。每批有四个平板,每个平板有 308 个填充的孔。每口井在两个地点进行监控,并在六个频率上拍照。太多了!我们将在下一节看到如何减少数据集的大小,保留最相关的组件。你可以在这里下载的资料。

这种排列产生以下树形数据结构:

我们的数据是如何排列的?作者图片

理解数据:它看起来像什么?

如前所述,每个地点都是在六个频率上拍摄的(在上图中用 w1,…,w6 表示)。如果只有 3 个频率就好了,就像我们在处理 RGB(红绿蓝)图像一样,因为大多数最先进的神经网络将 RGB 图像(即正好有三个通道的图像)作为输入。有很多方法可以将一些数据从高维降低到低维。我们将探索其中的两个。

首先,我们将使用一个小而方便的库来处理由 rxrx.ai 创建的特定数据。这个库将帮助我们以更有意义的方式可视化我们的数据。您应该在您希望运行所有脚本来准备数据的同一个文件夹中克隆他们的 git repo。从终端,您可以执行:

git 克隆https://github.com/recursionpharma/rxrx1-utils

然后,打开 jupyter 笔记本或 python 脚本,尝试以下操作:

这里有一个笔记本,上面有所有的代码。

为了确保您正确理解数据的树结构,请尝试更改 load_site_as_rgb 函数的参数,并查看是否有 rgb 单元格图像出现!

预期产出。作者图片

准备数据

因为我们想使用 Intelec ai 软件,我们需要坚持一些关于数据结构和标签文件的格式。我们将在后面讨论如何安装它。现在,我们已经创建了标签文件!

如果你想自己尝试,你没有义务尝试以下两种方法!一个就够了!

现在我们终于可以给我们的两个函数下一些定义了!

从左到右,作者使用 PCAColormap 技术生成的两幅图像如下所示。

主成分分析

主成分分析(PCA) 是对一些数据进行降维的常用技术。需要一个额外的库:scikit-learn。相应的代码如下:

尽管 PCA 通常在将数据嵌入到较低维度的流形中时显示出优异的结果,但这可能再次不适用于该问题,因为 PCA 通常在发现特征(此处为通道)之间的线性相关性时是好的,而对于那些细胞图像可能不是这样。

彩色地图

我们可以使用的最后一个想法是将每个通道的色图应用于 RGB 值。例如,可以想象第一通道将输出图像着色为红色值,第二通道着色为绿色值,第三通道着色为蓝色值,最后三个通道着色为某种组合,如洋红色等。但是要知道一个好的色彩映射表策略,我们应该对数据有深刻的理解,这不是我个人的情况。好在 rxrx 库有这个漂亮的方法叫 load_site_as_rgb!记得吗?它所做的是,我们需要指定它一个细胞图像,它应用一个自定义的色彩映射表来输出一个 3 通道的图像,正如我们所希望的那样!

有人会注意到我撒了一点谎,我们实际上使用了 convert_tensor_to_rgb 方法,因为另一个调用了他们的在线 API,比我们自己在本地打开图像要慢得多。

你可能会喜欢尝试自己的想法。为了保持代码对其他方法的模块化,我建议使用最后一种方法,它将允许我们根据需要选择任何函数:

现在我们需要主循环:遍历所有数据并将图像转换成 RGB 图像,如上所述。

关于上述代码的一些说明:

  • 第一行是如果你想尝试一个特定的建议方法(或者尝试你自己的想法),你可能会改变的内容。)
  • 你会注意到,在第 9 行,我们将站点固定为“1 ”,并且从未使用过第二个站点。原因是我们希望使用更轻的数据集,这只是一个演示,我们并不是要赢得 kaggle 竞赛(但如果你有动力,你可以使用这两个网站!)
  • 由于并非所有组合都定义了完整的数据,可能会有一些图像在站点 1 中不存在,因此我们使用 try-except 块来避免程序崩溃。

就是这样,伙计们!我保证,我们完成了旅途中最艰难的一步!现在我们有了格式良好的数据,让我们使用 intelec ai

如果你愿意,你可以在这里查看完整的笔记本。

智能安装

点击这里可以安装 Intelec ai。

[## 支持 GPU 的自动化机器学习平台免费下载

编辑描述

www.intelec.ai](https://www.intelec.ai/install)

你需要码头工人。如果你在安装上有问题,我邀请你去看看他们的网站

[## 增强开发者的应用开发能力| Docker

世界领先的服务,用于与您的团队和 Docker 社区查找和共享容器图像。对于…

www.docker.com](https://www.docker.com/)

运行它的第一个模型

我们终于到了!是的,我知道你也不耐烦在没有任何代码的情况下训练你的深度学习模型,别担心,我会告诉你怎么做。

上传您的数据

首先,您需要上传您选择的数据,然后可以是 PCA 或 colormap 或您选择的任何其他版本。

  1. 压缩你的文件夹。
  2. 进入英特尔页面的“文件浏览器”标签。
  3. 上传吧。
  4. 右键点击它解压。

选择您的型号

Intelec 的免费版本已经提供了一些有趣的神经网络。转到“培训”选项卡。分类任务有一个简单和一个较重的模型。我的建议是直接接受更重的挑战,因为这个挑战是一项复杂的任务。无论您选择简单型号还是较重型号,步骤都是完全相同的:

  1. 为您的分类器命名,例如深色细胞分类器
  2. 选择名为“train”的文件夹,其中应包含另一个名为“images”的文件夹和您的“labels.csv”文件
  3. 您可以选择添加一个测试或验证文件夹,我个人并没有为这个特定的任务这样做。否则,Intelec 将把培训的一部分作为默认验证,这完全没问题。
  4. 您还可以设置收缩因子:分辨率越高,分辨率越小,即模型训练越快,但精度越低。我的建议是从一个高值开始,然后慢慢降低它,看看在一个模型上花更多时间是否值得。也许从 4 开始,因为图像分辨率已经很低了(512x512x3)。在我的结果中,我实际上使用了 1 的收缩因子,因为我为这个任务租了一个服务器,但是你肯定不需要这样做。

这就对了。你可以保存这个模型。应该会打开另一个页面,建议您开始训练程序。这可能需要一段时间,所以请确保您的 GPU 设置正确。如果你需要建议,你可以阅读这个有趣的话题。

模型准备部署。作者图片

如果您看到红色粗体的“部署”按钮,这意味着您成功地训练了您的分类器,祝贺您!当然,你可能很想知道你的训练有多好。向下滚动一点,你应该会看到类似下图的东西。如果您有兴趣,可点击“培训总结”按钮了解更多详情。

培训和验证损失。作者图片

为了获得有意义的度量,总是在验证数据集上测量您的损失是非常重要的,以确保您没有过度拟合。您可能已经自己指定了一个测试或验证集,但是如果您没有,不要担心 intelec 会为您做的。

太棒了,你的模特真的学到了一些东西!我们可以看到损失减少了多少!

如果您想更进一步,您可以部署模型来预测一个或几个测试图像。你也可以给它一个任务来预测整个文件夹,如果你想参加 kaggle 比赛,这真的很有用,因为几乎要做 20,000 次预测。一个很好的视频解释了如何做所有这些事情。如果你很好奇,看看吧!

结论

多好的旅程啊!我们学到了很多关于医疗行业和制药公司如何着手开发新产品的知识,更重要的是,深度学习如何能够拯救我们。事实上,我们没有看到我们的神经网络架构的实现细节,但这就是 intelec AI 软件的目的:让每个人都可以进行深度学习。我们只需要对 pandas 库有一些了解,对 python 有一点经验,然后我们就能够解决一个困难的问题,比如超过一千个类的分类任务。

使用 fastai v2 和多标签文本分类器审查有毒评论

原文:https://towardsdatascience.com/censoring-toxic-comments-using-fastai-v2-with-a-multi-label-text-classifier-12688157d0e6?source=collection_archive---------17-----------------------

让互联网成为一个安全的空间,一次一个字

近来,互联网已经成为一种基本的必需品,我们世界中的许多物理事物正处于数字化的边缘。世界上已经有很大一部分人使用互联网进行日常事务、娱乐、学术研究等。保持互联网成为一个安全的空间,让每个人都能来这里互动,这是一个重大的责任,因为有各种各样的人在互联网上张贴东西,而没有意识到其后果。

这篇文章介绍了一个文本分类器的制作过程,它接受一段文本(短语、句子、任意长度的段落),并判断该文本是否属于一系列不同类型的恶意文章。本帖涵盖的主题有

您可以单击上述任何一个要点,导航到相应的部分。

免责声明:此处使用的数据集包含一些可能被视为亵渎、粗俗或冒犯的文本。

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

介绍

自然语言处理是一个研究理解计算机和人类语言之间交互的领域。由于许多东西正在走向在线或数字化,而且这些服务已经普及到全世界,这些数据产生的规模是巨大的。在这个时代,地球上的每个人都在发表他们的观点、想法、事实、文章、诗歌等等。在网上,监控和调节这些文本是一项不人道的任务(即使我们认为人类是一个社区,而不是一个个体)。

多亏了高容量 GPU 和 TPU 的出现,以及人工智能在文本应用方面的最新进展,我们已经提出了许多解决这个问题的技术。递归神经网络是解决这些问题的关键要素。fastai 是一个深度学习库,建立在 PyTorch 的基础上,由杰瑞米·霍华德和西尔万·古格开发,使得为这些任务构建应用程序非常用户友好和简单。

让我们开始学习如何使用 fastai 进行文本分类。

从 Kaggle 获取数据

我们将用于演示多标签文本分类过程的数据来自 Kaggle 上的有毒评论分类挑战。

我们的模型将负责检测不同类型的毒性,如威胁、淫秽、侮辱和基于身份的仇恨。该数据集包括来自维基百科谈话页面编辑的评论。事不宜迟,让我们开始下载这个数据集。

您可以手动从 Kaggle 下载数据集,也可以使用上面的命令使用 kaggle 提供的 API。

要使用 API,您必须创建一个 Kaggle 帐户并生成 API 密匙,该密匙允许您使用 shell 命令从 kaggle 下载数据集,并从工作笔记本或 shell 提交预测。一旦你创建了一个 Kaggle 帐户并创建了 API 密匙,你将得到一个 json 文件,其中包含你的用户名和密匙。根据您的唯一凭证,这些需要在上面的代码中输入。

MRINALI GUPTA 撰写的这篇文章很好地解释了如何开始使用 Kaggle API 下载数据集。

数据探索

让我们阅读训练集和测试集,并掌握其中包含的数据。

图片由 Vinayak 提供

数据帧中有几个字段。

  • id :与曾经的注释文本相关联的标识符。由于这是从维基百科的对话页面上获取的,它可能是某个发表评论的人的身份,或者是他们发布的文本的 HTML DOM id。
  • comment_text :用户发布的评论的文本。
  • 有毒、严重 _ 有毒、淫秽、威胁、侮辱、身份 _ 仇恨:这些列表示 comment_text 中同名元素的存在。如果它们不存在,就用 0 表示,否则就用 1 表示。

这些元素在某种意义上是独立的,它们并不相互排斥,例如,一个评论可以是有毒的和侮辱性的,或者如果一个评论是有毒的,它就不一定是淫秽的,等等。

图片由 Vinayak 提供

总的来说,有不良文字的评论要少得多;考虑到我们有超过 10 万条评论,有不到几万个令人反感的类别(除了有毒的那几个)。知道这一点很好,但如果这类文本更少就更好了。

此外,文本被人类标注了这些标签。这个注释的任务是一个巨大的任务,伴随着这些注释,会有很多人为的解释和偏见。这是需要记住的事情,我们将在结束时讨论这个问题。

多标签文本分类方法

文本或句子是单个单元的序列——单词、子单词或字符(取决于你说的语言)。任何机器学习算法都无法处理除数字之外的任何东西。所以,我们首先要用数字来表示数据。

在任何与文本相关的问题中,首先我们创建一个词汇库,这个词汇库基本上是我们要考虑的全部词汇;任何其他单词都将被加上一个名为 unknown 的特殊标签,并放入该桶中。这个过程叫做 标记化。

接下来,我们将每个单词映射到一个数字标记,并创建一个单词字典来存储这个映射。所以现在每一篇散文/评论/文字都转换成一串数字。这个过程叫做 数值化。

最肯定的是,评论的长度不会一样长,因为人们并不局限于用固定的字数来评论。但是,当创建批量文本以提供给我们的网络时,我们需要它们都具有相同的长度。因此,我们用一个特殊的符号来填充句子,或者如果句子太长而不能压缩到固定长度,我们就截断句子。这个过程叫做 填充。

在做上述所有事情的同时,还有一些其他的操作,比如将所有的文本小写,将标点符号作为单独的符号处理,理解大写而不管小写等等。这就是 fastai 的优秀员工让所有这些事情变得超级简单的地方。

  • xxpad :对于填充,这是使用的标准令牌。
  • xxunk :当遇到一个 oov(词汇外)单词时,这个令牌用来替换那个单词。
  • xxbos :在每个句子的开头,这是一个标记,表示一个序列的开始/起点。
  • xxmaj :如果一个单词是大写的或者标题是大小写的,这个符号会被加前缀以获取信息。
  • xxrep :如果一个单词重复,那么在标记化的表示中,我们将让这个单词后面跟着 xxrep 标记,后面跟着重复的次数。

有更多的语义信息用更多的这种标记来处理,但所有这些都确保捕捉到关于文本及其背后含义的宝贵信息。

一旦预处理完成,我们就可以建立一个 LSTM 模型来将文本分类到各自的标签中。单词被表示为 n 维向量,俗称编码/嵌入。PyTorch 中有一个用于嵌入的构造,它有助于在给定单词的数字标记的情况下查找单词的矢量表示,然后是其他 RNN 层和全连接层,以构建一个架构,该架构可以将序列作为输入,并返回一组概率作为输出。这些向量嵌入可以被随机初始化,或者从通常可用的 GLoVE 或 Word2Vec 嵌入中借用,这些嵌入已经在大的文本语料库上被训练,使得它们在一般意义上对特定语言中的上下文具有良好的语义单词理解。

然而,如果我们在构建分类器之前执行它,有一个技巧可以改善结果。这就是我们接下来要看的。

fastai v2 中的语言模型

fastai 提出了在构建任何分类器或应用程序之前微调语言模型的这种经过试验和测试的方法。

简而言之,他们说的是,如果你有一组在大型语料库中训练过的单词嵌入,他们对从语料库中学到的单词有一个非常通用的理解。然而,当我们谈论仇恨言论和令人讨厌的评论以及有毒的东西的分类时,有一种与这些句子相关的特定的负面氛围,并且语义上下文还没有出现在我们的嵌入中。此外,许多特定于我们的应用程序的单词/术语(可能是医学或法律或有毒语言)可能不会经常在我们从中获得单词嵌入的庞大语料库中遇到。在我们的分类器将要使用的嵌入中,这些应该被包含并很好地表示出来。

因此,在建立分类器之前,我们将微调一个已经在维基百科文本语料库上训练过的语言模型。我们将把训练和测试数据集的注释绑定在一起,并将它们提供给语言模型。这是因为我们不是在做分类,而是在给定当前序列的情况下简单地猜测序列的下一个单词;这叫做自我监督任务。通过这种方式学习嵌入,我们将能够构建一个更好的分类器,因为它知道特定于我们语料库的概念。

让我们看看如何在 fastai v2 中实例化和微调语言模型。

图片由 Vinayak 提供

我们附加训练和测试数据,并丢弃标签,因为在这个自我监督的学习任务中我们不需要它们。接下来,我们必须创建一个数据加载器来标记这些文本,在将它输入语言模型之前进行所有的数值化、填充和预处理。

1

这在 fastai 中非常简单,您只需将所有参数包装在一个工厂方法中,并用它实例化 TextDataLoaders 类。否则,这至少需要一百行代码加上适当的注释和其他东西,但多亏了 fastai,它又短又甜。我们可以看看一批中的几个条目。

图片由 Vinayak 提供

正如我们所看到的,输出只是将给定的序列偏移一个字,这与我们想要的一致,即给定一个序列,预测序列的下一个字。一旦我们有了这个数据加载器,我们就可以创建一个语言模型学习器,它可以根据我们的语料库而不是以前的文本语料库来调整编码。

图片由 Vinayak 提供

有了语言模型学习器之后,我们可以让学习器适应几个时期,并使用 save_encoder 方法保存编码。我们可以看到,在给定当前单词序列的情况下,语言模型平均可以以 38%的准确率预测下一个单词会是什么,这对这个数据集来说是相当不错的。

一旦我们做好了准备,现在我们可以进入下一步,创建一个分类器来识别 comment_text 的不同标签的概率。

fastai v2 中的分类模型

在我们开始创建分类模型之前,我们需要进行一些预处理,以便构建一个合适的数据加载器。在写这篇文章的时候,文本的数据块 API 有一个问题,它避免了正确地推断所有的因变量,因此我们不得不求助于这个方法。

基本上,我们将不得不在我们的数据帧中创建另一列,该列使用固定的分隔符来指示单个标签的存在或不存在。所以,如果一个评论是淫秽和有毒的,我们的新栏目会显示淫秽;分隔符为“;”时有毒。同样,对于没有任何不良文本的行,为了给出一个标签,我们现在称它们为 sober(没有任何标签,fastai 不会创建 dataloader)。

图片由 Vinayak 提供

因此,我们可以看到添加了包含“;”的列标签带分隔符的标签字段,所有的标签都在这里表示,而不是以一次性编码的格式提供。

现在,我们使用 datablocks API 创建数据加载器,分别为 x 使用“comment_text”字段,为 y 使用“Labels”字段。如果我们在 get_y 字段中作为一个列表提到了 6 列的名称,那么它总是只选取两个字段;由于数据加载器的这种不正确的推断,我们必须创建一个单独的标签列来获取因变量,即 y 的值。接下来,一旦我们有了数据加载器,我们就可以使用 LSTM 架构构建一个分类器模型。一旦实例化了语言模型,我们还需要将它的编码/嵌入加载到分类器中。

图片由 Vinayak 提供

然后我们可以开始训练分类器。最初,除了最终的 FC 层,我们将保持网络的大部分处于冻结状态。这意味着反向传播权重更新将仅发生在倒数第二层。我们将逐渐解冻之前的层,直到最终我们解冻整个网络。我们这样做是因为如果我们从一个未冻结的网络开始,模型将很难快速收敛到最优解。

可以看出,在训练结束时,准确率已经达到了相当稳固的 98%。由于训练和有效损失都在减少,我们可以理想地训练更多的纪元并继续下去,但出于时间的考虑,我们将认为这是一个足够好的分数,并从推论开始。

做出推论

现在我们有了一个训练好的模型,并且我们已经将它存储为 pkl,我们可以使用它对以前看不到的数据(即测试数据)进行预测。

我们将首先加载我们刚刚在 GPU 上创建和训练的模型。(由于我们有几十万条评论文本,CPU 推断会耗费大量时间)。接下来,我们将对 test_df 进行标记化,然后通过用于训练和验证数据的相同转换来传递它,以创建用于推断的测试注释的数据加载器。

接下来,我们将使用 get_preds 方法进行推理,并记住将 reorder 方法传递给 False,否则会发生文本的随机重排,这将导致最终预测的顺序不正确。

最后,我们将以 sample_submissions.csv 样式格式化这些预测。因此,在预测之后,我们得到一组 7 个值,每个类一个,并且不需要“清醒”类的概率,因为它是我们作为占位符引入的。我们把它去掉,把所有的 id 按正确的顺序排列。这是最终提交的样子。

图片由 Vinayak 提供

最后,我们可以使用 kaggle API 本身提交这些预测。无需手动转到 kaggle 并提交 csv 文件。这可以简单地通过这个 shell 命令来完成。

# Submit the predictions to kaggle!kaggle competitions submit -c jigsaw-toxic-comment-classification-challenge -f submissions_toxic.csv -m "First submission for toxic comments classification"

您可以根据自己的方便更改提交文件的名称和消息。我得到的最终提交分数如下所示

图片由 Vinayak 提供

排行榜上的最高分大约是 0.9885,所以我们的分数在这样少的代码行和很少甚至没有预处理的情况下还是不错的。我们可以删除停用词,清理 html 标签,处理标点符号,甚至调整语言模型,或者使用 GloVE 或 Word2Vec 嵌入,并采用像 Transformer 这样的复杂模型,而不是简单的 LSTM。许多人以不同的方式处理这个问题,并使用其中的一些技巧来获得如此高的分数。然而,通过使用已经实现的 fastai 库,我们可以在第一次尝试中获得足够好的分数。

最后,值得一提的是,这个由人类标注的数据集可能被贴错了标签,或者人与人之间可能存在主观差异,这也是公平的,因为这是一项非常手工和单调的工作。我们可以通过建立一个模型来帮助这一过程,然后用它来注释,并让人类监督注释,以使过程更简单,或者将这项工作众包给多个志愿者,以在少量时间内获得大量标记数据。无论如何,NLP 在解决现实世界中的许多语言问题方面已经变得非常有用,希望在阅读完这篇文章后,你有信心用 fastai 开始你的文本世界之旅!

参考

  1. 来自 Kaggle 的毒性评论数据集
  2. 如何使用 Kaggle API 下载数据
  3. Github 回购与这个帖子的所有代码
  4. T ext 分类笔记本使用 fastai

使用 NetworkX 的普查地理

原文:https://towardsdatascience.com/census-geography-with-networkx-fe2aa6c8ab16?source=collection_archive---------65-----------------------

公共数据

使用 Python 中的图表表示人口普查地图的教程

概观

本教程的目标是创建一个表示纽约州各县之间地理关系的图形数据结构。具体来说,我们希望确定两个县何时相邻。

在我们开始写代码之前,让我们想一想我们想要如何构建这些关于节点和边的关系。

  • 节点— 每个节点将代表纽约州的一个县。它们将通过它们的 FIPS(联邦信息处理标准)编号来识别。此外,每个节点将存储该县的自然语言名称以及公共交通的使用率。
  • 边— 如果两个节点在地图上地理上相邻,它们将共享一条边

设置

要完成本教程,您需要以下内容

  • 一个县邻接文件
  • 类似下面截图的人口普查数据框架。如果您对如何下载或格式化有任何疑问,请参考此处的。

在本教程中,我们将使用纽约州所有县的数据框架

节点

首先,我们需要导入一些包并实例化我们的 graph 对象。我们还假设我们的人口普查数据框架将被称为 df。

import pandas as pd
import networkx as nxdf=dfG = nx.Graph()

NetworkX 可以在每个节点以字典的形式存储数据。因此,为了存储我们的县名和公交使用数据,我们需要创建一个适当形式的节点列表。这将是一个 2 元组的列表,其中第一个元素是节点的名称,第二个元素是数据的字典。因此,单个元素将如下所示:

('36081', 
{'percent_public_transpo': 52.27, 'county_name': 'Queens County'})

要创建这个列表,让我们创建一个函数,该函数接收一个县的数据帧,并遍历该数据帧以返回所需的列表

def process_counties(df):
    final_list = []
    for index, row in df.iterrows():
        node = (str(index), 
          {'percent_public_transpo': row['percent_public_transpo'],
           'county_name': row['county_name']})
        final_list.append(node)
    return final_list

现在将这些节点添加到我们的图表中。

county_FIPS = process_counties(df)
G.add_nodes_from(county_FIPS)

优势

要添加邻接边,我们需要读入在设置部分链接的 CSV 邻接文件

adj_df = pd.read_csv('county_adjacency2010.csv')

邻接文件将会像这样读入。

这是全国每个县的名单。我们需要把范围缩小到纽约州的县,否则我们会把邻近州的县也包括进来。要做到这一点,从原始 df 中制作一个 FIPS 列表,然后根据它进行过滤。

county_FIPS_list = list(df.index)
adj_df = adj_df[adj_df['fipscounty'].isin(county_FIPS_list)]
adj_df = adj_df[adj_df['fipsneighbor'].isin(county_FIPS_list)]

然后删除除 FIPS 代码之外的所有列

adj_df = adj_df[['fipscounty', 'fipsneighbor']]

我们将定义一个函数,将数据帧转换为元组列表,同时删除任何镜像或自连接的边。

def create_tuples(df):
    all_tuples = list(df.itertuples(index=False, name=None))
    final_tuples = [] for tuple in all_tuples:
        if (tuple[1],tuple[0]) not in final_tuples:
            if tuple[1] != tuple[0]:
                final_tuples.append((str(tuple[0]),str(tuple[1]))) return final_tuples

最后,将邻接数据帧传递给它,并将结果添加到我们的图中。

fips_tuples = create_tuples(adj_df)
G.add_edges_from(fips_tuples)

肉眼观察

为了检查结果,我们将定义一个快速函数来绘制图形。

import matplotlib.pyplot as pltdef draw_graph(G):
    plt.close()
    nx.draw(G, with_labels=True, font_weight='bold')
    plt.show()
    return

最后,我们将把最终的 graph 对象传递给它来查看结果。这将是一个国家的抽象,可能看起来一点也不像纽约。

draw_graph(G)

NYS 邻接图的两种可能表示

就是这样。感谢您的阅读!

中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-95f355934d98?source=collection_archive---------34-----------------------

对你永远记不住的概念的简要解释

Unsplash 上的 chuttersnap 拍摄

在概率和统计中,特别是在假设检验中,你会经常听到一种叫做中心极限定理的东西。中心极限定理(CLT)或多或少地表明,如果我们重复地抽取独立的随机样本,随着样本量的增加,样本均值的分布接近正态分布。无论群体或原始变量的分布形状如何,都会发生这种情况。提醒一下, 样本 总体*正态分布 用钟形曲线表示(如下图)。我们也可以使用 CLT 来估计样本值大大偏离总体均值的概率。正如我们在下面的图表中看到的,样本均值偏离总体均值超过三个标准差的概率极低。*

m . w . Toews——自己的作品,基于(概念上)杰瑞米·坎普的数字,2005 年 2 月 9 日,CC BY 2.5,https://commons.wikimedia.org/w/index.php?curid=1903871

中心极限定理对于从样本统计中估计总体参数非常有用,因为您通常无法从您的实验所代表的整个总体中获得数据。通常,数字 30 被用作 CLT 成立的最小样本量的标志。中央极限理论的一个流行例子是掷骰子的实验。掷出六面骰子时,掷出 1、2、3、4、5 或 6 的概率总是⅙.这个图看起来几乎是平的。然而,如果我们掷骰子两次,取平均结果,并重复 500 次,随着分布变得更正常,图形将开始变得更像钟形。随着我们在平均之前继续增加我们执行的滚动次数(n ),由于中心极限定理,该图将进一步表示正态分布。

By Cmglee —自己的作品,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=18918612

参考资料:

* [## 中心极限定理

在概率论中,中心极限定理(CLT)确定,在某些情况下,当独立随机…

en.wikipedia.org](https://en.wikipedia.org/wiki/Central_limit_theorem) [## 中心极限定理:定义和例子在简单的步骤-统计如何

什么是中心极限定理?中心极限定理的例子:一步一步用视频剪辑中心极限定理…

www.statisticshowto.com](https://www.statisticshowto.com/probability-and-statistics/normal-distributions/central-limit-theorem-definition-examples/)*

中心极限定理:现实生活中的应用

原文:https://towardsdatascience.com/central-limit-theorem-a-real-life-application-f638657686e1?source=collection_archive---------6-----------------------

中心极限定理(CLT)是统计学中最流行的定理之一,在现实世界的问题中非常有用。在这篇文章中,我们将看到为什么中心极限定理是如此有用,以及如何应用它。

在许多使用统计的情况下,最终目标是识别人口的特征。

中心极限定理是一个近似值,当你研究的群体如此之大,需要很长时间来收集每个个体的数据时,你可以使用它。

人口

群体是你正在研究的一组个体。尽管他们被称为个体,但构成群体的元素不一定是人。

如果你是一家连锁杂货店的区域经理,你正努力提高效率,每周为每个商店的苏打水部分重新进货,这样你就能卖出尽可能多的苏打水,并避免最终出现大量未售出的存货,在那个特定的商店中售出的所有**箱苏打水代表了总人数。

如果你是一个家禽饲养者,想订购鸡饲料,你需要知道你的母鸡通常吃多少磅谷物。所以在这里,就是你的种群。

研究人口是困难的

根据您正在解决的问题,收集整个群体的数据将会非常困难。

如果像可口可乐这样的公司想知道他们的美国消费者是否会喜欢他们正在开发的新产品,他们不可能派一大批研究人员去和美国的每一个人交谈。嗯,他们也许可以,但是那会非常昂贵,而且需要很长时间来收集所有的数据😀

这就是为什么公司要对代表产品受众的几组人进行用户研究,这样他们就可以收集数据并确定是否值得继续进行产品开发。所有这些,都没有和所有人谈过。

因此,从统计学的角度来说,你将从你的人口中收集个样本,通过结合样本中的信息,你可以得出关于你的人口的结论。

从总体中抽取两个样本。

好的样品必须是:

  • 人口的代表,
  • 大到足以从中得出结论,在统计学中样本量大于或等于 30。
  • 随机挑选的,所以你不会偏向人群中的某些特征。

代表性样品

一个有代表性的样本必须显示出人口的所有不同特征。

如果您想知道谁更有可能赢得超级碗,并决定对美国人口进行民意调查,即从美国人口中抽取样本,您需要确保与以下人群进行交谈:

  • 所有不同的州都认为谁会赢,
  • 不同的年龄组和不同的性别,

在你的研究中,只包括那些对运动或运动本身感兴趣的人,否则,他们不会是对你的研究感兴趣的人群的一部分。

萨尔茨的箱子

你是一家杂货连锁店的区域经理,负责该地区的 350 家商店,下一个项目是优化萨尔茨矿泉水的每周补货。

您想知道每个商店每周订购多少箱苏打水,这样您就可以最大限度地减少商店货架上的闲置库存。

你知道必须有一个更好的方法来得到一个合理的答案,而不需要访问你所在地区的每一家商店并获得他们每周的销售数字。

既然你上过几堂统计学课,中心极限定理就会浮现在脑海里。你知道,应用于现实世界的问题,中心极限定理可以帮助你平衡收集所有数据所需的时间和成本,从而得出关于总体的结论。

你还记得样本均值中心极限定理的定义[1]:

当我们从具有均值μ和标准差σ的总体中收集足够大的 n 个独立观测值的样本时,样本均值的抽样分布将接近正态分布,均值= μ,标准差= σ/ √n

中心极限定理的可视化。从总体中抽取样本,获取它们的平均值,并创建样本均值分布。

中心极限定理告诉你,我们不必访问该地区的每一家商店,获得他们一周的苏打水销售数字,就可以知道下一个订单要放多少箱。你可以做的是从你的商店(总体)的每周销售中收集许多样本,计算它们的平均值(销售的苏打水的平均数量)并建立样本平均值的分布。这种分布也称为抽样分布。

如果这些样本满足中心极限定理的标准,您可以假设样本均值的分布可以近似为正态分布。所以现在你可以使用正态分布提供的所有统计工具。

从这一点开始,由于您知道了手头的分布,您可以计算概率和置信区间,并执行统计测试。

中心极限定理的总体抽样准则

但是在使用中心极限定理和使用正态分布近似之前,您的样本必须满足一组特定的标准,这些标准扩展了好样本的特征。

您的样品应该是:

  • **随机选取,这样你就不会偏向于群体中的某些特征,并且保证样本中的每个观察值都独立于所有其他观察值。这也有助于确保样本中的每个观察都是独立的。
  • **人口的代表
  • **大到足以得出结论的,在统计学上指样本量大于或等于 30。
  • **包括不到 10%的人口,如果你抽样没有替换的话。由于总体中的观察值并不都是相互独立的,如果您收集的样本太大,您可能最终会收集到相互不独立的观察值。即使这些观察是随机选取的。

你不需要知道人口分布——中心极限定理的超级威力

如果你想使用任何一种推断统计方法,即了解你的数据的概率分布特征,你需要知道你的数据遵循的分布。否则,你可能会在工作中使用错误的工具。

所以想到的一个问题是我需要知道我的人口分布才能使用中心极限定理吗?**

简短的回答是😁

中心极限定理真正强大的地方在于,你不需要事先知道你的人口分布。你所需要做的就是收集足够多的符合标准的样本,你就可以确定样本均值的分布将遵循正态分布。

你每周需要补充多少箱苏打水?

为了回答这个问题,让我们生成一个随机数据集来代表总体,其中每个数据点都是你所监管区域的每个商店每周售出的苏打水的总数。

随机生成的萨尔茨啤酒销售数据集中的片段。

*import pandas as pd
import random
import globdef create_dataset(dataset_size):
    *""" Creating the population dataset """* dataset = []

    while dataset_size > 0:
      dataset.append(random.randrange(3, 100))
      dataset_size -= 1 return dataset# Initializing the random number generator
random.seed(1234)# Reading the output directory in case we've already generated the population dataset
dataset_file_list = glob.glob("output/sales_dataset.csv")sales_data = None# Creating the population dataset and saving it to avoid always recreating the dataset
if len(dataset_file_list) == 0:    
    sales_data = pd.DataFrame(data=create_dataset(4200))
    sales_data.columns = ['sales']
    sales_data.to_csv("output/sales_dataset.csv", index=False)
else:
    sales_data = pd.read_csv('output/sales_dataset.csv')*

然后你可以取不同数量的样本,所有样本的大小都相同,然后绘制销售数据,看看看起来怎么样。

样本数据本身的分布不一定具有正态分布的形状。还有,中心极限定理不需要你知道人口的分布。

从总体中抽取不同数量样本的分布,每个样本有 30 个数据点。

在这个例子中,每个图表都有不同数量的样本,所有样本的大小都是 30,没有一个分布看起来像经典的钟形曲线。差远了。

当你取另一组样本时,这不会有太大变化,这次每个样本有 100 个数据点。

从总体中抽取不同数量样本的分布,每个样本有 100 个数据点。

*import numpy as np
import matplotlib.pyplot as pltdef picking_n_samples(population, number_samples, sample_size):
    *""" Sampling without replacement with fixed size
        Returning the array of sample and array with their respective mean
    """* results = []
    sample_mean = []

    while number_samples > 0:
        new_sample = random.sample(population, sample_size)
        results += new_sample
        sample_mean += [np.mean(new_sample)]
        number_samples -= 1 return [results, sample_mean]def generate_sample_sets(dataset, number_samples, sample_size):
    *""" Generate multiple sets samples with fixed size
        Returns all sample sets and their corresponding set of means    
    """* samples_array = []
    sample_means_array = [] for sample_count in number_samples:
        new_sample, sample_mean = picking_n_samples(dataset, sample_count, sample_size)
        samples_array.append(new_sample)
        sample_means_array.append(sample_mean) return [samples_array, sample_means_array] def plot_samples(sample_array, number_samples, default_size, plot_color='#6689F2', title='', x_axis_title='', filename='plot'): fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(12, 7), constrained_layout=True)
    fig.suptitle(title, fontsize=16) ax1.hist(sample_array[0], color=plot_color)
    ax1.set_title("Taking " + str(number_samples[0]) + " samples of size=" + str(default_size), fontsize=10)
    ax1.set_xlabel(x_axis_title) ax3.hist(sample_array[2], color=plot_color)
    ax3.set_title("Taking " + str(number_samples[2]) + " samples of size=" + str(default_size), fontsize=10)
    ax3.set_xlabel(x_axis_title) ax2.hist(sample_array[1], color=plot_color)
    ax2.set_title("Taking " + str(number_samples[1]) + " samples of size=" + str(default_size), fontsize=10)
    ax2.set_xlabel(x_axis_title) ax4.hist(sample_array[3], color=plot_color)
    ax4.set_title("Taking " + str(number_samples[3]) + " samples of size=" + str(default_size), fontsize=10)
    ax4.set_xlabel(x_axis_title)

    fig.savefig("output/" + filename) ######################### Example 1####################### Setting the defaults for this example
example1_number_of_samples_array = [5, 50, 100, 1000, 10000]
example1_default_sample_size = 30# Picking multiple samples of size 30
example_1_samples, example_1_means = generate_sample_sets(list(sales_data['sales'].values), example1_number_of_samples_array, example1_default_sample_size)# Plot the different sets of samples
plot_title = 'Distribution of sales from different samples of size ' + str(example1_default_sample_size)plot_samples(example_1_samples, example1_number_of_samples_array, example1_default_sample_size, title=plot_title, filename="example_1_samples_distribution")########################## Example 2######################## Setting the defaults for this example
example_2_number_of_samples_array = [5, 50, 100, 1000, 10000]
example_2_default_sample_size = 100example_2_samples, example_2_means = generate_sample_sets(list(sales_data['sales'].values), example_2_number_of_samples_array, example_2_default_sample_size)# Plot the different sets of samples
plot_title = 'Distribution of sales from different samples of size ' + str(example_2_default_sample_size)plot_samples(example_2_samples, example_2_number_of_samples_array, example_2_default_sample_size, title=plot_title, filename="example_2_samples_distribution", plot_color="#96D2D9")*

因为关键是取样并计算平均值!

看一下前面例子中样本均值的分布就清楚了。随着样本数量的增加,你就越接近正态分布的形状。

从总体中抽取不同样本的抽样分布,每个样本有 30 个数据点(左)和 100 个数据点(右)。

较高数量的样本还会降低采样分布的可变性。

如果你观察有 5 个和 50 个样本的分布,你会注意到后者有一个较小的标准差。

如果您收集的样本越大,获得极值的机会就越少,因此您的值会更加集中在一起。因此,标准偏差或与平均值的距离会更小。

从公式的角度来看,回顾中心极限定理的定义,采样分布的标准偏差(也称为标准误差)等于σ/ √n。因此,随着样本量的增加,分母也会增加,从而使总体标准值变小。

**

具有(顶部)5 个大小为 30 的样本和(底部)50 个大小为 30 的样本的抽样分布的汇总统计。

*example_1_sampling_distribution_5_samples = pd.Series(example_1_means[0])print("Example 1: Summary statistics for sampling distribution with " + str(len(example_1_sampling_distribution_5_samples)) + " samples taken (size= " + str(example1_default_sample_size) + ")")
print(example_1_sampling_distribution_5_samples.describe()) example_1_sampling_distribution_5_samples = pd.Series(example_1_means[1])print("Example 1: Summary statistics for sampling distribution with " + str(len(example_1_sampling_distribution_5_samples)) + " samples taken (size= " + str(example1_default_sample_size) + ")")
print(example_1_sampling_distribution_5_samples.describe())*

如果您从随机生成的销售数据集中抽取 10,000 个大小为 100 的样本,您将得到一个类似于正态分布的钟形曲线特征的采样分布。

*def plot_sample_means(sample_means_array, plot_color='#A9CBD9', title='', filename='plot'):
    fig, ax = plt.subplots(figsize=(12, 7))
    fig.suptitle(title, fontsize=16)
    ax.hist(sample_means_array, color=plot_color) 

    # removing to and right border
    ax.spines['top'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['right'].set_visible(False) # adding major gridlines
    ax.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5) ax.set_xlabel("Average number of seltzer cases sold")
    fig.savefig("output/" + filename)plot_title = 'Sampling distribution from taking 10,000 samples of size 30 ' + str(example1_default_sample_size)plot_sample_means(example_1_means[4], title=plot_title, filename="example_1_sampling_dist_10ksamples")*

回到原文,如果你想知道每周需要重新备货多少箱苏打水,看看这个最后抽样分布的汇总统计,一万个样本的那个。

抽样分布的平均值是 51,所以你需要每周每家商店平均 51 箱的。**

具有 10,000 个大小为 100 的样本的抽样分布的汇总统计数据。

**example_2_sampling_distribution = pd.Series(example_2_means[4])print("Summary statistics for sampling distribution with " + str(example_2_number_of_samples_array[4]) + " samples taken (size= "+ str(example_2_default_sample_size) + ")")print(example_2_sampling_distribution.describe())**

这是您所在地区所有商店的平均值。如果您想要每个商店的更精确的数字,您必须为每个商店做这个过程。每家商店都成为总体,你只从那家商店中抽取样本。

你离人口平均数有多近?

既然您生成了销售数据集,您可以做另一个有趣的检查。看看抽样分布的均值离真实总体均值有多远。

人口平均 51!

人口统计摘要。

**# Population summary statisticsprint("Summary statistics for the population (sales dataset)")
print(sales_data['sales'].describe())**

结论

我们刚刚体验了中心极限定理的威力!

使用随机生成的集合,并且不知道原始分布的任何细节(您只在最后检查😀)你:

  1. 取了越来越多的样本,发现样本的分布越来越接近正态分布。
  2. 证实抽样分布的平均值非常接近总体分布,误差很小。
  3. 用中心极限定理解决现实生活中的问题。

希望你喜欢这篇文章,感谢阅读!

参考

[1] 开放简介统计—第四版(2019)

中心极限定理(CLT):数据科学

原文:https://towardsdatascience.com/central-limit-theorem-clt-data-science-19c442332a32?source=collection_archive---------21-----------------------

使用推断统计学学习中心极限定理(CLT)及其在数据科学中的应用。

图片由皮克斯拜的 Gerd Altmann 提供

正如我们在上一篇文章中看到的, 推断统计在数据科学中起着举足轻重的作用。中心极限定理(CLT)是现实世界中数据科学家最常用的技术,是推断统计学的一部分。

要了解 CLT,首先,我们需要了解以下话题:

  1. 样品
  2. 抽样分布

1。样本

从整个员工/人群列表中选择一些员工/人群称为样本

假设我们有一家公司,里面有 30,000 名员工。我们想知道所有员工每天的通勤时间。去找每个员工并记录他们的通勤时间将是非常繁琐和耗时的。

让我们看看是否有另一种方法来完成任务。在公司说;我们对 100 名随机雇员进行了调查。调查结束后,我们计算出员工的平均通勤时间为 36.6 分钟。仅仅考虑 100 名随机的雇员,这足以说明所有雇员的通勤时间是 36.6 分钟吗?

不,我们不能这么说。总体平均值大约为36.6+误差,即如果误差为 3 分钟,那么员工的总体平均值将介于“36.6–3”到“ 36.6+3 ”之间。现在,我们如何找出错误?

要回答这个问题,首先,我们必须了解采样术语。

  • 项目总数/人口,人口规模** = N**
  • 总体均值,总体均值(μ)=(σ* X)/N****
  • 总体方差,总体方差(σ)=σ(Xi—μ)/N****
  • 项目数/总体,样本量= n****
  • 样本员工的均值,样本均值(x)=(σ* x)/n****
  • 样本方差,样本方差(S)=σ(Xi—x)/n-1****

让我们看看如何从给定的样本量中找到样本均值和样本方差,

我们需要从下面的样本数据中找出一个地区的人的平均身高。

样本量(n) = 5
样本均值(x)=(121.92+133.21+141.34+126.23+175.74)/5 = 139.69
样本方差(S)= sqrt[{(121.92–139.69)+(133.21–139.69)+(141

这就是我们如何在样本数据的帮助下计算样本均值和方差。

2.抽样分布

抽样分布是从总体列表中抽取的许多样本中获得的分布概率。

意思是,我们公司有 30000 名员工。首先,我们随机选择 50 名员工,计算他们的平均值,假设为 x 1。之后,我们将从整个列表中随机抽取另外 50 名员工,计算平均值,即 x ^ 2。假设我们继续这个过程,并计算平均值直到 x 100。

有趣的是,我们得到的是样本均值的分布。

如果我们把所有样本的均值分布绘制成一个图形,它就代表了二项分布。

抽样分布有一些有趣的性质,最终有助于发现总体均值的误差。

抽样分布的平均值用 μₓ表示。

μₓ =(所有样本平均值之和)/(样本总数)

****样本分布均值有两个重要属性:

  1. 抽样分布均值 (μₓ ) =总体均值 (μ)
  2. 抽样分布的标准差(标准差** ) = σ/√n ,其中σ为总体的标准差,n 为样本量**

中心极限定理

中心极限定理(CLT)指出,对于任何数据,只要有大量的样本。以下属性成立:

  1. 抽样分布均值 (μₓ ) =总体均值 (μ)
  2. 抽样分布的标准差(标准差** ) = σ/√n ≈S/√n**
  3. 对于 n > 30 ,抽样分布变为正态分布

让我们通过 Jupyter Notebook 验证一下 Python 中 CLT 的性质。

对于下面的 Python 代码,我们将使用人口和随机值的数据集,我们可以在这里找到。

首先,将必要的库导入 Jupyter 笔记本。

我们导入了我们在后续代码中使用的所有必需的包。因为我们将随机对信息进行采样,所以我们设置了一个随机种子np.random.seed(42),以便分析是可重复的。

现在,让我们阅读我们正在处理的数据集,

数据集看起来像这样,

人口数据集

让我们从数据集中提取“Weight”列,并查看该列的分布。

这个重量柱和它的分布图看起来像这样,

正如我们所看到的,图表接近于一个正态分布图

我们也通过代码找出权重列的均值和标准差。

均值= 220.67326732673268
Std。戴夫。= 26.643110470317723

这些值是重量列的精确平均值和标准偏差值。

现在,让我们开始采样数据。

首先,我们将从数据中抽取 30 个成员的样本。其原因是,在对观测值进行重复抽样后,我们需要确定抽样分布是否符合正态分布。

上述样本的平均值= 222.1,大于实际平均值 220.67。让我们重新运行代码,

df.Weight.sample(samp_size).mean()

上述样本的平均值= 220.5,几乎等于原始平均值。如果我们重新运行代码,我们将得到平均值= 221.6

每次我们取样时,平均值是不同的。样本均值本身存在可变性。让我们向前看,看看样本均值是否服从分布。

我们不是一次取一个样本平均值,而是取大约 1000 个这样的样本平均值,并将其赋给一个变量。

我们已经将 sample_means 转换为 Series 对象,因为 list 对象没有为我们提供均值和标准差函数。

样本总数= 1000

现在,我们有 1000 个样本,这是我们的平均值。让我们使用 seaborn 绘制分布图。

分布图看起来像这样,

正如我们所观察到的,上面的分布看起来近似正态分布。

这里我们需要检查的另一件事是样本的平均值和标准差。

样本平均值= 220.6945,这几乎与原始平均值 220.67 相似,样本标准偏差= 4.64426363765

让我们看看样本的标准差和实际数据的标准差之间的关系。
当我们用原始数据的标准差除以其大小时,

df.Weight.std()/np.sqrt(samp_size)

我们得到上面代码的值= 4.86
,该值接近于sample_means.std()

所以,从上面的代码中,我们可以推断:

  • 抽样分布的均值 (μₓ ) = 总体均值 (μ)
  • 抽样分布的标准差(标准差** ) = σ/√n**

到目前为止,我们已经看到“重量”栏的原始数据是正态分布的形式。让我们看看,即使原始数据不是正态分布,样本分布是否也是正态分布。

我们将采用另一个包含一些随机值的数据集,并将这些值绘制成分布图。

数据集和图表看起来像这样,

正如我们所看到的,值列不像正态分布图。它看起来有点像指数分布。

让我们从这个分布中挑选样本,计算它们的平均值,并绘制出抽样分布图。

现在,样本的分布图看起来像这样,

令人惊讶的是,我们从 Values 列获得的 sample_means 的分布,虽然远非正态分布,但在很大程度上仍然是正态分布。

让我们将sample_means平均值与其父平均值进行比较。

sample_means.mean()
# The Output will be
130.39213999999996df1.Value.mean()
#The Output is
130.4181654676259

正如我们所看到的,sample_means的平均值和原始数据集的平均值都是相似的。

类似地,样本平均值的标准偏差是sample_means.std()= 13。38860 . 68868888861

那个值应该非常接近于df1.Value.std()/np.sqrt(samp_size)= 14。36860 . 68686868661

让我们将每个数据集的分布图与其对应的采样分布进行比较。

作者图片

正如我们所见,无论原始数据集的分布如何,采样分布都类似于正态分布曲线。

现在只有一件事需要考虑,那就是样本量。我们将观察到,随着样本量的增加,抽样分布将更加接近正态分布。

样本量对抽样分布的影响

让我们创建不同大小的样本,并绘制相应的分布图。

现在,样本量为 3,10,30,50,100,200 的分布图看起来像这样,

不同样本量的分布

正如我们所观察到的,样本量为 3 & 10 的分布图不像正态分布。然而,从样本大小 30 来看,随着样本大小的增加,样本分布类似于正态分布。

作为一个经验法则,我们可以说 30 或更大的样本量对于得出抽样分布接近正态的结论是理想的,并且可以从中得出进一步的推论。

通过这段 Python 代码,我们可以得出结论,CLT 的以下三个性质成立。

  1. 抽样分布均值 (μₓ ) =总体均值 (μ)
  2. 抽样分布的标准差(标准差** ) = σ/√n**
  3. 对于 n > 30 ,抽样分布变为正态分布

使用 CLT 估计平均值

30000 名员工的平均通勤时间 (μ) = 36.6 ( 样本均值 ) +一定的误差幅度。我们可以利用 CLT(中心极限定理)找到这个误差范围。现在我们知道了 CLT 是什么,让我们看看如何找到误差范围。****

假设我们有 100 名员工的平均通勤时间是 X =36.6 分钟,样本的标准差是 S=10 分钟。利用 CLT,我们可以推断,

  1. 抽样分布 Mean(μₓ ) =总体平均值(μ)
  2. 抽样分布标准偏差= σ/√n ≈S/√n = 10/√100 = 1
  3. 由于抽样分布是正态分布
    P(μ-2<36.6<μ+2)= 95.4%,我们通过正态分布曲线的 1–2–3 法则得到这个值。
    P(μ-2<36.6<μ+2)= P(36.6–2<μ<36.6+2)= 95.4%

你可以在我的上一篇文章“T2 推断统计”中找到标准分布曲线、Z 表及其属性

现在,我们可以说,总体均值(μ)有 95.4%的概率位于(36.6–2,36.6+2)之间。换句话说,我们有 95.4%的把握估计均值的误差≤ 2。

因此,与索赔相关的概率被称为置信水平(这里是 95.4%)。
样本均值的最大误差称为
误差幅度(此处为 2 分钟)。
值的最终区间称为
置信区间{这里是:(34.6,38.6)}

我们可以用以下方式概括这个概念。

假设我们有一个样本大小为 n、平均值为 X、标准偏差为 s 的样本。现在,μ的 y%置信区间(即对应于 y%置信水平的置信区间)将由以下范围给出:

置信区间= (X — (Z S/√n ) ,X + (Z S/√n))**

其中 Z*是与 y%置信水平相关联的 Z 分数。

下面给出了一些常用的 Z*值:

Z*

这就是我们如何在样本的帮助下计算误差幅度和估计总体均值的方法。

结论

正如我们所看到的,对于只有少量代表性的样本,找到均值标准差是有益的。由于时间和资金的限制,我们可能不得不这样做。利用 CLT 性质,我们可以找到总体均值(μ)、标准误差(σ/√n),以及最重要的置信区间(y%)。CLT 有利在民调结果与置信区间、保险、银行业等新闻上报道。这就是关于 CLT 及其属性以及它如何在数据科学中有用的全部内容。****

感谢您阅读快乐编码!!!

在这里查看我以前关于 Python 的文章

参考

中心极限定理——举例说明

原文:https://towardsdatascience.com/central-limit-theorem-explained-with-examples-4c10377ee58c?source=collection_archive---------27-----------------------

用实现清楚地解释

路易斯·佩尔迪戈在 Unsplash 上拍摄的照片

中心极限定理(CLT)是统计学领域中一个基本且广泛应用的定理。在我们详细讨论 CLT 之前,让我们先定义一些术语,以便更容易理解 CLT 背后的思想。

基本概念

  • 群体是一个群体中的所有元素。例如,美国的大学生是指包括美国所有大学生的人口。欧洲的 25 岁人群包括了所有符合描述的人。

对人口进行分析并不总是可行或可能的,因为我们无法收集人口的所有数据。因此,我们使用样本。

  • 样本是总体的子集。例如,美国 1000 名大学生是“美国大学生”人口的一个子集。
  • 概率分布:显示事件或实验结果概率的函数。考虑掷骰子的例子。有 6 种可能的结果(1,2,3,4,5,6)。如果骰子是无偏的,观察到顶面每个数字的概率是相等的,所以概率分布是离散的均匀分布。
  • 正态(高斯)分布:一种看起来像钟的概率分布;

描述正态分布的两个术语是均值标准差。Mean 是被观察到的概率最高的平均值。标准偏差是对数值分布程度的测量。随着标准差的增加,正态分布曲线变宽。

中心极限定理

正态分布用于表示分布未知的随机变量。因此,它被广泛应用于包括自然科学和社会科学在内的许多领域。证明为什么它可以用来表示未知分布的随机变量的理由是中心极限定理(CLT)

根据 CLT ,当我们从一个分布中抽取更多样本时,样本平均值将趋向于一个正态分布而不管总体分布如何。

考虑一个案例,我们需要学习一个国家所有 20 岁人的身高分布。收集这些数据几乎是不可能的,当然也是不切实际的。所以,我们在全国范围内抽取 20 岁人群的样本,计算样本中人群的平均身高。根据 CLT,当我们从总体中抽取更多样本时,抽样分布将接近正态分布。

为什么正态分布如此重要?正态分布用平均值和标准偏差来描述,它们很容易计算。如果我们知道正态分布的均值和标准差,我们就可以计算出关于它的几乎所有东西。

证明 CLT 的例子

让我们看几个例子,证明 CLT 是正确的。我们将使用 python 库来创建群体、样本和绘图。和往常一样,我们从导入相关库开始:

import numpy as np
import pandas as pd #Data visualization
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='darkgrid')%matplotlib inline

我们首先定义一个从分布中创建随机样本的函数。我们可以使用熊猫的样本功能,它将选择随机元素而不替换。

def random_samples(population, sample_qty, sample_size):
    sample_means = []
    for i in range(sample_qty):
        sample = population.sample(n=sample_size)
        sample_mean = np.array(sample).mean()
        sample_means.append(sample_mean)
    return sample_means

我们只需要输入一个总体,我们需要多少个样本(sample_qty),以及每个样本包含多少个观察值(sample_size)。然后,该函数将选择样本并计算它们的平均值。返回的列表将包括样本均值。

让我们首先定义一个实际上具有正态分布的总体。我们使用 np.random.randn 函数创建一个大小为 10000 且呈正态分布的数组。

norm = list(np.random.randn(10000))
plt.figure(figsize=(8,5))
plt.title("Normal Distribution", fontsize=18)
sns.distplot(norm, hist=False)

现在我们从总体中抽取 30 个样本,每个样本包含 30 个值。请注意,我们需要将人口转换为熊猫系列,因为样本函数不接受 numpy 数组。

population = pd.Series(norm)
samples_from_normal = random_samples(population, 30, 30)
plt.figure(figsize=(7,4))
plt.title("Distribution of Sample Means - Normal Distribution", fontsize=15)
sns.distplot(samples_from_normal, hist=False)

正态分布的抽样分布

抽样分布(样本平均值的分布)看起来非常接近正态分布。随着我们抽取越来越多的大样本,样本分布将看起来更“正常”。

让我们对随机分布为的人群应用同样的程序。我们首先创建一个包含 1000 个随机数的数组:

random = np.random.random(1000)
plt.figure(figsize=(7,4))
plt.title("A Random Distribution", fontsize=15)
sns.distplot(random, hist=False)

让我们看一下 30 个样本,每个样本有 30 个值时的采样分布情况:

population = pd.Series(random)
samples_from_normal = random_samples(population, 30, 30)
plt.figure(figsize=(7,4))
plt.title("Distribution of Sample Means (30 samples)", fontsize=15)
sns.distplot(samples_from_normal, hist=False)

随机分布的抽样分布(30 个样本)

它越来越接近正态分布。我们现在尝试使用 50 个样本,并将样本大小增加到 50:

随机分布的抽样分布(50 个样本)

看起来肯定更“正常”。我添加了文本代码,所以你可以复制粘贴,并尝试不同的样本数量和大小。

我们也可以试试指数分布,看看 CLT 是否适用:

exp = np.random.exponential(0.01, 5000)
plt.figure(figsize=(7,4))
plt.title("Exponential Distribution", fontsize=15)
sns.distplot(exp, hist=False)

如果我们随机抽取 50 个大小为 50 的样本,样本均值的分布如下所示:

population = pd.Series(exp)
samples_from_normal = random_samples(population, 50, 50)
plt.figure(figsize=(7,4))
plt.title("Distribution of Sample Means (50 samples)", fontsize=15)
sns.distplot(samples_from_normal, hist=False)

指数分布的抽样分布(50 个样本)

它看起来更像正态分布,而不是指数分布。对于 100 个样本,正态性更加突出:

指数分布的抽样分布(100 个样本)

正如我们在示例中看到的,不管总体分布如何,当我们获取更多样本时,样本均值的分布越接近正态分布。这正是中心极限定理所陈述的。

感谢您的阅读。如果您有任何反馈,请告诉我。

用 Python 代码解释的中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-explained-with-python-code-230884d40ce0?source=collection_archive---------6-----------------------

马文·朗斯多夫在 Unsplash 上的照片

一个解释中心极限定理的模拟:即使一个样本不是正态分布,如果你抽取多个样本,取它们的每个平均值,这些平均值将代表一个正态分布。

条条大路通罗马!等等不要。条条大路通涩谷!等等不要。所有样本平均值都是总体平均值。

中心极限定理表明,如果你随机抽取一个客户样本,比如说 1000 个客户,这个样本本身可能不是正态分布的。但是如果你现在重复这个实验 100 次,那么这 100 个样本(1000 个客户)的 100 个平均值将构成一个正态分布。

这一行对我们很重要:“这个样本本身可能不是正态分布的”。为什么?因为生活中的大多数事物都不是正态分布的;不是等级,不是财富,不是食物,当然也不是我们的顾客在我们店里付了多少钱。但是生活中的一切都有泊松分布;更好的是,生活中的一切都可以用狄利克雷分布来解释,但为了简单起见,让我们坚持用泊松分布(泊松分布实际上是狄利克雷分布的简化情况)。

但实际上在一个电商店里,我们的客户大部分都是非购买客户。因此,分布实际上看起来像一个指数,因为泊松可以从指数得到,让我们做一些指数分布来反映我们的客户的购买。

让我们试一个例子

假设我们的客户群的平均订单价值为 170 美元,那么我们将用这个平均值创建指数分布。我们将尝试通过查看一些样本平均值来获得该值。

仅抽取四个样本

在这里,我抽取了 1000 名客户的样本。然后重复 4 次。我得到了以下四个分布(要得到与此类似的图形,请在末尾使用代码 repeat _ sample _ draws _ exponential(4,1000,170,True)):

从 1000 名顾客中随机抽取 4 个样本。每个样本都有一个平均值为 170 美元的指数分布。

下面是绘制的 4 个平均值(要获得类似的图形,请在结尾处使用代码 repeat _ sample _ draws _ exponential(4,1000,170,True)):

绘制的四个样本的平均值。

上述 4 个样本均值的平均值为 165.48 美元
上述 4 个样本均值的标准差为 5.36 美元

因此,如果您在这里停止实验,在四个样本中,您将报告您的客户群的平均订单价值为 166 美元,其中 68% ( 1 标准差包含 68% )的客户购买了 161 美元到 171 美元之间的商品(从 166+/-$5 美元)。这将是一个错误的结论,因为我们所有的这些模拟都是基于最初的假设,即人口平均值是 170 美元!

抽取 100 个样本,但保持每个样本的大小与上述 1000 个客户相同

如果我们重复这个实验 100 次会发生什么?即抽取 1000 个客户的 100 个样本?

在末尾使用代码:
repeat _ sample _ draws _ index(100,1000,170,True)

我们将得到 100 个类似这样的指数分布(要得到类似的图形,请在末尾使用代码 repeat _ sample _ draws _ exponential(100,1000,170,True)):

从 1000 名顾客中随机抽取 100 个样本。每个样本都有一个平均值为 170 美元的指数分布。

100 个平均值的分布现在看起来像正态分布(要获得类似的图形,请在结尾处使用代码 repeat _ sample _ draws _ exponential(100,1000,170,True)):

绘制的 100 个样本的平均值。

上述 100 个样本均值的平均值为 169.55 美元
上述 100 个样本均值的标准差为 5.18 美元

因此,现在您会得出结论,您的客户群的平均支出为 170 美元(耶!这实际上是我们的第一个假设!)我们 68%的客户购买价格在 165 美元到 175 美元之间。

关于标准差的旁注

注意标准偏差没有变化:当我们抽取 4 个样本时是 5 美元,当我们抽取 100 个样本时是 5 美元。您可以对 10000 个样本运行下面的代码,并看到标准偏差不会从$5 改变。这是为什么呢?

这就把我们带到了经常被忽视的中心极限定理的第二部分:样本均值的标准差等于总体的标准差除以样本大小的平方根。

我们的人口是平均 170 美元的指数分布。指数有一个特殊的性质,即它的标准差等于它的平均值,所以总体平均值的标准差是 170 美元。因此,在这种情况下,我们预计样本均值的标准差为 170/sqrt(1000) = 5.4

这就是我们得到的结果,样本的标准差——意味着大约是 5 美元。无论我们重复抽样多少次,标准偏差都不会改变,因为它只取决于样本量(它也取决于总体平均值,但对于给定的总体来说,它保持不变)

结论

这就是中心极限定理。抽取的样本越多,就越能准确预测总体均值。我们不可能测试/调查我们所有的客户(或我们所有的人群),所以我们能做的下一个最好的事情是抽取几个较小数量的样本,并得到这些平均值的平均值。这里的关键是尽可能多地抽取样本。当我们这样做时,我们有:

而样本均值分布的标准差会随着你增加你的样本量而改变(样本量不是样本数;在我们的示例中,样本大小为 1000,样本数量为 100):

在以后的帖子里,我会描述为什么这是 A/B 测试中的一个重要概念

代码重现了这一点:

**import** numpy **as** np
**import** matplotlib.pyplot **as** plt

**def** repeat_sample_draws_exponential(n, samp_size, mu, show_all=**False**):
    means = []

    samples = []
    **for** ii **in** range(0, n):
        samples.append(np.random.exponential(mu, samp_size))
        means.append(np.mean(samples[ii]))

    **if** show_all:
        pltdim = np.math.ceil(np.math.sqrt(n))
        fig, axs = plt.subplots(pltdim, pltdim, figsize=(8, 8), gridspec_kw={**'hspace'**: 0.2}, sharex=**True**, sharey=**True**)
        fig.suptitle(**'Individual Samples\' Order Value Distribution'**)
        fig.text(0.5, 0.04, **'Order Values ($)'**, ha=**'center'**)
        fig.text(0.04, 0.5, **'Number of Customers'**, ha=**'center'**, rotation=**'vertical'**)
        axs = axs.flatten()
        **for** ii **in** range(0, n):

            plt.sca(axs[ii])

            plt.gca().hist(samples[ii], bins=int(50), histtype=**'step'**,
                           label=**'$mean = {0:.2f}$'**.format(np.mean(samples[ii])), range=[0, 2 * mu])
            **if** n < 10:
                plt.gca().set_title(**'Sample #{0} : average={1:.2f}'**.format(ii, np.mean(samples[ii])))
            **for** item **in** ([axs[ii].title, axs[ii].xaxis.label, axs[ii].yaxis.label] +
                             axs[ii].get_xticklabels() + axs[ii].get_yticklabels()):
                item.set_fontsize(8)

        plt.savefig(**'expdist_{0}_mu_{1}_sample_{2}_sampsize'**.format(mu, n, samp_size))

    plt.clf()
    plt.hist(means, bins=int(10), histtype=**'step'**)
    plt.title(**'Overall Average of {} Samples\' Average Order Value'**.format(n))
    plt.xlabel(**'Average of Individual Sample\'s Order Value ($)'**)
    plt.savefig(**'average_of_expdist_{0}_mu_{1}_sample_{2}_sampsize'**.format(mu, n, samp_size))
    print(**'mean of the samples is {0:.2f}'**.format(np.mean(means)))
    print(**'standard deviation of the samples is {0:.2f}'**.format(np.std(means)))

repeat_sample_draws_exponential(100, 1000, 170, **True**)

中心极限定理的应用

原文:https://towardsdatascience.com/central-limit-theorem-in-action-1d4832599b7f?source=collection_archive---------7-----------------------

数据科学

以及实际应用中的例子

图片来源:凯西·邓恩和《生物》剧组 Vimeo

统计学是一个数据科学家的必备知识。中心极限定理是它的基石。

当我看到任何理论概念在实践中时,我学得更好。我相信有更多像我一样的人,所以我今天将用一个具体而又朗朗上口的例子来解释中心极限定理——希望让它永久留在你的脑海中,供你使用。

你还记得当今世界的平均寿命是多少吗?(提示:如果没有,请在此处查看)

是 73。

这是一个总结了全世界,确切地说是 186 个国家预期寿命数据的数字。如果我们把这个数字放到完整的上下文中,它会告诉我们更多。

上下文是由统计术语组成的,所以我们先来了解一下:

群体:包含来自您的实验空间的元素、个体或度量的所有数据的集合。我们的实验空间是世界,人口是所有国家的预期寿命数据——人口规模用 N 表示。

样本:是从总体中随机选择的一个子集,样本量用 n 表示。

分布: It 描述了数据/总体/样本范围以及数据在该范围内是如何分布的。截至 2018 年,全球预期寿命分布如下:

平均值:您的总体或样本的所有数据的平均值。在本例中,总体平均值为 73,用(Mu)表示总体,用 (x 条)表示样本。

标准差:不是所有国家的平均寿命都是 73。它们分布在我们上面看到的范围内。标准差是对人口分布的一种度量,用 σ (适马)表示。

正态分布—钟形曲线—高斯分布:当你的总体围绕平均值以σ标准差完美对称分布时,你得到如下钟形曲线:

维基百科上的正态分布

我们只触及了在解释中心极限定理中使用的必要统计术语的表面,现在让我们来看看这个定理的实际应用!

截至 2018 年全球平均预期寿命是怎样的分布?它是正态分布还是其他分布?

嗯,这不是一个完美的正态分布,因为它似乎被拉向左侧,被称为左偏分布。

现在让我们从人群中抽取一些样本。换句话说,让我们从总体中抽取 1000 个大小为 150 的子集,并绘制每个样本均值的分布图(x̄).这个过程叫做抽样分配:

这是一个完美的正态分布!实际上,来自任何总体的任何抽样分布都显示正态分布,因为中心极限定理指出:

不管总体分布的初始形状如何,抽样分布将接近正态分布。随着样本量的增加,抽样分布将变得更窄且更正态。

这个视频用兔子和龙的翅膀以意想不到的有趣方式解释了这个定理🙂

视频致谢:生物演员&凯西·邓恩在 Vimeo 上解释了中心极限定理

回到我们对中心极限定理的解释,它允许我们用下面的公式计算抽样分布的标准偏差——称为标准误差:

标准误差公式,其中 σ是标准偏差,n 是样本量。 图像来源

让我们看看这个计算是否也适用于我们创建的人口和抽样分布:

果然不出所料!这个公式的直观解释是;随着样本量的增加,抽样分布将更准确地表示总体参数(平均值和标准偏差)。

奖金定理:你知道抽样分布的中心在哪里吗?你认为抽样分布和总体均值都是 73 是巧合吗?

当然不是!这用统计学中的另一个基本定理来解释:大数定律。随着从总体中抽取的样本越多,样本量越大,抽样分布的均值将越接近总体均值。

中心极限定理的实际应用

在任何机器学习问题中,给定的数据集代表来自总体的样本。使用这个样本,我们试图捕捉数据中的主要模式。然后,在进行预测时,我们尝试将样本中的模式推广到总体。中心极限定理有助于我们对样本和总体参数进行推断,并使用它们构建更好的机器学习模型。

此外,该定理可以通过观察抽样分布来告诉我们一个样本是否可能属于一个总体。这个定理的力量也在于此。

当我为这篇博文键入第一个单词时,我打算写统计意义和假设检验,但我意识到中心极限定理是解释它们的核心。所以,我将把它们留给下一篇文章。关注我的媒体账号了解他们😉

感谢阅读!如果你想更仔细地看看这个定理的“作用”,你可以看看这个 Deepnote 笔记本。我这个吸引人的例子来源于 Gapminder 的公开数据,可以在这里找到

如果你喜欢这篇文章,你可以在这里查看我的其他文章:

对于评论或建设性的反馈,您可以通过回复、 TwitterLinkedin 联系我!

来源:

[## 机器学习的中心极限定理简介

中心极限定理是统计学和机器学习中经常被引用但被误解的支柱。这是…

machinelearningmastery.com](https://machinelearningmastery.com/a-gentle-introduction-to-the-central-limit-theorem-for-machine-learning/)

中心极限定理:证明&通过数学实际工作

原文:https://towardsdatascience.com/central-limit-theorem-proofs-actually-working-through-the-math-a994cd582b33?source=collection_archive---------2-----------------------

…不要再做另一个“手动波浪状”的 CLT 解释…让我们实际算一算

迭戈·PH 在 Unsplash 上的照片

背景和动机

对于任何从事数据科学、统计学或机器学习研究的人来说,说“知道中心极限定理(CLT)很重要”是一种保守的说法。特别是从数理统计的角度来看,在大多数情况下,CLT 使得恢复参数估计的有效推理覆盖成为一个易处理和可解决的问题。

媒体平台上有几篇关于 CLT 的文章。然而,我注意到没有一篇文章(就我所知)深入研究这个定理的数学,甚至也没有恰当地说明 CLT 成立的假设。在我看来,这是一个巨大的伤害。这些都是上述领域每个从业者都应该知道的数学基础。

不仅理解 CLT 的数学基础很重要,而且理解 CLT 不成立的条件也很重要。例如,如果我们有一系列 n . I . I . d .柯西分布 RVs,它们的均值中心和标准偏差比例样本均值不会收敛到标准正态分布,CLT 不适用;如果我们对 CLT 的理解是“摇摆不定的”,那就很难理解上面的柯西例子。我希望这篇文章中的信息可以为感兴趣的人弥补知识上的差距。

本文分为三个部分:

  1. CLT -数学定义(特别是林德伯格-列维·CLT),我们为什么要关心?
  2. 证明 CLT 的数学准备
  3. 林德伯格的证明CLT

注意,中心极限定理其实不是一个定理;相反,它是一组相关的定理。这些定理依赖于不同的假设和约束。在本文中,我们将具体介绍林德伯格-莱维·CLT。这是 CLT 最常见的版本,也是大多数人在口语中提到 CLT 时实际引用的特定定理。

所以让我们开始吧!

1.CLT -数学定义,我们为什么要关心? :

让我们用文字(以明确的方式)来描述林德伯格-莱维·CLT:

作者图片

好极了。但是我们如何用数学方法来写呢?:

作者图片

作者图片

因此,(林德伯格–莱维)CLT 告诉我们,在上面指定的假设下,Y*在分布上收敛于标准正态分布 N(0,1)。

那么…有什么大不了的?我为什么要关心这个??

注意我们是如何为 CLT 搭建舞台的。我从没具体说过这 n 辆 RV 来自什么发行版。只是这 n 个 RVs 是独立的,并且是从具有定义的期望值和方差(一阶和二阶矩)的分布中抽取的。然而,即使有这种模糊的信息,我们可以说一些关于均值中心和标准差比例抽样估计的极限分布的建设性的东西。

CLT 是重要的和有影响力的,因为它(在许多情况下)可以使统计推断更容易处理。如果我们能以正确的形式参数化我们的抽样估计量,我们就能了解它的极限分布,即使我们不知道组成样本的 RVs 具体来自什么分布。从这些信息中,我们可以更容易地进行推理分析(即假设检验、p 值、置信区间等),而不必知道各个 RVs 本身的具体分布。

2.证明 CLT 的数学准备;

为了证明 CLT,我们可以利用一些数学事实和定理:

2A:变量变化:

作者图片

上面我们可以看到 Y和 S是数学上等价的抽样估计量。为了证明 CLT,我们将使用 S。这种选择仅仅是数学上的便利。用 S证明 CLT 比直接用 Y*更容易

2B:标准正常 RV 的力矩生成函数(MGF):

下面我们导出标准正态随机变量 Z~N(0,1)的矩母函数(MGF)。我们将在第 3 节看到为什么这很重要。

作者图片

2C。矩母函数的性质(MGF):

在第三节中,我们将代数操作 mgf。以下属性将会很有用:

作者图片

3.林德伯格的证明CLT:

我们现在准备证明 CLT。

但是我们的证明策略是什么呢?仔细查看上面的 2C 部分(MGFs 的属性)。最后陈述的性质(本质上)告诉我们,如果 RV A 的 MGF 逐点收敛于 RV B 的 MGF,那么一定是 RV A 在分布上收敛于 RV B

我们证明 CLT 的方法是证明我们的抽样估计量 S的 MGF 逐点收敛于标准正态 RV Z 的 MGF。在此过程中,我们证明了 S以分布收敛于 Z,即 CLT,并结束了我们的证明。

所以让我们开始吧:

作者图片

作者图片

作者图片

作者图片

作者图片

作者图片

这就是我们的证据!恭喜,你通过了数学考试:)

总结和最后的想法

我认为理解上面的推导对于任何数据科学、统计学或机器学习从业者来说都是一项有价值的工作。理解以上内容不仅能让你对 CLT 有所了解,更重要的是能让你理解 CLT 不支持的情况。

在本文的开头,我提到了 CLT 不适用于 n . I . I . d .柯西分布式房车。柯西分布是一种没有定义均值或方差的连续概率分布。因此,给定林德伯格-莱维【CLT】(一阶和二阶矩未定义)所需的条件,CLT 在这里不成立。如果你(读者)能想到 CLT 不成立的其他常见例子,请在评论区发表你的想法。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

简化的中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-simplified-7a0689519a46?source=collection_archive---------32-----------------------

感谢高斯所做的一切

贾瑞德·克雷格Unsplash 上拍摄

推理统计学背景中的一个重要定理,没有它,推理统计学就没有意义。它有助于假设检验、回归分析和其他分析技术。

是的,我说的是“中心极限定理”

它表明,无论总体分布如何,随着从总体中导出(替换)的样本的样本大小(n)增加,样本均值或和的分布接近正态分布。

从数值上看,从任何具有均值和标准差σ的总体分布中抽取的随机样本的均值将具有近似正态分布,均值等于σ /√n,标准差为σ/√n。

举例理解(+视觉):

假设在行星“X”上有一群男性,我们想估计他们的平均身高,我们该怎么做呢?

1.用全部人口数据计算平均值?

2.用中心极限定理用样本估计?

选择 1 是不切实际的,因为没有人拥有这样的马格努斯活动所需的时间和精力。选择 2 是,让我们看看它是如何工作的:

假设下面的分布有身高(男性)——行星 x 上的全部男性人口的数据,为什么是正常的?因为任何在偶然/随机原因下可测/可数的东西,总会遵循正态分布曲线。即使它受到可指定原因的影响(不是正态分布曲线),中心极限定理仍然成立。现在,我们举这个例子来理解这个定理的要点。测量所有男性的身高是不切实际的,我们将尝试用样本来推断总体平均值。

(图片由作者提供)

现在我们有 5 个自称的估计专家来估计不同抽样选择的平均值:

(图片由作者提供)

让我们看看谁得到的估计最准确(每个人可以得到 10 个样本):

专家 1 —练习

(图片由作者提供)

这里估算主的评论显示了对估算专家和他选择的样本量(n=2)的负面情绪。10 个估计平均值的分布也远离正态分布。现在轮到下一位专家了:

专家 2 —练习

(图片由作者提供)

这里估算主的评论显示了对估算专家和她选择的样本量(n=10)的一些积极的看法。我想我现在能够将中心极限定理的一些相关概念放入您的脑海中了——随着样本大小的增加,总体均值的估计值越来越接近实际总体均值,离散度/扩散度减小,形状复制正态分布(*样本估计均值)。据此,03 位剩余的估计专家中,哪一位将具有高置信度的总体均值的最佳估计(估计均值的低传播/分散)—

没错,就是最后一个家伙(爱因斯坦的二重身)。引入 CLT 的数值定义与同一盖伊的估计:

样本估计值的标准差均值 = σ/√n = 10/√200 = 10/14.1 = 0.7

其中σ是总体分布的标准偏差,n 是总体中派生样本的样本大小

(图片由作者提供)

估计均值分布具有近似等于实际总体均值的均值(*也称为估计均值的均值),具有非常低的散布/离差,这描绘了估计的良好置信度。

这种样本估计平均值的扩散/分散也被称为“标准误差”。

因此,一个至关重要的观点是,样本量越大,样本估计均值的分布越低,这导致估计的可信度越高。

现在对于不同的取样范围,标准误差的计算是不同的:

1.从无限总体中取样(上面已经讨论过)

2.从有限总体中抽样

3.总人口抽样

标准误差的一般公式(不考虑人口规模):

当总体标准差已知时,上述公式是适用的。当 N 接近无穷大时,我们得到上面讨论的公式(σ/√n)。当 n = N 时,标准误差为零。

现在我们已经到了这个博客的结尾,我希望通过看到一个非常规和简单的视觉练习,你已经理解了中心极限定理应用背后的基本思想。

主要的收获是“我们在推断统计学范围内所做的一切(使用总体样本进行估计),中心极限定理总是在背景中出现”。

请关注更多即将发布的博客。

谢谢!!!

用 Python 模拟中心极限定理

原文:https://towardsdatascience.com/central-limit-theorem-simulation-with-python-c80f8d3a6755?source=collection_archive---------16-----------------------

中心极限定理的 Python 仿真实验验证

来源

统计领域最重要的概念之一是什么,但它经常让有抱负的数据科学家感到困惑?没错,就是中心极限定理。

让我们深入研究数据科学中最重要的定理!

收集全部人口的数据是非常不可能的。相反,我们可以从总体中收集数据的子集,并使用该样本的统计数据来推断总体。

什么是大数定律?

大数定律 ( LLN )是一种理论,该理论指出,随着样本均值的大小增加,样本分布的均值将接近总体分布的均值。因此,大数定律可以直观地理解为收集更多的数据会产生更具代表性的样本。

什么是中心极限定理?

中心极限定理(CLT) 是一种理论,声称从重新抽样计算出的样本均值的分布将趋于正态,随着样本规模的增大,而不考虑总体分布的形状。

( 来源 )

这两种理论的区别在于,大数定律描述的是单个样本均值,而中心极限定理描述的是样本均值的分布。

样本分布中的数据必须遵循什么规则?

  1. 分布中的数据应该是随机选择的。
  2. 样本应该相互独立。
  3. 样本量应该足够大。如果总体分布很正态,30 的样本量就足够了。

为什么样本量至少要有 30 人?

有大量的书籍引用了这个值,例如,霍格和坦尼斯的概率和统计推断(7e) 说:

也就是说,当 N“足够大”时,X 约为 N(μ,σ2/n),Y 约为 N(nμ,nσ2),其中μ和σ2 分别是样本来源的基础分布的均值和方差。一般来说,如果 n 大于 25 或 30 ,这些近似值就不错了。

自然界中许多变量的分布非常接近正态曲线。查看 t 表,您会发现具有 30 个自由度的 t 的值接近 z 的值。其中一个原因是 t 分布(如正态分布)是对称和单峰的。因此,我们可以得出结论,样本量为 30 的均值样本的分布也将是正态分布。

t 表(来源)

如果总体的分布不是正态的,你可能需要尝试比 30 大得多的样本量。人口数据离对称和单峰越远,你就需要越多的数据进入 CLT。

因此,分布越接近正态分布,调用 CLT 所需的样本就越少。实际上,我从不依赖于 n = 30,并建议你尝试不同的抽样规模。

从这两个定理得出什么结论?

  1. 均值的抽样分布将是正态或接近正态的。
  2. 抽样分布的均值将等于总体的均值分布。数学上,

3.抽样分布的标准误差与原始总体的标准偏差直接相关。数学上,

4.如果我们增加从总体中抽取的样本,样本均值的标准差就会减小。

来源

CLT 的统计意义是什么?

我们有一些分布,其中的数据不是正态分布,但我们不使用这个分布,而是使用样本均值的分布。这让我们可以作弊,说我们可以在统计推断中无处不在地使用正态分布,尽管潜在的分布不是正态的。

  1. 假设检验中使用的中心极限定理。
  2. 样本平均值可用于创建一个称为的数值范围,即置信区间。这些方法假设总体是正态分布的。
  3. CLT 在一个类似的算法中使用了随机梯度下降。算法表现如何?我们从我们的训练集中抽取一批样本,并计算各批损失的平均值或总和。感谢 CLT,现在我们知道了损失估计的最终分布将是高斯分布。

让我们通过用 Python 模拟来提供中心极限定理的经验证据吧!

我们将使用一个 Kaggle 数据集和 Python 统计库,如 Numpy、Matplotlib 和 Pandas

  1. 首先,我们导入所需的库,然后使用.read_csv()读取数据集,并将其作为DataFrame对象存储在变量df中。
  2. 我们使用了.head(10)属性来浏览前 10 行数据。
  3. 我们用.info()显示了所有列及其数据类型:
  4. .shape属性需要看到它的维度。结果是一个包含行数和列数的元组。
  5. Pandas **describe()**用于查看一些基本的统计细节,如百分位数、平均值、标准差等。一个数据帧。

为了说明抽样的中心极限定理,我们将采用“CoffeeCupsPerDay”列。我们来画一个程序员喝咖啡的杯数直方图。

正如我们看到的,程序员每天喝的咖啡杯数据的分布是正偏态的,数据分布的平均值= 2.89。但是我们想要分析近似正态分布的数据。

理论上,随着每个样本大小的增加,样本均值越接近高斯分布。让我们抽取足够的不同大小的样本,并计算它们的样本均值。我们将从 300 个样本中抽取 10、40、60 和 80 个样本。计算算术平均值,并绘制 300 次样本的平均值。

所以,我们通过采取不同的样本量并逐步增加来进行试验。然后我们将不同样本量的样本均值分布可视化,比较它们的分布形态和均值。现在,我们知道随着样本量的增加,我们会得到一个非常好的钟形曲线。

从样本大小为 80 的分布形状可以看出,该分布是高斯分布。抽样分布的均值等于总体的均值分布,等于 2.89。

数学上,

我们可以观察到,随着样本大小 N →无穷大,均值的标准差趋于零。这意味着数据集的尺寸越大标准误差越小

因此,我们可以认为采样分布是正态的,所以我们可以使用这些分布进行进一步的分析。

感谢您的阅读!我希望这篇文章让你对中心极限定理有了基本的了解。如果您有任何问题,欢迎在 GmailNataliia Rastoropova上评论或给我写信。

[## 提交您的文章—清单

准备你的文章发表。(下载我们的 PDF 版本)

towardsdatascience.com](/post-for-writers-2-ebd32d1fac21) [## 数据科学统计学:中心极限定理介绍

什么是统计学中最重要和最核心的概念之一,使我们能够进行预测建模,但它…

www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2019/05/statistics-101-introduction-central-limit-theorem/) [## 机器学习的统计方法

机器学习的统计方法探索如何用 Python 将数据转化为知识我们为什么需要…

机器学习桅杆](https://machinelearningmastery.com/statistics_for_machine_learning/)

确定性大师:概率模型第 1 部分:理解模型

原文:https://towardsdatascience.com/certainty-wizards-probability-models-part-1-understanding-models-d70511603c4c?source=collection_archive---------48-----------------------

概率如何在日常生活中帮助我们?

Gabriel Manlake 在 Unsplash 上拍摄的照片

哔哔声:07:30…哔哔声:07:45…哔哔声:08:00…

ZZZzzz……!!!09:25?!只是推迟了几分钟!现在我又要迟到了…

有些事情我们无法知道。事实上,由于生活的不可预测性,我们只知道一些事情。不幸的是,不确定性是天生的,我们对此无能为力。

但是即使我们不能预测未来,我们仍然可以推测,如果我们有办法测量一个事件所有可能的结果它们发生的可能性,那么我们就可以为那个特定的事件做更好的准备。这些主题将是第一部分的主题。

所以现在重要的问题是,我今天要不要睡午觉?

好吧,原来我问自己这个问题已经有一段时间了,所以我花了一些时间记下了我每天醒来的时间:

我过去 150 天的起床时间表

在这个表中我们可以看到我在某个时间醒来的次数,除了 07:00 (指 07:30 之前的)和 09:00 (在 08:30 之后的)如果这个发生我就要迟到。我们可以看到,在 150 天里,我已经迟到了 3 天!

但是,明天我迟到的可能性有多大?

如果我们的目标是预测未来,我们就需要用我们能与之共事的方式来表达现实,用一种量化的方式。随机事件(其结果不确定)的数学化被称为概率模型。

概率模型要求:

为了能够正确地模拟一种情况,我们将需要描述可能的结果(-)按时,所有的可能性组成所谓的样本空间,并指定一个概率法则。一个概率定律(或概率函数 ) 定义了在所有可能的结果中,某个结果出现的可能性有多大。

这是通过将一个概率关联到每一个可能的事件(在这种情况下是迟到准时)来实现的。概率在这种情况下可以解释为分配给某个事件的数值,它描述了我们的信念,我们认为这个事件能够发生的可能性有多大,但是要小心!我们称之为信仰并不意味着它是主观的。******

通常这种信念是基于以前的知识,由于这一事实,我们也可以将一个事件的概率定义为 长期相对频率(当它非常大时,预期获得该事件的次数与实验次数成比例)。****

虽然这种解释在理论上是正确的,但这个定义的问题是,在某些情况下,如选举,它没有太大的意义。在这种情况下,我们不能假设候选人将永远参加竞选,因此我们不能说它的长期相对频率是多少。

样本空间

创建我们自己的模型的第一步是定义一个样本空间,明天早上我去办公室时会有什么不同的可能结果?嗯,我可以迟到或者准时或者准时所以我们可以定义一个包含那些可能结果的集合,这就是所谓的样本空间,通常用大写希腊字母 omega: 表示****

样本空间属性

在这种情况下,样本空间是微不足道的,但有时它可能很难定义。想想扔硬币两次,我们可以猜测我们可以有三个输出,两个头,头和尾或者两个尾。这是正确的,但如果我们谈论概率,我们必须跳出框框,一步一步地思考,考虑到每个小细节和我们实验的性质,在这种情况下,投掷硬币两次将有四种可能的结果:

样本空间必须始终为:

  • 互斥的:只有一种结果会发生
  • 统称穷举:它必须覆盖所有的概率空间
  • 正确粒化:不能包含无关信息

让我们看一些例子:

在这种情况下,如果我们假设 H 表示“至少有一个头”,而 T 表示“至少有一个尾巴”,那么我们的样本空间就不正确,我们可能有一些 HTTH 并且它不满足第一个必须条件,这个样本空间就不是互斥的。

这个新的样本空间不会崩溃,但这还不够。有了它我们可以得到HHHTTH ,但是我们没有覆盖的情况。该样本空间并非*全部。*******

现在想象一下,*表示“雨天”, S 表示“晴天”,利用这个样本空间,我们确实涵盖了实验的所有可能结果,而且没有任何冲突,但是我们添加的信息是不相关和不必要的(除非我们想知道天气是否会改变硬币的行为)。这个样本空间没有正确地粒化。*****

概率定律

正如我们之前已经提到的,我们可以使用我们的数据创建一个概率定律。在这种情况下,我们将从事件发生的次数除以我们做实验的次数(定义样本空间的所有元素的所有数据)来推断,假设我未来的行为(在这种情况下)不会有太大的不同。****

我们知道迟到的概率是我迟到的次数除以总次数:

现在我们明白了!假设我的行为不会有太大的改变,我会迟到大约 2%的时间,50 天中的 1 天。我真的不知道我的老板是否真的会欣赏这一点…

连续空间中的概率定律

我们不会总是有相同的概率定律,在延迟/准时的情况下,该公式工作良好,我们可以推断一些未来的行为,但在其他情况下可能不是这样。

毛罗·吉利在 Unsplash 上拍摄的照片

想象一下,你和一些朋友在酒吧里扔飞镖。你的飞镖第一次击中中心的概率是多少?我们没有以前的数据来预测你是否会错过,即使我们有,我们也只能预测你是否能击中中心(或其他定义的区域)(因为我们会记下它是在的还是在****

相反,更准确的假设是你击中任何定义的地方 B (假设中心)的概率等于它的面积除以目标面积,在这种情况下将是样本空间。**

如果没有以前的代数知识,这种情况可能有点难以理解,但不要担心,因为这只是一个例子,说明定义概率定律不仅仅是我们的长期预期**

这个问题的样本空间将由在从目标中心的半径内的目标的任何点来定义。我们可以将飞镖击中定义空间 B 的概率表示为其面积( A )除以样本空间的面积:

总结:

在第一部分中,我们已经看到了一些例子,比如什么是概率模型,它们是如何工作的,以及它们是由什么定义的。我们还看到了帮助我们以数学方式处理实验中事件发生的可能性的工具,概率,以及适当的样本空间的属性。

在下一部分,我们将讨论概率论建立的基础,即概率公理。我们还将与维恩图一起深入集合论以更好地理解这个不确定的世界。**

可证明的对抗攻击的鲁棒性;有什么意义?

原文:https://towardsdatascience.com/certifiable-robustness-to-adversarial-attacks-what-is-the-point-9152490f9c1?source=collection_archive---------60-----------------------

活动讲座

尼克·弗罗斯特| TMLS2019

在多伦多机器学习峰会上的演讲

关于演讲者

尼克·弗罗斯特是杰弗里·辛顿实验室谷歌大脑的研究工程师。他在多伦多大学获得了计算机和认知科学的学士学位。他专注于胶囊网络,对立的例子和理解表示空间。

可证明的对抗攻击的鲁棒性;有什么意义?

数据科学家直观地解释了链式规则

原文:https://towardsdatascience.com/chain-rule-explained-visually-by-the-data-scientist-67e45af61742?source=collection_archive---------37-----------------------

只需 5 分钟就能掌握链式法则的直觉,为你未来的求职面试做准备!

简介

今天我们将讨论链式法则,我希望我对这个概念的直观解释能对你有所帮助!注意,本文假设你已经熟悉了导数的基本概念,只是想更深入地理解链式法则本身。

快速衍生工具概述

也就是说,让我们先快速回顾一下导数。

想象一下,我们从一群人那里收集了这些测量数据。在 x 轴上,我们测量了他们作为数据科学家的工作量,在 y 轴上,我们测量了他们的工资。

我们现在可以用这条绿色抛物线来拟合数据。

数据点的抛物线

抛物线的方程式是

salary = (years as Data Scientist)**2

这个方程的导数告诉我们沿曲线任一点切线的斜率。然而,切线的斜率告诉我们salary相对于作为数据科学家的years变化有多快。我们可以用幂法则计算出salaryyears的导数!

具体数据点的切线

幂法则告诉我们将years乘以 2 的幂,然后将years乘以 2–1 的幂,得到下面的等式。

dSalary/dyears = 2 * years

嗯,这是一个快速回顾的衍生物:)

链式法则解释

现在让我们用一个超级简单的例子来深入研究链式法则!想象一下,我们收集了三个人的体重和身高测量值,然后对数据进行拟合。

这 3 个数据点的最佳拟合线

如果有人告诉我们他们有这么重,我们可以用绿线来预测他们有这么高。

根据体重确定身高

现在想象一下,我们收集了身高和鞋码的测量数据,并对这些数据进行了拟合。

这 3 个数据点的最佳拟合线

如果有人告诉我们他们有这么高,我们可以用橙色线来预测这是他们的鞋码!

现在,如果有人告诉我们他们有这么重,那么我们可以预测他们的身高,我们可以用预测的身高来预测鞋码,如果我们改变体重值,我们就会看到鞋码的变化!

根据重量确定鞋号

现在让我们来关注这条代表体重和身高关系的绿线。假设体重每增加一个单位,身高就会增加两个单位。

换句话说,直线的斜率是 2 除以 1,等于 2。由于斜率为 2,导数为

dHeight/dWeight = 2

因为绿线的斜率和它的导数 2 相同,所以高度的等式是

height = dHeight / DWeight * weight

注意,高度方程没有截距,因为绿线穿过原点。

现在让我们把注意力放在代表身高和鞋码关系的绿线上。

在这种情况下,假设身高每增加一个单位,鞋码就增加四分之一。按照与上述相同的逻辑,绿线的等式为

Shoe size = dSize / dHeight * height

在哪里

dSize /dHeight = 1/4

再次注意,因为绿线穿过原点,所以鞋码的等式没有截距。

因为体重可以预测身高,身高可以预测鞋码,所以我们可以把身高方程代入鞋码方程。如果我们想准确地确定鞋号如何随着体重的变化而变化,我们可以对鞋号相对于体重求导。

鞋码相对于体重的方程的导数就是这两个导数的乘积!换句话说,因为身高把体重和鞋号联系起来,所以鞋号对体重的导数是

Shoe size = dSize / dHeight * dHeigt/dWeight * weight

这种关系是链式法则的精髓。输入数字给我们一半,这意味着重量每增加一个单位,鞋码就增加一半!

结论

你可以看到链式法则里面没有什么复杂的东西,我们只是在计算一个参数如何改变其他参数!我希望这个链式法则的快速直观解释对你和你未来的职业生涯有所帮助!别忘了看看关于数学和机器学习主题的推荐书籍。

推荐书籍

使用 Scikit-Learn 进行机器实践学习

Python 机器学习简介:数据科学家指南

数据科学家实用统计:使用 R 和 Python 的 50 多个基本概念

工程师和科学家的应用数值方法

带 Scikit-Learn 的链式多输出回归解决方案

原文:https://towardsdatascience.com/chained-multi-output-regression-solution-with-scikit-learn-4f44bf9c8c5b?source=collection_archive---------27-----------------------

内部 AI

按顺序运行回归模型,以利用目标之间的相关性来预测多个因变量

作者插图——链式多输出回归

在典型的回归或分类场景中,我们有一组自变量和一个或多个因变量。有时,不可能一起预测所有因变量的值。由于目标之间的相关性,我们需要考虑序列中其他因变量的预测值来预测下一个目标值。屏住呼吸,通过本文讨论的详细解释和例子就变得清晰了。所有变量也称为特征,因变量称为目标。

为了在这种情况下使用机器学习进行预测,我们可以将序列回归模型与 Scikit-Learn 中的回归链放在一起

基于独立特征和目标变量序列中的第一因变量来训练第一模型。在训练第一个模型时,不考虑其他因变量值。

作者举例说明—基于独立特征训练数据和第一从属训练数据实际值训练第一模型

第二模型根据训练数据集中的独立特征值、第一和第二因变量值进行拟合和训练。该模型用于随后用测试数据集预测第二目标值。

作者的说明-基于独立特征训练数据、第一和第二相关训练数据实际值来训练第二模型

最后,为了预测第三因变量,基于独立特征值和所有因变量值训练最后的模型。最后一个模型将用于预测变量序列中最后一个因变量(目标)的值。

作者举例说明-根据独立特征训练数据和所有三个相关训练数据实际值训练最后一个模型

所有三个经过训练的模型将与不同的输入数据一起使用,以预测序列中的因变量值。

将独立特征测试值作为输入的第一训练模型用于根据从属特征的指定顺序来预测第一从属变量。

作者插图-测试第一个训练模型的数据集独立特征值输入

第一因变量的预测值和独立特征测试值被训练的第二模型用作输入,以预测下一因变量。

作者的说明-测试数据集独立特征值和第一目标预测值是第二训练模型的输入

前两个因变量预测值与测试独立特征值一起用作第三训练模型的输入,用于预测最后一个因变量。

作者的说明-测试数据集独立特征值和两个目标预测值是第三个训练模型的输入

步骤 1: 在 Scikit-Learn 包中, RegressorChain 在 multioutput 模块中实现。我们将使用 make_regression、math 和 NumPy 来创建测试数据。

**from sklearn.linear_model import LinearRegression
from sklearn.multioutput import RegressorChain
import math
import numpy as np
from sklearn.datasets import make_regression**

第二步:生成 20000 条记录的样本测试数据,包含 10 个独立特征和 1 个相关特征。

**X, y,coef  = make_regression(n_samples=20000, n_features=10, random_state=0, noise=4.0,coef=True, bias=200)**

步骤 3: 创建相关的第二个和第三个因变量 y2 和 y3,所有三个因变量在下面的代码中被转换成一个 2000 x 3 的数组。

**y2=(y*math.sin(45))+(math.pi/3)
y3=y*y
y= np.vstack((y,y2,y3)).T**

第四步:根据回归链中的“顺序”参数考虑连续的因变量,用于训练不同的模型。在我们的示例中,基于独立特征训练值和第二因变量值来训练第一模型。然后,独立特征值、第二和第三从属值被用作训练第二模型的输入。最后,利用独立特征测试值和所有三个因变量测试数据集值,训练第三个模型。

**reg = LinearRegression()****ChainRegression= RegressorChain(reg, order=[1,2,0])
ChainRegression.fit(X,y)****print(ChainRegression.score(X, y))**

已训练模型的准确度分数

如前所述,以独立特征测试值作为输入的第一模型预测第二相关值。那么独立特征测试值和第二从属预测值将被用作预测第三从属值的输入。最后,独立特征测试值连同第二和第三预测值被用作预测第一相关值的输入。

这样,如果我们有一个以上的目标(因变量)值,并且目标特征(因变量)以一定的顺序相关,我们就可以实现序列回归。

"Full Code"**from sklearn.linear_model import LinearRegression
from sklearn.multioutput import RegressorChain
import math
import numpy as np
from sklearn.datasets import make_regression****X, y,coef  = make_regression(n_samples=20000, n_features=10, random_state=0, noise=4.0,coef=True, bias=200)****y2=(y*math.sin(45))+(math.pi/3)
y3=y*y
y= np.vstack((y,y2,y3)).T** **reg = LinearRegression()
ChainRegression= RegressorChain(reg, order=[1,2,0])
ChainRegression.fit(X,y)****print(ChainRegression.score(X, y))**

用 Hadoop/ Java 链接多个 MapReduce 作业

原文:https://towardsdatascience.com/chaining-multiple-mapreduce-jobs-with-hadoop-java-832a326cbfa7?source=collection_archive---------5-----------------------

来源:https://mapr.com/blog/how-to-launching-mapreduce-jobs/

大约一年前,当我的工作需要一点 Hadoop 时,我简要地了解了 MapReduce。那时我还没有接触过 MapReduce,更不用说用 Java 了。因此,当一项任务要求我在一个脚本下实现多个 MapReduce 作业时,在 Stack Overflow 和 Youtube 上搜索简直是一团糟。

那么,为什么不写点什么呢?是的,我是。

概要:MapReduce

MapReduce 是一个计算抽象,可以很好地与 Hadoop 分布式文件系统(HDFS)一起工作。它包括“映射”步骤和“减少”步骤。Map 执行过滤并分类到另一组数据中,而 Reduce 执行汇总操作。在这两个步骤中,单个元素被分解成键和值对的元组。

MapReduce 因能够在后台的多个计算节点上轻松扩展数据处理而广受欢迎。因此,它可以很好地与

非常大的数据集。

多个 MapReduce 作业

为了说明如何在一个脚本中链接多个 MapReduce 作业,我将使用大约 760 万行的NYC Taxi&Limousine Commission数据集来计算位置度数差异的分布。的。我使用的 tsv 文件具有以下结构:

假设我们想使用 MapReduce 获得以下两列的输出:

其中“diff”是位置 ID 的出度减去其入度。位置的出度是该位置用于拾取的次数,入度是该位置用于放下的次数。那么,“计数”就是特定“差异”的频率。

因此,实现这一点的一种方法是拥有两个 MapReduce 作业。一个是计算每个位置的“diff ”,另一个是将第一个作业的输出转换为“count ”,就像我们上面想要的那样。

映射-减少作业#1

映射程序#1

Job #1 的 Map 过程简单地循环并中断。tsv 为每行输入 4 个不同的值:PickUpLocation ID、DropOffLocation ID、PassengerCount 和 TotalFare。但是,这里只有 PickUpLocation ID 和 DropOffLocation ID 与我们的任务相关。然后,对于每个元素,该类还创建一个为 1 的 inDegree 变量和一个为-1 的 outDegree 变量。

然后,它将每个(PickUpLocation,inDegree)和(DropOffLocation,outDegree)写入一个键值元组,该元组将由 Reduce 过程进一步处理,该过程采用如下形式,其中第一列是位置 ID,第二列指示它是从每个位置 ID 拾取还是放下。

简化程序#1

然后,Reduce 过程所做的只是按位置 ID 进行分组,并通过对第二列求和来实现“diff”。然后,它将(Location ID,diff)作为键值元组写入。

输出采用以下形式:

MAP-REDUCE 作业#2

然后,作业#1 的输出作为作业#2 的输入传入。

映射程序#2

为了按“diff”分组以获得最终输出,Job 2 的 Map 过程需要将输入键值对(Location ID,diff)交换到(diff,Location ID)中,因为 Reduce 过程按键分组。

实际上,这次 Map 过程的输出如下所示:

最后,将它传递给第二个 Reduce 过程来完成任务:

简化程序#2

这里发生的事情是,Reduce 过程简单地遍历输入,并且对于唯一的“diff”的每一次出现,它的计数增加 1。在循环结束时,它将(diff,count)作为键值对写入最终输出文件:

连锁作业#1 &作业#2

我发现的具有挑战性的步骤是连接上述两个 MapReduce 作业,这样作业#2 可以将作业#1 的输出作为输入,而不需要作业#1 实际写出一个文件。

链接步骤

我不得不在网上寻找和尝试多种建议,直到我找到最容易理解的组合。

基本上,关键是为这两个作业创建两个不同的配置,即“conf”和“conf2 ”,它们也获得两个不同的实例。

*Configuration* conf = **new** Configuration();
*Job* job1 = Job.getInstance(conf, "degree");*Configuration* conf2 = **new** Configuration();
*Job* job2 = Job.getInstance(conf2, "frequency");

然后,作业#2 只能在作业#1 完成时执行

job1.waitForCompletion(true);

但是请注意,系统并没有在这里终止。然后,作业#1 的输出与作业#2 的输入相同:

FileOutputFormat.setOutputPath(job1, **new** Path(args[1]));FileInputFormat.addInputPath(job2, **new** Path(args[1]));

仅此而已。使用这种技术,您不仅仅局限于两个 MapReduce 作业,还可以增加到三个、五个甚至十个来适应您的任务。

我希望这篇简短的笔记可以帮助那些正在努力寻找一个关于链接 MapReduce 作业的全面且易于理解的指南的人。

在 BigQuery 中链接多个 SQL 查询

原文:https://towardsdatascience.com/chaining-multiple-sql-queries-in-bigquery-8498d8885da5?source=collection_archive---------15-----------------------

在 BigQuery 中依次执行多个查询

Dakub ,Souce Pixabay

Bigquery 是一个非常棒的工具!它可以让你使用类似 SQL 的语法进行非常强大的分析工作。

但是它缺少对 SQL 查询的链接。我们不能在一个 SQL 完成后立即运行另一个。在许多实际应用中,一个查询的输出依赖于另一个查询的执行。我们希望运行多个查询来获得结果。

这里有一个场景,假设您正在使用 BigQuery ML 进行 RFM 分析。首先,您必须计算所有用户的 RFM 值,然后将 k-means 聚类应用于第一个查询的结果,然后合并第一个查询和第二个查询的输出,以生成最终的数据表。

在上面的场景中,每个下一个查询都依赖于前一个查询的输出,并且每个查询的输出也需要存储在数据中以供其他用途。

在本指南中,我将展示如何在 BigQuery 中一个接一个地执行尽可能多的 SQL 查询,创建一个链接效果来获得想要的结果。

方法

我将演示链接查询的两种方法

  1. 第一种使用云发布/订阅和云函数:这是一种更复杂的方法,因为它确保在执行下一个查询之前完成当前查询的执行。这种方法也需要一点编程经验,所以最好联系公司里有技术背景的人。
  2. 第二种使用 BigQuery 自己的调度器:然而,查询调度器不能确保一个查询的执行在下一个查询被触发之前完成,所以我们必须使用查询执行时间来破解它。稍后将详细介绍。

如果你想弄脏自己的手,那么 这里有一个极好的课程 可以开始。

注意:我们将继续上面讨论的 RFM 的例子,让你了解这个过程。但是这同样适用于任何需要触发多个 SQL 查询的场景。

方法 1

方法 1 使用云功能和发布/订阅的组合来链接整个流程。该过程由查询调度器开始,该查询调度器在执行第一个查询之后向发布/订阅主题发送消息,该消息触发负责触发第二个查询的云功能,并且一旦完成,就向另一个发布/订阅主题发送消息,以启动另一个云功能。这个过程一直持续到云函数执行最后一个查询。

让我们通过 RFM 分析用例来理解这个过程。

假设我们有三个需要依次运行的查询来执行 RFM 分析。
首先是 ,这样计算出的 RFM 值,我们就称之为 *RFM Values* 第二个 ,这就产生了模型,我们就称之为 *RFM Model* 第三个 ,即将模型输出与用户 RFM 值合并,我们称之为 *RFM Final*

下面是数据管道的样子:

通过 Muffaddal 在 BigQuery 数据管道中链接查询

注意 : 我假设已经为所有三个查询创建了表。

1-我们首先创建一个发布/订阅主题,因为在创建*RFM Values*查询调度器时会用到它。我将它命名为RFM_Model_Topic,因为它将触发负责执行我们的模型查询的云函数(即*RFM Model*)。

RFM _ 模型_Topic发布/订阅主题,作者 Muffaddal

复制创建 *RFM Values* schedular 时需要的主题名称。

2-接下来,转到 BigQuery,在查询编辑器中粘贴为我们的用户计算 RFM 值的*RFM Values*查询,然后单击“Schedule query”按钮创建一个新的查询调度器。

通过 Muffaddal 创建计划查询

3-在调度程序创建菜单中输入所需的值,以创建调度程序

查询日程创建菜单,按 Muffaddal

这个调度程序将在指定的时间执行,计算用户的最近次数、频率和货币值,并将其存储在上述 BigQuery 表中。一旦调度完成执行查询,它将向我们的RFM_Model_Topic发送一条消息,这将触发一个云函数来触发我们的模型查询。接下来让我们创建一个云函数。

4-进入RFM_Model_Topic发布/订阅主题,点击屏幕顶部的“触发云功能”按钮。

由 Muffaddal 从发布/订阅主题创建云函数

5-进入如下所示的设置,并将云功能命名为RFM_Model_Function

云功能设置,由 Muffaddal

6-并将下面的代码粘贴到index.js 文件中

由 Muffaddal 触发 RFM 模型查询的云函数

一旦查询被执行,云函数向名为RFM_Final的新发布/订阅主题发送发布消息,这触发了负责将 RFM 值和模型结果组合在一个数据集中的最后查询的云函数。

7-因此,接下来,在发布/订阅中创建RFM_Model主题和一个云函数,就像我们在上一步中做的那样。将下面的代码复制粘贴到云函数中,这样它就可以运行最后一个查询。

触发 RFM 最终查询的云函数

就是这样!

我们可以使用任意多的发布/订阅和云函数来链接任意多的 SQL 查询。

方法 2

现在第一种方法是健壮的,但是需要一点编程背景,并且说这不是你的强项。您可以使用方法 2 来链接 BigQuery 查询。

BigQuery 的查询调度器可以用来一个接一个地运行查询。

想法是我们像方法 1 一样开始这个过程,即使用调度程序触发第一个查询,并估计它的完成时间。假设第一个查询需要 5 分钟来完成。我们要做的是在第一个查询开始时间后 10 分钟触发第二个查询。这样,我们可以确保第二个查询在第一个查询完全执行后被触发。

让我们通过例子来理解这一点

使用查询调度器的链式查询,由 Muffaddal

假设我们将第一次查询安排在凌晨 12:30。需要 10 分钟才能完成。因此我们知道在凌晨 12:40 第一个查询应该完成。我们将第二个查询调度器设置为在 12:50 am 执行(为了以防万一,在两个调度器之间保持 10 分钟的间隔)。我们将在凌晨 1:10 触发第三次查询,依此类推。

方法 2 也可以与方法 1 结合使用。这意味着我们使用云函数来触发查询调度程序。这样做还有一个额外的好处,那就是您不必遇到云函数的执行时间限制,并且您的查询可以执行所需的时间。
PS:由
西蒙汤姆森 建议用云功能触发按需查询调度器。

注意:由于查询调度器不能与 BigQuery ML 一起工作,因此,方法 2 不能用于我们的 RFM 分析案例,但是它应该让您了解如何使用调度器来链接查询。

其他方法

如果你能处理更复杂的管道塞巴斯蒂安·莫兰提出了另外两种方法供你使用。

总结

一个接一个地执行查询有助于获得非常好的结果,特别是当一个查询的结果依赖于另一个查询的输出,并且所有的查询结果都需要表格格式时。开箱即用的 BigQuery 不支持这一功能,但使用 GCP 的组件,我们可以简化流程以获得结果。

在本文中,我们通过两种方法做到了这一点。首先使用 cloud pub/sub 和 cloud 函数,另一个使用 BigQuery 自己的查询调度器。

通过这篇文章,我希望我能够向您传达这个过程的想法,以便您能够根据您的特定业务案例来选择和定制它。

阅读关于 BigQuery 的更多信息:

[## 使用 BigQuery ML 进行 RFM 分析

使用 BigQuery ML 中的 RFM 分析和 Data Studio 中的可视化进行用户细分。

towardsdatascience.com](/rfm-analysis-using-bigquery-ml-bfaa51b83086) [## 向 BigQuery 发送标准的 Google Analytics 点击量数据

如何发送标准的谷歌分析点击量数据到 BigQuery?

towardsdatascience.com](/send-google-analytics-hit-level-data-to-bigquery-5093e2db481b) [## 自动将数据导入 Google Analytics。

建立一个数据管道,使用 Google Cloud Platfrom 将数据导入 google analytics。

towardsdatascience.com](/automate-data-import-to-google-analytics-471de2c3fc76)

将机器学习模型部署到生产中的挑战

原文:https://towardsdatascience.com/challenges-deploying-machine-learning-models-to-production-ded3f9009cb3?source=collection_archive---------18-----------------------

MLOps:用于机器学习的 DevOps

目录

传统软件开发 vs 机器学习
机器学习工作流程
阶段#1:数据管理- 大数据量

机器学习(ML) 世界的一个众所周知的事实是,将 ML 模型部署到生产中比开发它需要更长的时间。根据著名论文“机器学习系统中隐藏的技术债务”:

“只有一小部分真实世界的 ML 系统由 ML 代码组成,如中间的小黑框所示(见下图)。所需的周边基础设施庞大而复杂。”

图表#1: 摘自论文 机器学习系统中隐藏的技术债务

传统软件开发与机器学习

如果你把传统的软件开发和机器学习放在一起考虑,你可以在下面的图 2 中清楚地看到后者的分歧。即使是这样,传统软件开发的大多数原则和实践都可以应用于机器学习,但是有一些独特的 ML 特定挑战需要以不同的方式处理。在本文中,我们将讨论那些使 ML 模型难以部署到生产中的独特挑战。

图表#2: 传统软件开发 vs 机器学习

机器学习工作流

典型的 ML 工作流程包括数据管理、实验和生产部署,如下图所示。

图 3: 机器学习工作流程

我们将了解下面的每个阶段,以及团队在每个阶段面临的特定挑战。

阶段#1:数据管理

训练数据是决定模型性能的基本因素之一。这一阶段通常包括数据采集和准备。使用 ML 数据时,您需要注意以下挑战:

大数据量:模型在训练过程中通常需要大数据集,以提高其对实时数据进行预测的准确性。数据集可能高达数百千兆字节,甚至更大。这带来了一些独特的挑战,如移动数据不容易,数据传输通常成本高昂且耗时。

高质量数据:如果数据质量不好,拥有一个大的数据集是没有用的。找到高质量的正确数据对于模型的准确性非常重要。从正确的来源获取数据并进行足够的验证以确保高质量有助于解决问题。确保你的模型没有基于种族、性别、年龄、收入群体等方面的偏见。也很关键。为此,你需要确保你的数据有模型偏差和公平性验证。

数据集跟踪:复制模型的训练方式对数据科学家很有帮助。为此,需要对每次训练运行中使用的数据集进行版本控制和跟踪。这也让数据科学家能够灵活地回到数据集的先前版本并对其进行分析。

位置:根据使用情况,这些数据集位于不同的位置,如上所述,它们可能会更大。由于这些原因,在更接近数据位置的地方运行训练和某些情况下的预测可能是有意义的,而不是跨位置传输大型数据集。

注意:确保这是值得努力的。如果你能在不增加复杂性的情况下进行管理,并集中运行,我会推荐你这样做。

安全性&合规性:在某些情况下,所使用的数据可能是敏感的,或者需要满足某些合规性标准(如 HIPAA、PCI 或 GDPR)。当你支持 ML 系统时,你需要记住这一点。

第二阶段:实验

这一阶段包括模型开发,数据科学家将大量时间用于研究各种架构,以了解哪些架构符合他们的需求。例如,对于语义分割,这里有各种可用的架构。数据科学家编写代码来使用前一阶段的数据,并使用这些数据来训练模型,然后进行评估,以查看它是否符合他们所寻求的准确性标准。请参见下面您将在此阶段面临的一些挑战。

持续的研究和实验工作流程:他们花时间收集/生成数据,进行实验,尝试各种架构,看看什么适合他们的用例。他们还尝试超参数优化和用各种数据集进行训练,看看什么能给出更准确的结果。

由于其研究和实验性质,需要支持的工作流不同于传统的软件开发。

跟踪实验:该工作流程的一个关键方面是允许数据科学家跟踪实验,并了解各次运行之间发生了什么变化。他们应该能够轻松地跟踪不同实验之间的数据集、架构、代码和超参数变化。

代码质量:由于研究和实验阶段的原因,许多编写的代码通常质量不高,不能用于生产。数据科学家花费大量时间使用像 Jupyter Notebook 这样的工具,并在那里直接进行修改以进行测试。您需要记住这一点,并在将 ML 模型部署到生产之前处理它。

训练时间&故障排除:训练一个模型通常需要几个小时甚至几天的运行时间,并且需要特殊的基础设施(参见下面的挑战 4)。例如,根据他们的网站,一个完整的特斯拉自动驾驶神经网络需要 70,000 个 GPU 小时来训练。由于培训通常需要大量时间,您需要能够在培训过程中使用监控、日志记录、警报和验证等方面来支持简单的故障排除。如果培训过程出错,提供简单的方法来解决问题,并继续/重新开始培训非常重要。

模型精度评估:训练完成后,需要对模型精度进行评估,看是否满足生产中预测所需的标准。如上面的图 3 所示,您通过训练/数据管理步骤不断提高准确度,直到达到可接受的数字。

再培训:当您遇到数据漂移,生产中的错误,或者需求变更时,您可能需要对模型进行再培训。需要有一种方法来支持再培训模型。

基础架构需求: ML 工作负载有某些特殊的基础架构需求,如GPU&高密度内核。数千个处理核心在一个 GPU 中同时运行,这使得训练和预测的运行速度比仅使用 CPU 要快得多。由于这些基础设施需求(尤其是 GPU)成本高昂,并且大多是周期性突发培训所需,因此支持弹性和自动化扩展以及供应/取消供应基础设施(尤其是在使用云时)是一个好主意。

如今,像 Nvidia Jetson 系列这样的边缘设备(物联网、移动设备等)越来越多地被使用,部署到这些设备是另一个挑战,因为这些设备大多使用 ARM 架构,而不是资源有限的 x86 。需要在这些设备上测试模型的准确性和性能。

由于缺乏对 ARM 架构的某些依赖项及其最新版本的支持,围绕构建包/模型的良好实践会有所帮助。

阶段#3:生产部署

在模型经过训练并达到一定的准确性后,它将被部署到生产中,开始根据实时数据进行预测。以下是此阶段需要注意的一些挑战。

离线/在线预测:根据模型及其在生产中使用实时数据的方式,您可能需要支持离线(批量)预测或在线(实时)预测。您需要一个合适的框架来为基于类型(批处理或实时)的模型提供服务。如果是批处理预测,请确保您可以适当地实时调度批处理作业,您需要担心处理时间,因为结果通常需要同步返回。

模型退化:由于数据漂移、环境变化等各种因素,模型在生产中退化(即预测变得不准确)。久而久之。让团队能够随时获得解决问题所需的信息是很重要的,这样他们才能采取行动。

结论

DevOps 原则和实践包括所有三个方面(人员、流程和技术),已被有效地用于缓解传统软件的挑战。这些相同的 DevOps 原则和实践以及一些机器学习特定实践可以用于成功部署和操作 ML 系统。这些人工智能原则和实践也被称为机器学习的 MLOpsdevo PS。我将撰写后续文章,探讨那些有助于克服本文中提到的挑战的原则和实践。

鸣谢: Priyanka Rao 和 Bobby Wagner 阅读了本文的草稿版本,并提供了反馈来改进它。

同时发布在 我的网站

自然语言处理(NLP)中开发多语言语言模型的挑战

原文:https://towardsdatascience.com/challenges-in-developing-multilingual-language-models-in-natural-language-processing-nlp-f3b2bed64739?source=collection_archive---------32-----------------------

意见

图片来自 Lexalytics

为企业客户和品牌开发 NLP 解决方案的一个标志是,这些客户通常服务于语言不同的消费者。虽然我们的大多数客户都在运营以英语为主要消费群的 VoC(客户之声)、社交倾听和市场研究项目,但我们确实有一些客户服务于 20 多种语言的消费者,而且许多客户在北欧国家、拉丁美洲和亚太地区有大量业务,更不用说欧洲的其他地区了。

其他语言的 NLP 面临的挑战是英语是互联网的语言,说英语的用户比下一个最流行的语言普通话多近 3 亿。现代的 NLP 需要大量的文本— 16GB 到 160GB,具体取决于所讨论的算法(800 万到 8000 万页的打印文本)—由许多不同的作者在许多不同的领域编写。然后需要收集、清理这些不同的文本,并将其放入数据科学家可以访问的广泛可用的、适当注释的语料库中。最后,至少有一个由深度学习专业人士或爱好者组成的小型社区必须执行这项工作,并提供这些工具。拥有更大、更干净、更容易获得的资源的语言将会看到更高质量的人工智能系统,这将在未来产生真正的经济影响。

结果是一个语言支持的分层系统,如下所示:

  1. 尖端型号通常首先支持英语,有时支持普通话。
  2. 这些数据发布一段时间后,拥有许多数据科学家和语言学家的大国在本土复制了这些工作。这些国家包括德国、法国和俄罗斯。
  3. 对于接下来的大约 100 种最流行的语言,通常会生成单一的多语言模型,以便一次为整个集合生成 ok 结果
  4. 对于世界上的其他人来说:人工智能不理解它,这阻止了扬声器从这些新技术中受益。

NER 的准确性和情绪分析

业界解决多语言建模挑战的一种方法是将目标语言翻译成英语,然后执行各种 NLP 任务。如果你辛辛苦苦地用英语制作了一个情感语料库,很容易把所有东西都翻译成英语,而不是用其他语言重复这个任务。

然而,确定情感是翻译创造性过程的一部分。理解“五十步笑百步”是在表达否定,然后想出用另一种语言表达这一想法的相应方式,需要理解两种语言中的情感。我们也使用在其他语言中没有直接对应的文化速记和惯例。翻译一个单词通常有多种选择。西班牙语中的“pequeñ”是“little”吗?还是“微不足道”?还是“矮小”?或者甚至是“可爱”?

如果你的模型足够好,能够在翻译时捕捉到细微差别,那么它们也足够好,能够执行最初的任务。但更有可能的是,他们不能捕捉细微差别,你的翻译将不会反映原始文件的情绪。事实性的任务,比如回答问题,更适合翻译。需要更多细微差别的主题(预测模型、情感、情绪检测、总结)在外语中更容易失败。

多语言自然语言处理的未来

为了追求最高的准确性,非英语语言很少被训练。开源世界中一个有希望的解决方案是 Google 的 BERT,它提供了一种英语和一个适用于大约 100 种其他语言的“多语言模型”。人们现在为其他语言提供了经过训练的 BERT 模型,并看到了有意义的改进(例如,NER 的 F1 为 0.928 比 0.906)。然而,在我们自己的工作中,例如,我们已经看到通过 BERT 处理英文医学文本的效果明显好于日文。很可能在日文版的 BERT 中没有足够的关于特殊领域的内容,但是我们希望随着时间的推移会有所改善。

创建和维护自然语言特性是一项繁重的工作,而且必须在新的母语人士的帮助下一遍又一遍地重复这项工作,这是一项令人生畏的任务。专注于几门特别重要的语言,让它们为世界说话,这很有诱惑力。然而,世界并不是同质的。一家公司在各个国家可能会有特定的问题和机会,讲不太通用语言的人不太可能通过任何渠道听到他们的声音,而不仅仅是数字渠道。

因此,尽可能仔细地倾听他们所服务的每一种语言符合企业的利益,也符合大学、政府和公民科学家的利益,有助于创建文本语料库和模型,以促进他们的语言同胞在现在和未来获得尖端技术。

数据科学在人才和业务方面的挑战

原文:https://towardsdatascience.com/challenges-of-data-science-in-talent-and-in-business-5a75beda8ad7?source=collection_archive---------25-----------------------

商业管理视角

作者:@ adamantios . koumpis@ kyrcha—2020 年 1 月

照片由蒂姆·莫斯霍尔德Unsplash 上拍摄

介绍

迈向数据科学的一篇文章中,Haebichan Jung 讨论了我们通常如何高估硬技能的作用,例如在求职面试过程中的数据科学项目,并阐述了真正重要的“软”技能。然而,众所周知,找到一份工作是一件(非常重要的)事情,而在工作中茁壮成长是完全不同的,有时要困难得多。

在科学领域,很多时候,一个好的研究问题比它的答案更重要。答案可能(而且通常)是错误的——而一个问题,即使看起来很天真,有时也要等上几年才能得到一个好的或正确的答案。Quora 上引发我们兴趣的问题是:“你见过数据科学家被解雇吗?如果是,为什么?”。下面,我们借此机会与你分享一些想法,这些想法是我们在阅读它时,尤其是在我们阅读它得到的最高投票答案时开始形成的。

顶级答案以一个意想不到的高潮开始——考虑到我们对文学的业余爱好——我们可能敢与史诗小说中的几个伟大的开头段落相比较也就是这里的这个:“我实际上在工作了大约 6 个月后就要被解雇了。”。因此,对我们两人来说,这似乎是一个令人兴奋的好巧合的开始:找到一个值得问的问题,由某个人回答,他提供了自己在这个问题上的痛苦经历。

被告提出了他们即将被解雇的以下原因(注意,我们使用的所有摘录都以斜体显示,并且都来自 Quora 答案 ) :

“机器学习并不完全适用于被大肆宣传的每个行业。今天的想法是,你把一堆特征扔进一个模型,模型会以 95%的准确率进行预测。事实是这样的。

  • 大多数公司和行业还没有为并购做好准备。他们没有合适的功能集,无法访问合适的功能集,甚至不知道哪些功能驱动着他们的市场。
  • ML 被视为可以解决任何问题的灵丹妙药,这是完全不正确的。如果你的特征空间在某种程度上与目标变量不相关,那么任何模型都不会有任何有意义的预测能力。例如,有一个特征,如有多少超过 50 岁的总统赢得了第二个任期的选举,将无助于预测谁将在 2020 年获胜。我这样说的原因是因为这些是最可用的、相关的、但并不真正驱动模型的特性类型。
  • 公司想抛给 ML 的问题,通常大多都不是容易的问题。它们通常是我们所说的空中楼阁问题,比如预测股票市场。

上面描述的是一个行业努力跟上新技术的情况,发现自己处于早期采用者的角色,正如著名的罗杰斯的钟形曲线所示。另一方面,没有人会将机器学习(ML)的使用描述为当今的创新。20 世纪 90 年代使用 ML 的尝试可能被认为是这样的——但即使在那个时候也仍然有一些先前的尝试。

我们的目的是而不是解构 Quora 回答者提出的论点——恰恰相反——我们想为这种情况提供可能的解释,这种情况无疑可能面临严重的改善。

参数编号 1:责怪公司(和他们的特点)

【m】大部分公司和行业还没有做好 ML 的准备。他们没有合适的功能集,也无法获得合适的功能集,甚至不知道哪些功能驱动着他们的市场。

当然,一些公司所在的商业领域可能需要更多的 ML 应用程序和更密集的 ML 使用——但这是有待证明的。如果一家公司是数据密集型或数据贪婪型的,产生大量数据,并让员工利用这些数据(特征)做出决策(标签),那么这家公司可能会成为 ML 的良好候选公司。

然而,我们明白上面的意思和许多拜访安康会议或曼陀罗-泰式按摩、使用心理分析师的服务或在教堂参加弥撒的人一样:他们都被一些他们试图满足的内在(深奥的)需求所驱使。对于人类来说,这是一个很好理解的案例,它通常会带给我们新知识的发现,并帮助我们创新,因此我们没有理由指责公司根本不是“正确的类型”。

当然,公司也有责任——仅举几例:

  • 他们不关心或不考虑他们是否真的有能力支持他们。即使是一些简单的数据存储费用、思维计算费用、云成本也可能导致初创公司走向死亡螺旋(例如,查看这篇关于培训最先进模型的成本的文章)。我们已经看到中小企业希望进行机器学习(和其他炒作的术语),但一旦他们开始计算数据和计算的云成本,他们就会削减。在这里你可以找到乔尔测试的第 9 步:更好编码的 12 个步骤:“你使用了金钱能买到的最好的工具吗?”
  • 没有线索将个人贡献者与业务联系起来——我们需要一个能说两种语言的人,并弥合(许多)沟通差距。
  • 他们(还)看不到硬技能之外的技能,因此无法判断谁是个人贡献者,谁是领导者,谁是产品经理,等等。再看这个帖子

参数编号 2:神奇的子弹

ML 被看做是可以解决任何事情的灵丹妙药,这根本不成立。如果你的特征空间在某种程度上与目标变量不相关,那么任何模型都不会有任何有意义的预测能力。例如,有一个特征,如有多少超过 50 岁的总统赢得了第二个任期的选举,将无助于预测谁将在 2020 年获胜。我之所以这么说,是因为这些是最常见的功能类型,它们相互关联,但并不真正驱动模型。

所以想象一下,一个虚构的爬虫发现了以前从未被考虑过的信息:例如,假设所有的总统小时候都有一只汤姆猫,他们都叫它鲍勃。因此,这可能是我们希望考虑的一个特征,特别是如果下次选举也有一个或多个候选人具有相同的特征。

我们认为,作为一名数据科学家,人们应该更担心模型本身的意义,然后是它们的预测能力。我们将在这里打一个比方:我们不愿意想象政治家们仅仅因为想象他们自己在大约 20 年后举行一次演讲来庆祝他们做出了一个多么好的决定而做出决定。我们也不认为阿尔伯特·爱因斯坦在瑞士伯尔尼专利局工作时在笔记本上写下了他的方程,想到了几年后他将在瑞典面临的诺贝尔奖颁奖仪式,并幻想着他将在那里举行的演讲。(顺便说一句:由于在远东旅行,爱因斯坦根本无法出席斯德哥尔摩颁奖典礼并亲自接受诺贝尔奖……)。

所以,公司的目标主要是与业务相关的,而技术只是达到这一目的的手段。公司可能会也可能不会收集大量与其业务相关的数据,可能会也可能不会将这些数据与“外面”发生的其他事件联系起来。他们在预测未来或改善自身业务方面有多成功取决于很多参数。我们看到了对他们预测未来和提出杀手级应用或产品的需求。商业中的每一次失败都被准备或预见为可能或潜在的成功——这是毫无疑问的。有时候,公司和人一样,会被蒙蔽,只看到现实的一面。但正是因为这种片面性,他们有时也会在业务上取得成功。我们可以想象总统候选人的两只手政治顾问建议他们的客户不要竞选总统,因为他们小时候没有一只叫鲍勃的汤姆猫。这不是科学,而是神秘学。在企业决策实践中,人工智能并不是支撑新黑暗时代至高无上地位的支柱,在新黑暗时代,专门研究数据的女巫在她们的坩埚中准备人工智能支持的魔药,寻求预见未来。

因此,总结一下:我们希望公司投资收集与其业务和整个市场相关的所有信息,慷慨投资于建模练习,这些练习可能会失败,但也可能会成功——有时需要足够长的视野才能获得好的结果。所以是 不是 关于收集相关特征 不是 关于预测未来。主要是关于 理解业务 并能够 解释业务 以及可能一点点我们的世界。如果 ML 能帮助我们做到这一点,我们将很乐意把它作为一种工具来使用。

参数编号 3:天上的苹果馅饼

Quora 回答者提供的第三个论据让我们相信,大多数公司和行业还没有为并购做好准备:

大多数公司想扔给 ML 的问题通常都不是容易的问题。他们通常是我们所说的空中楼阁问题,比如预测股市。

毫无疑问,很少有人敢于仅仅为了讨论癌症治疗方案的而去看肿瘤学专家。通常,人们在他们自己的生活或他们的一些亲戚的生活中的一个非常戏剧性的时刻被送到这样一个专家那里。他们对这样的专家的要求是为他们提供最好的治疗【此时此地】。他们可能不知道个性化或精准医疗这样的术语,所以他们不会在乎得到与特定专家之前十个或上百个患者相同的治疗,只要它有效,他们就能得到治愈,并能够享受回归正常生活。

当然,在完全没有希望的时候,总有向人推销蛇油或者希望的空间。但是我们不认为公司会愚蠢到产生各种错误的期望不是关于他们使用的技术而是关于他们想要得到的解决问题的答案

我们非常理解为什么 Quora 的回答者将一些问题命名为“天上掉馅饼”。另一方面,我们看不出人们有什么理由不要求更多:预测股市不是一个不合理的目标。这可能是很难提供的东西,就像告诉人们他们什么时候会死,或者更好的是,告诉他们他们将会死,同时也给他们一些治疗以避免死亡。

因此,即使这很难或不可能,公司——和人一样——作为信息技术的消费者,也有充分的理由要求不可能的事情(同时也补偿不可能的事情)。通常我们现在认为不可能的事情在未来可能会改变。一些不可能的事情已经被科学和技术成功地解决了——而其他一些问题仍然无法解决,尽管一个成功的答案似乎离我们只有很短的时间了…

程序中的错误

遗憾的是,故事的起点是有人被解雇了。但是让我们看看每一个项目任务,并试着理解哪里出错了。Quora 回答者抱怨说他:

已经工作了 6 个月,给了我几个 ML 项目,但最终都无法解决。lol。这是因为他们希望我解决的每一个问题都是“天上掉馅饼”的问题。'

我们理解这种感觉,也曾数次面对这种感觉——这肯定会打击你的士气。大学教育人们获得学位——所以他们通过认证程序,在那里最有才华的人或那些准备更充分的人获得最好的分数(查看保罗·格拉厄姆的文章“要忘却的教训”对这一问题的阐述),但在现实世界中,正如梅尔·布鲁克斯在他的歌曲“希望最好的(期待最坏的)”中所写的,“世界是一个舞台,我们是未经训练的”。

所以 Quora 回答者的第一个项目是:

‘逆向工程一家著名科技公司的算法,智取他们的算法,本质上是游戏系统。这从一开始就注定要失败。请注意,这是一家著名的公司,使用这种算法带来了数百万+的利润。重点是用我的 ML 努力战胜这个算法,这样我们就不用付给这家公司那么多钱了。我应该找到一个有预测能力的 ML 循环孔。或者更好的是,这家财富 500 强公司是如此愚蠢,任何人都可以破解他们的算法!是啊没错。最终,由于随机猜测的预测能力,这个项目失败了。

我们都可以猜测这个算法是 GAANG 还是 FAAGM 或者类似的算法。人们也可以很好地想象将这项任务分配给某人的人的期望。他们设想,通过雇用这个人,他们进入了数据科学的高速公路,这是所有演示和文章都在宣传的东西,在这里,小大卫们拿着 DIY 弹弓可能会竞争并击败巨人。这个愿景没有错。作为一家公司的员工,任何人的任务都应该是将愿景分成许多更小的部分(这正是 Haebichan Jung 在他的文章《T4 的分析思维》中的意思),并尝试每天或每周取得进展,这些进展也可以向雇主报告和传达,这样他们 a)就不会认为自己什么都不做,b)对所做的每个决定都有争论,因为正如埃里克·梅耶尔在他的“黑客之路”演讲中所说的那样,“代码赢得争论”这种交流可能提供获得反馈的机会。也许把愿景分割成更小实体的方式是错误的。也许有一个人已经迷路了,需要一些帮助或更详细的指导。

第二个项目是类似上述的另一个问题,但这次试图以某种方式预测公司的未来。这是部分成功的。

在某些情况下,成功是随机的。另一方面,对于这个(部分)成功的案例,最重要的结果不是模型本身的准确性,而是逆向工程的过程,并找到为什么第一个问题(和第三个问题,我们将在后面看到)是失败的原因,而第二个问题,根据 Quora 回答者的说法,与第一个问题相似,是成功的。从长远来看,这样的反馈循环(或回顾)是非常重要的一步。此外,根据 John Kotter 的领导变革的八步流程,创造和传达短期成功也是领导和推动组织变革的步骤之一,在这种情况下,是为了实现 ML。

最后但同样重要的是,第三个项目是关于:

在站点级别预测公司利润。你已经可以看到这将走向何方。这家公司在全国有 1000 多个站点,类似于零售连锁店。我应该想出一个捕捉行为的模型来预测每个网站在网站级别的利润!我们实际上能够得到大量的人口统计数据来解释这一点。例如,你可能会认为你需要的只是人口、工作等特征,以了解这将如何推动市场。同样,这就像试图预测股票市场,因为普通的人口普查数据本身并不能推动利润。我们有我们能想到的每一个特征,但一个具有一系列特征的单一模型仍然无法令人信服地捕捉到纽约与莫德斯托的行为,因为归根结底,这不仅仅是关于就业增长或生活在那里的人,还有其他隐藏的社会经济变量,我们无法捕捉或无法获得,甚至不知道。“这个模型实际上产生了合理的预测能力,但他们想要 90%以上的准确率,所以这个项目被认为是失败的。”

根据我们自己在教授学生数据科学入门课程和(一点点)高级课程时获得的个人经验,学生们被训练使用一些工具和/或编程语言,并完成不是很复杂的作业,而且在任何情况下都无法与某人在现实生活中面临的作业相比。我们承认,现实生活中的一个额外困难是,人们通常会对自己的期望设定很高的标准。因此,虽然学生在课堂上被教育像小学生一样处理初等算术问题,但在现实生活中,他们需要适应高中或大学代数的需要和要求,而有时客户或他们的老板要求他们达到与顶级大学教授相当的水平。Haebichan Jung 的文章再次提供了如何应对这种情况的答案,名为分析思维:将问题分解成子问题,与其他人讨论,并试图建立一个稳定的知识基础。这是公司的真正资产,这是人们应该做出贡献的地方,而不是展示脆弱准确性的系统。

通过阅读其他类似的故事,我们产生了一种担忧,即雇主可能会普遍妖魔化 ML,因为他们未能描绘出 ML 对于当今公司的未知领域。来自雇主或顾客的期望的主要问题是来自销售者或雇员的过度承诺。一个苦涩的事实是,许多数据科学家出售的是他们的项目,而不是他们解决问题的经验,因为这可能是公司和招聘经理想要听到的。

在结束这篇评论时,我们将引用前 UFC 冠军康纳·麦格雷戈的教练约翰·卡瓦纳的名言“要么赢,要么学”——这幸运地适用于数据科学家和作为员工的 ML 专家,以及计划开始他们的第一个或下一个 ML 项目的雇主。

挑战作为分析师的利益相关者

原文:https://towardsdatascience.com/challenging-the-stakeholder-as-an-analyst-e8ce0dc92ea5?source=collection_archive---------28-----------------------

(来源: Pixabay )

办公时间

为什么分析师不应该盲目地回答摆在他们办公桌上的每一个数据请求,以及如何做得更好。

“你想知道什么?”作为分析师,这可能是最简单但也是最有价值的问题。它帮助我极大地改善了回应利益相关者要求的方式。然而,我可以说,在分析师的世界里,这个问题被问得不够多。

请求输入—数据输出?

在我职业生涯的早期,我认为尽可能精确地回答每个数据请求是我工作的本质。乍一看,交付快速、格式良好的分析结果,直接回答您收到的请求,似乎让双方都很高兴。你的利益相关者得到了她所要求的,你以最快的方式交付了据称是好的结果。

分析师应该提供答案,而不是数据。

但是人们经常会看到以下两种情况之一:

  • 要么你的利益相关者只是简单地看了一下分析,然后就忘记了,因为它对她手头的实际问题没有帮助。
  • 或者你的利益相关者可能会回来找你,要求对它进行迭代并争论更多的数据,希望这将揭示更多可操作的见解。

不管怎样,到目前为止的分析过程都是在浪费你和你的利益相关者的时间。

改变对话

在某个时候,我意识到成为一名优秀的分析师并不意味着提供数据。相反,我们必须提供答案。提供答案意味着我们帮助利益相关者解决他们需要解决的业务问题。要做到这一点,您必须改变与利益相关者的对话,以:

  1. 找出真正的问题是什么
  2. 找到正确的数据来回答问题
  3. 检查数据是否真的是决策所需要的

1)深入了解业务问题

作为一名分析师,如果有人联系您提出数据请求,您有责任确保结果将推动业务价值。你必须追根究底,以确保你是在帮助回答一个真正的商业问题。如果不这样做,所发生的一切就是报告和在数据中打探。相反,目标是进行价值导向的分析。

“过去 12 个月,每个市场的应用下载量是多少?”不是商业问题。

‘你想知道什么?’是开始正确对话的一个短语。这有助于发现利益相关者真正想要做什么,以及哪些数据可以帮助支持他的决策。这个过程可能会将原始请求转化为实际的业务问题,如:

  • “未来 6 个月,我们应该如何在不同市场分配我们的应用营销活动预算?”
  • “在改善我们的入职流程方面,我们可以在哪些方面产生最大的影响?”

如果答案是‘我只是想知道’,这通常是一个强烈的信号,表明请求者没有考虑这个数据点将如何影响她的决定。在这种情况下,更重要的是坐下来一起讨论问题,找出哪些数据可以支持决策过程。

(来源: Pixabay )

2)针对正确问题的正确数据

询问为什么需要一组特定数据的原因对于提高决策质量和避免错误有很大的帮助。

重要的是要记住,利益相关者本身通常没有数据或分析背景。他们无法知道哪些信息是可用的,一些数据集的局限性是什么,什么是可能的。

我曾经被问到在过去 12 个月里下载我们应用的用户数量。在对请求的背景进行了简短的交谈后,发现请求者正试图评估针对应用用户的营销活动的受众规模。

虽然下载量可能是估计使用应用程序的人数的一个很好的代理,但数据集不包括任何卸载,也没有提供关于这些用户活动的任何信息。我们可能已经把我们的计划建立在休眠和搅动用户的基础上了!最后,事实证明,会话数据是回答这个问题的一个非常好的方法,导致了与下载数据完全不同的结果。

3)洞察力,但可操作的

见解应该是可操作的。分析师通常在他们的待办事项堆上有足够多的请求。如果感兴趣的数据点不是决策所必需的,那么可能会有另一个我们可以产生更多价值的请求。

如果要求的数字是 30%和 70%,我们的决策会有什么不同吗?

我发现,当被要求提供一个看似随机的业务数字时,快速检查这个数字的重要性的一个很好的方法是与利益相关者一起玩不同的场景。如果数字是 20%,结论会是什么?还是 60%?我们未来的行动会有什么不同吗?

如果答案是否定的,那么首先就不值得研究这个问题。取而代之的是,可能会问一些其他的问题来帮助解决手头的问题。

挑战与沮丧

挑战利益相关者并不意味着阻止人们提出并非 100%防水的问题。相反,定义数据问题应该是一种协作方法,以找到共同解决特定业务问题的理想方式。

以我的经验来看,人们通常会对自己的请求受到挑战而心存感激,因为这有助于他们以更快、更简单的方式实现目标。

重要的是要记住,利益相关者本身通常不是分析者,并不总是知道可以调查什么、可以获得什么样的数据以及应该如何解决特定的问题。一个好的分析师会意识到这些局限性,并帮助人们提出正确的问题,以确保每一项分析都能带来商业价值。

结论

你是一名提供答案或数据的数据科学家吗?如果答案是后者,你可能需要重新考虑如何处理利益相关者的请求。

‘你想知道什么?’是向利益相关者提供更多面向业务的、有价值的见解的第一步。

喜欢这篇文章吗?那么你可能也会喜欢我的其他帖子:

[## 分析师的偏见

为什么实验和数据使用不能保证公正的决策。

towardsdatascience.com](/the-analysts-bias-5c84825c0f48) [## 用正确的实验解决你的产品问题

如何用真正强大的假设推动商业价值

productcoalition.com](https://productcoalition.com/solve-your-product-problems-with-the-right-experiments-32c6cce02800)

使用暹罗网络的变化检测

原文:https://towardsdatascience.com/change-detection-using-siamese-networks-fc2935fff82?source=collection_archive---------29-----------------------

在 CNN 的帮助下,你如何衡量变化

所有的事情都会随着时间而变化,能够理解和量化这种变化会非常有用。例如,观察一个城市或城镇多年来的基础设施变化可以帮助衡量它的经济繁荣程度,面部变化可以揭示你是否变老得太快,签名变化可以检测欺诈活动,皮肤纹理和颜色的变化也可以告诉你是否开始患上像痤疮这样的轻度皮肤病,捕捉历史遗迹的时间戳图像可以揭示它们随着时间推移而产生的裂缝。很明显,测量这种变化的方法很有价值,这将是这篇文章的内容。

资料来源:联合国人类住区规划署

在深入技术细节之前,让我们试着更好地理解和阐述这个问题(这将有助于我们以后以更可量化的形式评估我们的模型)。你认为为观察变化而建立的系统的理想特性是什么?

1.检测相关变化,忽略其他变化

重要的是,任何模型都善于忽略与我们的用例不相关的变化,并且只检测我们感兴趣的变化。对于检测建筑物随时间的变化,它可能涉及忽略道路、树木和水体的变化,对于检测衰老,其他面部变化如晒黑或新的无关斑点/痣并不重要。

2.足够健壮以考虑稍微不同的方向/照明条件

这更多的是一个数据标准化问题,因为随着时间的推移捕获的图像会有差异,这将很难一直得到关注。如果面部图像是用智能手机拍摄的,那么光线和方向条件将会完全不同。同样,使用卫星拍摄的图像可能容易受到云层变化、阳光反射以及卫星自身方位角和仰角变化的影响。

3.模块化

这个标准基本上将建模技术分为两类,一类是您可以从模型中分离出组件,另一类是您不能。允许您在某种程度上隔离模型管道的不同部分的技术是非常优越的,因为您可以使用其他人已经构建的预构建部分并将其合并在一起(为什么要像他们所说的那样重新发明轮子)。当我们谈到早期的融合网络以及它们与暹罗网络的比较时,这一点会变得更加清楚。

基于这些标准,测量变化的最简单和最容易的方法,即使用逐元素的像素差异,就不存在了。也有更智能的方法来做这件事,但是结果仍然很差,也不是很健壮。暹罗网络来救援!

暹罗网络

一个连体神经网络将两幅图像作为输入(在两个不同的时间戳捕获),使其通过一系列卷积层,以获得两幅图像的高阶特征向量,然后使用欧几里德范数比较这些向量,以测量变化。这个想法是,没有相关变化的两幅图像将在特征向量的维度空间中产生相似的向量。

值得注意的是,两幅图像在特征提取阶段都经过完全相同的网络。

检测基础设施变化的暹罗网络(来源:https://www.mdpi.com/2072-4292/11/11/1292

让我们看看这种类型的模型如何在训练阶段调整权重。

对比损失

对比损失函数用于训练暹罗网络。如果没有变化,它试图最小化两个特征向量之间的距离,反之亦然。下面的图像试图在两类分类的情况下解释它。

对比损失(作者图片)

让我们快速直观地看一下这个。如果两幅图像都没有包含我们正在训练的变化,那么实际的标签将会是 1。如果模型权重不正确,向量 v1v2 之间的距离会很大。将这两个因素代入公式,我们得到损耗 L值。反向传播开始起作用,为了减少损失,它调整权重,使得向量之间的距离小于之前的距离(对于这组特定的图像)。引入余量 m 是为了推动网络为变化的图像产生更多独立的特征。

早期融合网络

还有一类非常相似的架构,它们在变化检测方面很流行,被称为早期融合 (EF)网络。它包括首先沿通道轴组合两个输入。因此,如果我们处理 RGB 图像,输入将是一个 6 维矩阵。这一次它将通过一个单一的前馈网络,而不是暹罗网络中的两个平行网络。

早期融合网络(尽可能简单)(图片由作者提供)

早期融合网络的最大问题是缺乏模块化。对于暹罗网络,您可以根据领域将预训练的网络用作用例的特征提取器,这在您没有大量数据时非常有用。

比方说,你想观察某个地区的建筑在 5 年前当地政府决定投入巨资建设企业园区和购物中心后的变化。因此,在投资之前,您有包含建筑物的注释数据,一旦它们完全建成。如果我们要使用的模型也可以使用来自其他广义的和各种各样的建筑物足迹数据集的知识,这将会好得多,这些数据集由来自世界各地城市的图像的瓦片和瓦片组成。

暹罗网络支持迁移学习的能力是迄今为止它优于其他方法的最大原因。

正如他们所说,变化是唯一不变的。正是这种变化,当具体评估时,可以产生非常重要的见解。

参考

  1. 杨展付昆,基于深暹卷积网络的光学航空影像变化检测(2017):https://www . semantic scholar . org/paper/Change-Detection-Based-on-Deep-Siamese-Network-for-Zhan-Fu/b 702 cf 22 AFB 725 B1 BF 9d 633 ffdd 96 CFB 00 a 87253
  2. 天宇宋、Pytorch 执行:暹罗网(2017):https://Tianyu Song . com/2017/11/16/py torch-Implementation-Siamese-Network/
  3. Mathew D. Li,,等,用于医学影像中连续疾病严重度评估和变化检测的连体神经网络(2020):
  4. 罗德里戈·卡耶·道特,贝特朗·勒·索克斯,利用卷积神经网络进行多光谱地球观测的城市变化检测(2018 年):https://www . ground ai . com/project/Urban-Change-Detection-for-multiple-multiple-Earth-Observation-Using-convolutionary-Neural-Networks
  5. 李攀方博,使用双时 VHR 光学遥感图像进行变化检测的基于双重学习的连体框架(2019):https://www.mdpi.com/2072-4292/11/11/1292

用 5 行代码改变任何图像的背景

原文:https://towardsdatascience.com/change-the-background-of-any-image-with-5-lines-of-code-23a0ef10ce9a?source=collection_archive---------8-----------------------

使用 PixelLib 对任何带有图片的图像进行模糊、着色、灰度处理和背景更改

作者照片拼贴

图像分割有很多惊人的应用,可以解决不同的计算机视觉问题。PixelLib 是一个库,旨在确保在实际应用中轻松集成图像分割。PixelLib 现在支持一种称为图像调谐的功能。

图像调优:通过图像分割改变图像的背景。图像分割的关键作用是从图像中去除分割出的对象,并将它们放置在新创建的背景中。这是通过为图像生成一个遮罩并将其与修改后的背景相结合来实现的。我们使用在 pascalvoc 数据集上训练的 deeplabv3+模型。该模型支持 20 种常见的对象类别,这意味着您可以更改图像中这些对象的背景。

该模型支持下列对象:

person,bus,car,aeroplane, bicycle, ,motorbike,bird, boat, bottle,  cat, chair, cow, dinningtable, dog, horse pottedplant, sheep, sofa, train, tv

支持的背景效果有:

1 用图片改变图像的背景

2 给图像的背景赋予不同的颜色。

3 模糊图像的背景

4 对图像背景进行灰度处理

安装 PixelLib 及其依赖项:

安装 Tensorflow 与:(PixelLib 支持 tensorflow 2.0 及以上版本)

  • pip3 安装 tensorflow

安装 PixelLib 与

  • pip3 安装 pixellib

如果已安装,请使用以下工具升级至最新版本:

  • pip3 安装 pixellib —升级

用图片改变图像的背景

PixelLib 只需 5 行代码就可以改变任何图片的背景。

sample.jpg

来源:Unsplash.com,作者雷根·布莱克伍

我们想用下面提供的图片来改变上面图片的背景。

background.jpg

来源:Unsplash.com,作者:达维德·扎维拉

用图片改变图片背景的代码

import pixellibfrom pixellib.tune_bg import alter_bgchange_bg = alter_bg()

我们导入了 pixellib,并从 pixellib 导入了类 alter_bg 。我们创建了该类的一个实例。

change_bg.load_pascalvoc_model("deeplabv3_xception_tf_dim_ordering_tf_kernels.h5")

我们加载了 deeplabv3+模型。从这里下载 deeplabv3+ pascalvoc 模型。

change_bg.change_bg_img(f_image_path = "sample.jpg",b_image_path = "background.jpg", output_image_name="new_img.jpg")

我们调用了函数 change_bg_img 来改变图片的背景。

该函数采用以下参数:

f_image_path :这是前景图像,背景将被改变的图像。

b_image_path :这是将用于改变前景图像背景的图像。

output_image_name :背景改变后的新图像。

输出图像

哇!这是美丽的,我们已经成功地取代了我们的图像背景。

我们能够使用 PixelLib 通过图像分割执行出色的前景和背景减法。

获得改变后的图像数组的输出数组的代码

对于特殊用途,您可以通过修改下面的代码轻松获得更改图像的数组。

给图像的背景分配不同的颜色

您可以为图像的背景指定不同的颜色,就像您可以用图片更改图像的背景一样。这也可以通过五行代码来实现。

为图像背景分配不同颜色的代码

它非常类似于上面使用的用图片改变图像背景的代码。唯一不同的是,我们把函数 change_bg_img 换成了处理颜色变化的函数 color_bg

change_bg.color_bg("sample.jpg", colors = (0, 128, 0), output_image_name="colored_bg.jpg")

函数 color_bg 采用参数 colors ,我们提供想要使用的颜色的 RGB 值。我们希望图像有一个绿色的背景,颜色的 RGB 值设置为绿色,即 (0,128,0)

绿色背景

注意:通过提供颜色的 RGB 值,您可以将任何颜色分配给图像的背景。

change_bg.color_bg("sample.jpg", colors = (255, 255, 255), output_image_name="colored_bg.jpg")

我们希望将图像的背景更改为白色,并将颜色的 RGB 值设置为白色,即 255,255,255。

白色背景

白色背景的相同图像。

获取彩色图像输出数组的代码

对于特殊用途,您可以通过修改下面的代码轻松获得更改图像的数组。

灰度图像的背景

使用与 PixelLib 相同的代码行对任何图像的背景进行灰度化。

对图像背景进行灰度编码

change_bg.gray_bg(“sample.jpg”,output_image_name=”gray_img.jpg”)

这仍然是相同的代码,除了我们调用函数 gray_bg 来灰度化图像的背景。

输出图像

注意:图像的背景会被改变,出现的物体会保持它们原来的质量。

获取灰显图像输出数组的代码

模糊图像背景

您可以应用模糊图像背景的效果,并且可以控制背景的模糊程度。

sample2.jpg

来源:【Unsplash.com·作者:艾蕾拉·霍瓦特

*change_bg.blur_bg("sample2.jpg", low = True, output_image_name="blur_img.jpg")*

我们调用了函数 blur_bg 来模糊图像的背景,并将模糊效果设置为低。有三个参数决定背景模糊的程度。

**低:设置为 true 时,背景略有模糊。

**中度:设置为 true 时,背景中度模糊。

**极端:设置为 true 时,背景深度模糊。

图像模糊,效果不佳。

*change_bg.blur_bg("sample2.jpg", moderate = True, output_image_name="blur_img.jpg")*

我们希望适度模糊图像的背景,我们将适度设置为真实

图像的背景模糊,效果中等。

*change_bg.blur_bg("sample2.jpg", extreme = True, output_image_name="blur_img.jpg")*

我们想要对图像的背景进行深度模糊处理,我们将极端设置为真实

图像的背景非常模糊。

模糊图像背景的完整代码

获得模糊图像输出数组的代码

注意:PixelLib 的 github 的存储库PixelLib 的文档中学习如何将这些背景效果应用到视频和摄像机的馈送中。我将很快发表一篇关于如何将这些背景效果应用到视频和相机馈送的说明性文章。

通过以下方式联系我:

电子邮件:olafenwaayoola@gmail.com

Linkedin: 阿尤拉·奥拉芬娃

推特: @AyoolaOlafenwa

脸书:阿尤拉·奥拉芬娃

查看这些关于如何利用 PixelLib 对图像和视频中的对象进行语义和实例分割的文章。

* [## 用 5 行代码实现图像分割

用 PixelLib 进行语义和实例分割。

towardsdatascience.com](/image-segmentation-with-six-lines-0f-code-acb870a462e8) [## 用 5 行代码实现视频分割

视频的语义和实例分割。

towardsdatascience.com](/video-segmentation-with-5-lines-of-code-87f798afb93) [## 用 5 行代码对 150 类对象进行语义分割

用 PixelLib 对 150 类对象进行语义分割

towardsdatascience.com](/semantic-segmentation-of-150-classes-of-objects-with-5-lines-of-code-7f244fa96b6c) [## 用 7 行代码进行自定义实例分段训练。

用 7 行代码训练您的数据集,以实现实例分割和对象检测。

towardsdatascience.com](/custom-instance-segmentation-training-with-7-lines-of-code-ff340851e99b)*

疫情前 6 个月的静息生理学、睡眠、训练和感知压力的变化

原文:https://towardsdatascience.com/changes-in-resting-physiology-sleep-training-and-perceived-stress-during-the-first-6-months-of-a1682f75349c?source=collection_archive---------20-----------------------

实践教程

HRV 4 培训用户分析

一年前 6 个月的静息心率变化。2020 年的数据显示,随着许多欧洲国家开始封锁,静息心率将下降。静息心率一直被抑制到 7 月。灰色部分,可以看到与 2019 年数据的对比。作者图片

上周我在 Twitter 上做了一个调查,是看到上面的数据引发的:在分析 HRV 4 训练数据时,在疫情的前 6 个月降低了静息心率。数据显示的趋势与我们大多数人的预期相反:

没那么快。作者图片

在这篇文章中,我将更详细地回顾这些数据,包括在疫情的前 6 个月中休息生理、睡眠、训练和感知压力的变化。

数据集

在此分析中,我将选择加入研究的 HRV4Training 用户和以下国家/地区(我们的大多数用户在这些国家/地区):澳大利亚、比利时、巴西、加拿大、法国、德国、意大利、西班牙、南非、荷兰、英国和美国。总的来说,我可以包括大约 5500 人,平均每人每天测量 3 个月,总共将近 50 万次测量。利用HRV 4 训练收集早晨的静息生理测量值,使用相机版本或外部传感器,通过将应用程序链接到 Strava 或 TrainingPeaks 来收集训练数据,同时使用应用程序中的问卷来收集主观数据。

HRV4Training 是唯一一款经过验证的应用,支持基于摄像头的心率变异性(HRV)测量。作者图片

不用说,这是人口的一个特殊样本:活跃的、有健康意识的个人,他们有足够的动力每天早上测量他们的生理状况。因此,这篇文章中显示的内容仅代表该示例,可能不适用于其他示例。

然而,上面的调查以及使用我们平台的大多数人(包括我在内)预期相反的情况(例如在锁定期间心率加快)的事实,使其成为一个有趣的分析

静息心率的变化

让我们从最初的图表开始。在下图中,我展示了在欧洲第一次停搏开始后静息心率是如何降低的。我还增加了 2019 年的心率,这种比较更容易排除季节变化等因素,并强调 3 月至 6 月期间静息心率的降低:

作者图片

背后会有什么呢?

在这一点上,我们可以提出各种理论。例如,许多人指出体育活动是如何发挥作用的。

由于封锁或一般来说较少的户外训练机会,人们可能训练得更少(我们稍后会看到事实并非如此),或者可能花更多的时间做低强度运动(也不正确)

虽然确实没有比赛可做,但我有点怀疑静息心率的降低可能与已经训练有素的人的训练有关(而且是在这么短的时间内)。

另一方面,我们谈论的是那些可能经常出差,并且总体上可能有点过度劳累的个人(这也可能促使我们寻找一款帮助量化和管理压力的应用)。让我们更深入地研究一下。

旅行和睡眠

正如我们在这里看到的,旅游受到疫情的严重影响并不奇怪:

任意单位,旅行在应用程序中被记录为是/否,在这里我们看到报告旅行的个人百分比,我们可以看到直线下降,然后在波浪之间再次开始攀升,正如预期的那样。作者图片

同样,随着许多人开始远程工作,睡眠时间变长了,这显然与疫情有关,与前一年的比较显示:

睡眠时间的变化。我们可以看到 5 月和 7 月之间的季节性下降,但也可以看到大流行前和大流行后值之间的明显差异。作者图片

当我们包括许多国家时,情况会变得有些混乱(这里我绘制了每个国家一月份随时间变化的差异,以便它们或多或少处于同一水平)。我们可以看到 3 月中旬以及 2019 年和 2020 年的“周末”左右的跳跃,睡眠时间明显增加:

作者图片

旅行和睡眠时间似乎是静息心率变化背后的两个主要因素,特别是因为这些变化都是长期的(静息心率在 6 月份仍然受到抑制,类似地,仍然很少旅行和更长的睡眠时间)

我们将在下面看到其他变量,特别是主观变量,有一个更短暂的过程,并很快重新规范化。

培训呢?

正如我前面提到的,训练和/或体能的变化也可能是静息心率变化的原因。然而,从数据来看,这一理论似乎并不成立。例如,训练时间并没有真正减少(我自己也买了一台跑步机,我记得我的很多朋友也买了一台跑步机,或者找了一位室内自行车教练,有趣的是,这似乎证实了“积极性高的人无论如何都会训练”)。

下面是一些数据,三月初训练时间降低一点,然后再归一化。一旦封锁解除,我们可以发现的是明显的增长(例如在意大利、法国和西班牙):

作者图片

就训练强度而言,似乎强度的降低或在较低强度下花费更多时间并不是心率降低的真正原因,因为训练 RPE 比前一年高了很多。然而,我们再一次看到先是一个小幅度的减少,接着是一个大幅度的增加:

作者图片

当查看骑自行车者的平均锻炼瓦特时,也可以看到类似的模式(此处未显示)。

让我们看看一些额外的参数,例如,自我报告的疲劳和压力。

我们感觉如何?

让我们从与训练相关的事情开始:疲劳。在应用程序中,我们将疲劳报告为“身体”疲劳,而不是“精神”疲劳。我们可以在下面的数据中看到一个类似于我们刚刚看到的三月底左右的训练数据的模式,有一个最初的下降(可能是由于训练时间和强度的短暂减少)。然而,自我报告的疲劳似乎不会随着负荷的增加而增加,并且很快恢复正常:

作者图片

自我报告的压力呢?

以下是应用程序中报告的内容:

作者图片

在我看来,这是最有趣的图表。我们可以看到在压力下有一个初始峰值,疫情显然是一个值得严重关注的原因。然而,过了一段时间后,其他因素可能会发挥作用:睡眠时间增加的影响,减少旅行等。—这导致自我报告的压力水平比 2019 年低得多

请注意,相对于 2019 年,2020 年 1 月和 3 月之间没有变化,突出显示了此处显示的变化如何最有可能与疫情相关联。

心率变异性(HRV)

最后,由于我的工作通常专注于生理压力和心率变异性(HRV),让我们也来看看这些数据。

总的来说,我总是建议不要做我将要做的事情:在人、群体或不同时期之间比较 HRV。我坚信 HRV 是捕捉个人压力变化的有效工具,这样我们就可以收集客观反馈并实施日常调整,以更好地管理压力,而不仅仅是比较群体。

这与静息心率不同(在我看来),这种差异可以以最简单的形式看到,静息 HR 是最大摄氧量的良好预测指标,而 HRV 不是。HRV 是关于持续反馈和压力管理的。题外话说够了,如果你刚到 HRV,并且对这个话题感兴趣,请查看这个案例研究列表或这个网络研讨会

话虽如此,但不可否认的是当我们观察人群的宏观差异时在群体水平上存在着联系(例如久坐者的 HRV 较低,随着年龄的增长而下降,所有我在这里展示的)。一场影响遍及全球的重大破坏(疫情),显然符合可能以类似方式对许多人的生理产生巨大影响的条件。让我们看看同一时间段的 HRV 数据:

作者图片

虽然这里的变化很小,但似乎在 3 月和 5 月之间,我们可以发现以下情况:

首先,随着疫情的开始,我们可以看到 HRV 的下降,每个人都对正在发生的事情和我们周围的许多未知感到非常紧张

然后,随着其他一些变化的出现(睡眠增加,旅行减少,压力减轻),我们也可以看到 HRV 的增加

在这两个事件之外,这条线相当平坦,正如我们所预期的那样,这是一个压力的标志(许多因素在起作用,这里我们对数千人进行了平均,所以再次强调,除非发生了非常大的事情,否则数据中应该没有亮点,类似于 2019 年我们自我报告的疲劳或压力)。

包裹

在上面的 9 张图中,我展示了在疫情的前 6 个月中,休息生理、睡眠、训练和感知压力的变化。

虽然巨大、严重的压力毫无疑问是今年大部分时间的特点(可以在上面的一些图表中以 HRV 下降或自我报告的指标看到)但从客观数据(旅行、睡眠、生理)和自我报告的压力水平也可以清楚地看出,我们生活方式的一些变化已经导致了可能意想不到的积极结果(睡眠时间增加,静息心率降低)。

同样,虽然我们在这里分析了一个相当大的样本(5500 人),但这些关系是特定于这个人群的,不一定适用于其他人。

我希望你已经发现写起来信息量大,保重!

Marco 拥有应用机器学习的优等博士学位、计算机科学工程的优等硕士学位以及人类运动科学和高性能教练的优等硕士学位。

已经发表了50 多篇论文和专利,涉及生理学、健康、技术和人类表现的交叉领域。

他是 HRV4Training爱跑步的联合创始人。

推特: @altini_marco

HRV 4 训练新手?

更改 Pandas 中时间数据的频率(精度)

原文:https://towardsdatascience.com/changing-the-frequency-precision-of-time-data-in-pandas-5f5882671c7f?source=collection_archive---------24-----------------------

使用 Pandas 的 resample()方法调整时间特征

华盛顿州渡口。布莱恩·汉森在 Unsplash 上的照片

今天,我们将获取华盛顿州渡轮等待公告(带有精确时间戳的推文),并将它们转换为完整的逐小时数据集。我看到了堆栈溢出周围浮动的一些其他建议,但pandas resample()似乎是我的任务的一个优雅的工具。

数据

到目前为止,我有描述等待时间的推文、这些公告的时间戳以及提取的等待时间:

带有 index、tweet_text、time 和 wait_time 的数据表头。

目标

我想扩展这个信息,这样就有一个每小时渡轮运行的记录,以及当时等待的小时数。在这种情况下,等待时间警报会一直存在,直到更新不再有延长等待。

带有每小时数据的扩展数据框。

熊猫。重新取样()

在调整了时区并添加了一天的开始等待重置之后,我需要得到上面的结果

df = df.resample('1H').ffill()

让我们来看看这些部分:

首先,*DataFrame.*resample()改变时间序列数据的频率。参见完整文档此处。因此,您可以将与时间段相关的数据转换为您想要的任何级别。它使用参数on='col_name'处理 DatetimeIndex 字段或任何类似 datetime 的列。

其次,我们指出我们想要对非时间数据使用什么策略。在这种情况下,ffill()是完美的——它从最后一个已知值向前填充所有数据点。或者,您可以使用各种策略,包括 sum、min、max、mean、median、first、last、std、bfill(反向填充)等。

结果呢

在几行代码中,我能够得到我需要的东西:

最终数据表头。

你可以在这个 GitHub repo 上找到完整的代码。更多关于熊猫的日期时间数据,请查看他们的时间序列/日期用户指南。编码快乐!

马特·弗洛雷斯在 Unsplash 上拍摄的照片

可视化美国住房市场人口统计

原文:https://towardsdatascience.com/changing-us-housing-markets-demographics-34d9b0c71cb4?source=collection_archive---------55-----------------------

使用 Seaborn 和赛璐珞的人口金字塔动画

斯科特·韦伯在 Unsplash 上拍摄的照片

2008 年美国房地产市场崩盘的影响仍在实体经济中蔓延。许多 X 一代和千禧一代看到他们积累的资产消失了。那些即将退休或已经退休的人目睹了他们最信任的资产之一——他们的财产——从悬崖上掉了下来。在所有年龄组中,人们都遭遇了经济困难。那些有能力购买新房产或保留自有资产的人,在过去 10 年里看到了巨大的收益,不仅恢复到了危机前的高位,而且在一些地区价值翻了一倍甚至两倍。与此同时,一场完美的债务风暴、收入尚可的早期职业工作越来越少,以及生活成本的上升,改变了许多人拥有住房的前景。最近的一项分析发现,52%的 18-29 岁年轻人与父母住在一起,这可能部分归因于高等教育的偏远、远程工作的持续增加以及不同行业的大规模裁员。在这篇文章中,我将展示 2010 年至 2018 年期间,不同年龄组和不同年龄段的业主入住率和租房率的变化。这些数据可以从美国社区调查中公开获得。所有使用的脚本和数据都可以在项目 GitHub 上获得。这个项目是对我之前关于就地老化的推测的跟进。

[## 年龄到位:对住房市场流动的重大干扰

在冠状病毒疫情的影响下,就地养老的决定对那些准备退休或…

medium.com](https://medium.com/swlh/age-in-place-a-major-disruption-to-the-housing-market-flow-a3fe7a75d14f)

数据

原始数据是业主入住和租赁时间的百分比值的汇编,按年龄人口统计分开。在这项研究中,我们探讨了百分比随时间的变化以及按世代类别的变化。这四个世代类别是沉默的一代、婴儿潮一代、X 一代和千禧一代。

将年龄组分成几代。图片作者。

动画

为了制作动画,赛璐珞被用来记录多个海波恩的情节。赛璐珞可以使用 pip 安装在 Python 中。

pip install celluloid

简单地说,我们拍下一个 for 循环中生成的每个图。在循环之后,我们将这些图像拼接成视频或 gif。

## Open the camera lens
fig = plt.figure()
camera = Camera(fig)## Start the photoshoot
for i in range(9): 
   ## Build graphs here
   ... ## Take the shot
   camera.snap()## Make the movie
animation = camera.animate(interval=500)
animation.save('animation_housing.gif', writer = 'pillow')

结果

动画程序的输出。作者制作的动画。

这幅图中有很多东西需要解读。首先,从 2010 年到 2018 年,变化最大的群体是64-74 岁的业主居住者,总体增长了 4.4%。45 至 54 岁的车主居住者同期降幅最大,为-4.0%。54 至 64 岁的业主住户的收益为 1.1%,这可能是业主住户进入新类别的结果。包括 45 岁至 54 岁在内的所有年龄段,租房和自住的比例都在下降。2017 年和 2018 年,年轻人(35 岁以下& 34 岁至 44 岁)的拥有率略有上升(分别上升 0.3%和+0.2%)。

世代变迁

这些数字是如何按世代分类的呢?

作者制作的动画。

沉默的一代和婴儿潮一代的成员看到他们的业主入住率在这段时间内有所增加,而 X 一代和千禧一代的业主入住率则有所下降。代码和额外的 gif(按年份的增量)可以在 GitHub 上找到。

讨论

在我之前的文章中,我推测考虑到当前的疫情和经济不确定性,许多临近退休或已经退休的人选择就地养老。甚至在疫情之前,老一代人自有住房类别的扩大就证明了这一点。该数据中令人惊讶的是,X 一代在租赁和自有住房比例方面都有所下降。虽然千禧一代正以创纪录的速度搬到父母身边,但尚不清楚 X 一代成员的自有/租赁比例将会如何。我叫科迪·格利克曼,可以在 LinkedIn 上找到我。请务必查看下面的一些其他文章。

[## 年龄到位:对住房市场流动的重大干扰

在冠状病毒疫情的影响下,就地养老的决定对那些准备退休或…

medium.com](https://medium.com/swlh/age-in-place-a-major-disruption-to-the-housing-market-flow-a3fe7a75d14f) [## 使用 Python 创建照片镶嵌

一步一步的教程,让你自己的美丽的图像

towardsdatascience.com](/creating-photo-mosaics-using-python-49100e87efc) [## 使用 GitHub 创建漂亮的静态网页

查找模板和为静态网页创建表单的位置

towardsdatascience.com](/building-a-beautiful-static-webpage-using-github-f0f92c6e1f02)

用 R 在 5 分钟内创建您的交互式动画图形

原文:https://towardsdatascience.com/channel-your-creativity-interactive-and-animated-graphics-in-r-with-covid-19-data-5f7bede4b29f?source=collection_archive---------33-----------------------

D3.js 中没有编码的动画可视化

冠状病毒,或称新冠肺炎病毒,在不到两个月的时间里已经在几个大洲传播,并且肯定已经引起了公众的恐慌和疫情的恐惧!这个星球上的每条新闻都在报道冠状病毒,股票市场正在崩溃,人们正在让焦虑支配他们的行为。当然,我对病毒遗传学和流行病学没有任何专长,但就我而言,理性的做法是采取必要的预防措施,呆在家里,保持社交距离,直到我们一起度过难关!

与其呆在家里做最坏的打算,我们为什么不积极地用一些有创造性的东西来占据我们的大脑呢?在这篇博客中,我将使用 COVID–19 数据来讨论 R 中使用较少代码行生成图形的几种技术,以及如何在 R 中创建交互式动画图形,而无需在 D3.js 中编写一行代码。现在,让我们加入到 r 中新冠肺炎可视化的潮流中来

我们将使用由约翰霍普金斯大学 CSSE 2019-nCoV Github 存储库维护并每日更新的新冠肺炎数据集(这里是链接)。有 3 个单独的数据集,分别用于确诊、死亡和恢复的病例,这 3 个数据集都是宽格式的,从 1 月 22 日持续到 3 月 28 日(当我开始这篇博客时)。

新冠肺炎确诊病例数据集

同时读入数据集(并创建绘图变量)

首先,让我们把 3 个数据集读入 R,

注意,我们在每个数据集中创建了一个额外的变量,标记为‘Status’。我稍后会解释原因,但是现在,让我们做一个快速的完整性检查,以确保 3 个数据集包含相同的绑定列。这种健全性检查总是有用的,尤其是在原始数据源发生变化的情况下,并且(复活节彩蛋)下面的代码显示了如何做 DRY

现在,我们需要将数据集列表追加到一个数据框中,

现在,让我们回到我们在读取每个数据集时创建的‘Status’变量。在已确认、已死亡和已恢复数据集中,此堆叠变量的值将分别为“已确认”、“已死亡”和“已恢复”。将此'状态'变量作为单独的一列,可将其指定为{ggplot2}中的计算和绘图参数。

因此,下面展示了按“国家”和“状态”分组的数据准备步骤(这里,我选择了 4 个国家进行比较——中国、意大利、美国和伊朗)。

(复活节彩蛋)注意到了 colnames(。)?这可能是{ magrittr }管道中我最喜欢的功能。)这里接收上一次操作返回的所有内容。超级得心应手!

静态热图显示确诊病例

可视化纵向数据或任何二维数据的一种方法是热图,因此,让我们继续看第一个图表——上述 4 个国家确诊病例的热图。

出于演示的目的,我只绘制了从 2 月 22 日到 3 月 28 日的数据,但是如果您愿意的话,可以随意扩展时间线,

这是我们的热图,显示与其他国家相比,中国的确诊病例数一直是最高的,直到美国和意大利在 3 月底超过了这些数字。

热图的一个缺点是它不能处理第三维度,这意味着如果我们要观察确诊、死亡和康复病例的模式,我们必须做 3 个单独的热图。

交互式纵向意大利面条图

纵向折线图适用于添加第三层(即确诊、死亡和痊愈)的任务。在这里,对于每个国家,情节的开始日期被设置为第一个病例被报告确认的日期,我们需要将格式从宽转换为长,

为了一次创建多个图,{ggplot2}有一个很棒的函数‘facet _ wrap’(查看此链接了解详情),这里我们允许不同国家的比例有所不同。为了让剧情互动,{plotly}是我们的打包产品,

这是我们的互动折线图,

现在,我们可以直观地说出 4 个选定国家的轨迹,那么其他国家呢?

R 中的动画条形图

我们可以创建一个赛车条形图,显示确诊病例最多的前 N 个国家,我们可以使用{gganimate}软件包在 R 中完成!

完整的代码可以在 my Github 中找到,但是基本上,我们首先定义一个静态图,就像我们定义{ggplot2}一样,

然后定义动画部分,(复活节彩蛋)函数 ease_aes() 可以用来调整你的酒吧过渡的平滑度,

瞧,在这里。

我希望这篇博客让你从冠状病毒恐慌中分散了一点注意力,更好的是,你学到了一些新东西。同样,你可以在 my Github 中找到完整的代码,包括如何将你的动画情节保存为 GIF 或 MP4

保持积极,保持健康!

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

平静中的混沌:什么是混沌工程?

原文:https://towardsdatascience.com/chaos-in-the-calm-what-is-chaos-engineering-5311c27b2c7e?source=collection_archive---------55-----------------------

凯文·霍尔瓦特在 Unsplash 上的照片

时间是主动而不是 被动

混沌工程不仅仅是机器人尼克博士做的事情;这是开发生命周期中一个严肃且日益普遍的部分。

在不断变化的全球环境中,将持续测试引入 DevOps 工具链以确保安全性和弹性的压力越来越大。随着云成为越来越多公司的主导领域,情况更是如此,因为哪里有新兴技术,哪里就有新兴威胁

在实践中,一个没有经过常规和有效测试的系统更容易停机,这会导致失望甚至失去客户。在 ITIC 的第 11 次年度停机时间每小时成本调查 中,发现 87%的组织现在被要求在 99.99%的时间内可用(他们注意到,在过去的 2.5 年中,这一数字上升了 81%)。令人难以置信的是,40%的企业组织表示,一个小时的停机时间会给他们带来 100 万到 500 多万美元的损失。

那么,你如何先发制人,为那种可能让你的公司损失数百万的灾难做准备呢?嗯,一个越来越流行的方法是在别人打破你自己的东西之前,有成效地打破它。

揭露,改进

对于我们这些不是 DevOps 世界巫师的人来说,仅仅是故意给你的辛苦工作带来混乱的想法就令人不寒而栗。不过,理解这个概念并不困难,一旦你理解了需要做的工作,我相信你会同意结果是值得投入资源的。

这方面一个相当传统的例子是渗透测试道德黑客,即一家公司(通常)付钱给第三方,试图找到他们基础设施中的安全弱点。混沌工程将这种测试安全性的想法提升了一个档次。

为了在高层次上进行解释,您将中断(例如重大服务器崩溃、黑客攻击企图、停电)引入系统的正常生产 状态,以便主动(而不是被动)测试其弹性。

开发生命周期的简单视图(图形我自己的)

它旨在复制真实的“紧急”情况,与传统的主流测试不同,它发生在生产环境中,而不是在开发生命周期的早期。

但是,如果不需要的话,你为什么要竭尽全力去破坏你自己的网络或者烧毁你自己的硬件呢?

嗯,这有点像一句老话“没有准备就是为失败做准备”;如果你不做,那么别人可能会做。因此,为了避免陷入意外停机的灾难性局面,最好提前准备好任何缓解措施。

通过暴露任何可能的弱点,你可以最终提高对未来任何系统的信心。

像对待科学学科一样对待它

混沌大师 Gremlin 在他们的白皮书中明确指出:

"混沌工程的关键在于它被视为一门科学学科."

混沌工程不只是雇佣一些人来尝试破坏你的系统,而是让你恢复到原始状态,而不会对客户或员工造成任何影响。从法规遵从性的角度来看,它允许您验证和证明假设的防御机制。Gremlin 列出了成功工程应该遵循的六个步骤:

  1. 形成假设
  2. 计划你的实验
  3. 最小化爆炸半径
  4. 进行实验
  5. 庆祝结果
  6. 完成任务

有许多对混沌工程的批评和怀疑,因为,当然,其中有风险。但是,遵循这些步骤并利用最佳实践(包括从试运行环境开始,始终有一个“终止开关”,并提前计划),可以大大降低出错的可能性。记住:如果你不在一个受控的环境中测试东西,你肯定会在它们将来不可避免地出错时努力去修复它们!

最终,通过模拟可能完全压倒一切的事件,你让它们成为非事件——如果它们在未来发生——几乎不会留下痕迹。

解决假设

混沌工程的另一个好处是它挑战了软件工程世界最大的弱点:不正确的假设。无论是相信你拥有所有的权力,还是相信你永远不会失去空间,让这些谬论生根发芽会让问题悄悄进入。

分布式计算的谬误,作者 L. Peter Deutsch

如果您没有持续不断地进行测试,并将您的基础设施推向极限,那么您就依赖于在现实世界中发现您的系统弱点,这可能会损害您的客户群。

无论是长时间还是短时间的停机,每一分钟都很重要。安迪·格罗夫说得好,“成功滋生自满”,这是真的。自满滋生失败”。

猿人军队

混沌工程并不是一个新概念。早在 2011 年,网飞就开始开发一套被称为“猿猴军”的开源工具。这些工具旨在测试其亚马逊网络服务基础设施的安全性、可靠性和弹性,包括像混沌猴、看门猴这样的大牌。

混沌猴是网飞的第一个工具,它通过随机重启服务器来工作。虽然难以置信的创新,但它似乎已经在网上臭名昭著,部分原因是它偏离了混沌工程的现代基础。一般来说,在繁忙时期随意破坏东西是不明智的,而是要使用控制和措施来了解弱点(除非,像网飞一样,你有一个庞大的工程师团队排队包猴子说!)

网飞随后引入了一整套猴子来合作,包括混沌孔(它消灭了整个 AWS 区域颤抖)和潜伏猴子(它引入了通信延迟来模拟真实世界的退化和中断)。最近,猴子已经被单独开发,许多被构建到 Spinnaker,网飞的“开源多云连续交付平台”

你可以在网飞科技博客上阅读关于猿人军队和网飞令人难以置信的混沌工程项目的详细信息。

平静中的混乱

包括 Salesforce、亚马逊和优步在内的其他公司多年来一直在使用弹性测试来提高可靠性,因为如此多的项目都是开源的,所以接受混乱并不困难。

这里有很棒的论坛(包括 Chaos 社区 )以及丰富的产品,包括 VMware 的“”Mangle,它被描述为一种工具,可以让你:

“…针对应用程序和基础架构组件无缝运行混沌工程实验,以评估弹性和容错能力。它旨在引入几乎没有预先配置的故障……”

也有合法的全面服务,如超级酷的' Gremlin ',它提供了一个平台,允许您通过多种故障模式在您的堆栈中引入“攻击”。

作为一种实践,它还不是很标准。即使这不一定是有史以来最困难的过程,公司也希望得到经验丰富的开发人员的保证,他们可以安全地设计混乱,这可能很难 1)找到,2)投资。

尽管最终,随着新出现的威胁变得更加复杂,持续测试的需求只会变得更加必要;随着客户对功能系统依赖的增加,出错的空间缩小了。

正如比尔·盖茨 5 年前警告我们的那样:

“没有必要恐慌……但我们需要继续前进”。

使用 Detectron2 对自定义数据进行字符识别和分段

原文:https://towardsdatascience.com/character-recognition-and-segmentation-for-custom-data-using-detectron2-599de82b393c?source=collection_archive---------32-----------------------

详细说明

利用迁移学习的力量

照片由 Unsplash 上的苏伦兰议员拍摄

目录

  • 什么是探测器 2?
  • 项目设置
  • 建立模型
  • 培训和评估
  • 结果
  • 资源

什么是探测器 2?

Detectron2 是一个开源的对象识别和分割软件系统,它实现了最先进的算法,是脸书人工智能研究(FAIR)的一部分。这是 PyTorch 对其先前版本 Detectron 的彻底重写,它源自 MaskRCNN-Benchmark

您可以从 PyTorch DevCon19 上看到 Detectron2 的详细信息,以及基准比较、不同的应用程序、定制,以及关于其工作性质的具体细节。

Detectron 还提供了一个由 Detectron2 训练的大型基线集合,您可以从模型动物园开始访问代码。使用 FAIR 提供的笔记本来玩 Detectron2。

[## Detectron2 入门

侦探 2 初学者教程

colab.research.google.com](https://colab.research.google.com/drive/16jcaJoc6bCFAQ96jDe2HwtXj7BMD_-m5)

项目设置

我们将开发一个“泰卢固语字符”的字符识别和分割。为了建立这个项目,我们需要适合上述机器学习任务的数据。由于没有足够的可用数据,我们需要收集自定义数据。

资料组

使用文章“如何为字符识别和分段准备自定义数据集?”创建您自己的自定义数据,其中包括工具和程序来收集数据和预处理,并建立数据的注释。

[## 如何准备用于字符识别和分割的自定义数据集?

本文是泰卢固语字符识别研究的一部分。它侧重于为…创建自定义数据集

towardsdatascience.com](/how-to-prepare-a-custom-dataset-for-character-recognition-and-segmentation-c39f6bf3690)

项目结构

在这里,您可以看到由文件和目录组成的项目结构,例如 test_datatrain_data 由用于训练和测试模型的图像和注释组成。

|   Detectron2_Telugu_Characters.ipynb
|   label2coco.py
|   resize.py
|   test.json
|   train.json
|   Viewer.ipynb
|
+---results
|       res1.PNG
|       res2.PNG
|       res3.PNG
|       res4.PNG
|       res5.PNG
|       res6.PNG
|       res7.PNG
|
+---test_data
|       img1.json
|       img1.png
|       img10.json
|       img10.png
|       img11.json
|       img11.png
|       img12.json
|       img12.png
|       img13.json
|       img13.png
|       img14.json
|       img14.png
|       img15.json
|       img15.png
|       img16.json
|       img16.png
|       img17.json
|       img17.png
|       img18.json
|       img18.png
|       img19.json
|       img19.png
|       img2.json
|       img2.png
|       img20.json
|       img20.png
|       img3.json
|       img3.png
|       img4.json
|       img4.png
|       img5.json
|       img5.png
|       img6.json
|       img6.png
|       img7.json
|       img7.png
|       img8.json
|       img8.png
|       img9.json
|       img9.png
|
+---test_images
|       81XtS7O3nUL._SL1500_.jpg
|       alpha1.jpg
|       download.jfif
|       images (1).jfif
|       images (2).jfif
|       images (2).png
|       images (3).jfif
|       images (3).png
|       images (4).jfif
|       images (4).png
|       images (5).jfif
|       images (5).png
|       images (6).jfif
|       images (7).jfif
|       images.jfif
|       images.png
|       test_1.jpg
|       x1080.jfif
|
\---train_data
        img1.json
        img1.png
        img10.json
        img10.png
        img100.json
        img100.png
        img101.json
        img101.png
        img102.json
        img102.png
        img103.json
        img103.png
        img104.json
        img104.png
        img105.json
        img105.png
        img106.json
        img106.png
        img107.json
        img107.png
        img108.json
        img108.png
        img109.json
        img109.png
        img11.json
        img11.png
        img110.json
        img110.png
        img111.json
        img111.png
        img112.json
        img112.png
        img113.json
        img113.png
        img114.json
        img114.png
        img115.json
        img115.png
        img116.json
        img116.png
        img117.json
        img117.png
        img118.json
        img118.png
        img119.json
        img119.png
        img12.json
        img12.png
        img120.json
        img120.png
        img121.json
        img121.png
        img122.json
        img122.png
        img123.json
        img123.png
        img124.json
        img124.png
        img125.json
        img125.png
        img126.json
        img126.png
        img127.json
        img127.png
        img128.json
        img128.png
        img129.json
        img129.png
        img13.json
        img13.png
        img130.json
        img130.png
        img131.json
        img131.png
        img132.json
        img132.png
        img133.json
        img133.png
        img134.json
        img134.png
        img135.json
        img135.png
        img136.json
        img136.png
        img137.json
        img137.png
        img138.json
        img138.png
        img139.json
        img139.png
        img14.json
        img14.png
        img140.json
        img140.png
        img141.json
        img141.png
        img142.json
        img142.png
        img143.json
        img143.png
        img144.json
        img144.png
        img145.json
        img145.png
        img146.json
        img146.png
        img147.json
        img147.png
        img148.json
        img148.png
        img149.json
        img149.png
        img15.json
        img15.png
        img150.json
        img150.png
        img151.json
        img151.png
        img152.json
        img152.png
        img153.json
        img153.png
        img154.json
        img154.png
        img155.json
        img155.png
        img156.json
        img156.png
        img157.json
        img157.png
        img158.json
        img158.png
        img159.json
        img159.png
        img16.json
        img16.png
        img160.json
        img160.png
        img161.json
        img161.png
        img162.json
        img162.png
        img163.json
        img163.png
        img164.json
        img164.png
        img165.json
        img165.png
        img166.json
        img166.png
        img167.json
        img167.png
        img168.json
        img168.png
        img169.json
        img169.png
        img17.json
        img17.png
        img170.json
        img170.png
        img171.json
        img171.png
        img172.json
        img172.png
        img173.json
        img173.png
        img174.json
        img174.png
        img175.json
        img175.png
        img176.json
        img176.png
        img177.json
        img177.png
        img178.json
        img178.png
        img179.json
        img179.png
        img18.json
        img18.png
        img180.json
        img180.png
        img181.json
        img181.png
        img182.json
        img182.png
        img183.json
        img183.png
        img184.json
        img184.png
        img185.json
        img185.png
        img186.json
        img186.png
        img187.json
        img187.png
        img188.json
        img188.png
        img189.json
        img189.png
        img19.json
        img19.png
        img190.json
        img190.png
        img191.json
        img191.png
        img192.json
        img192.png
        img193.json
        img193.png
        img194.json
        img194.png
        img195.json
        img195.png
        img196.json
        img196.png
        img197.json
        img197.png
        img198.json
        img198.png
        img199.json
        img199.png
        img2.json
        img2.png
        img20.json
        img20.png
        img200.json
        img200.png
        img21.json
        img21.png
        img22.json
        img22.png
        img23.json
        img23.png
        img24.json
        img24.png
        img25.json
        img25.png
        img26.json
        img26.png
        img27.json
        img27.png
        img28.json
        img28.png
        img29.json
        img29.png
        img3.json
        img3.png
        img30.json
        img30.png
        img31.json
        img31.png
        img32.json
        img32.png
        img33.json
        img33.png
        img34.json
        img34.png
        img35.json
        img35.png
        img36.json
        img36.png
        img37.json
        img37.png
        img38.json
        img38.png
        img39.json
        img39.png
        img4.json
        img4.png
        img40.json
        img40.png
        img41.json
        img41.png
        img42.json
        img42.png
        img43.json
        img43.png
        img44.json
        img44.png
        img45.json
        img45.png
        img46.json
        img46.png
        img47.json
        img47.png
        img48.json
        img48.png
        img49.json
        img49.png
        img5.json
        img5.png
        img50.json
        img50.png
        img51.json
        img51.png
        img52.json
        img52.png
        img53.json
        img53.png
        img54.json
        img54.png
        img55.json
        img55.png
        img56.json
        img56.png
        img57.json
        img57.png
        img58.json
        img58.png
        img59.json
        img59.png
        img6.json
        img6.png
        img60.json
        img60.png
        img61.json
        img61.png
        img62.json
        img62.png
        img63.json
        img63.png
        img64.json
        img64.png
        img65.json
        img65.png
        img66.json
        img66.png
        img67.json
        img67.png
        img68.json
        img68.png
        img69.json
        img69.png
        img7.json
        img7.png
        img70.json
        img70.png
        img71.json
        img71.png
        img72.json
        img72.png
        img73.json
        img73.png
        img74.json
        img74.png
        img75.json
        img75.png
        img76.json
        img76.png
        img77.json
        img77.png
        img78.json
        img78.png
        img79.json
        img79.png
        img8.json
        img8.png
        img80.json
        img80.png
        img81.json
        img81.png
        img82.json
        img82.png
        img83.json
        img83.png
        img84.json
        img84.png
        img85.json
        img85.png
        img86.json
        img86.png
        img87.json
        img87.png
        img88.json
        img88.png
        img89.json
        img89.png
        img9.json
        img9.png
        img90.json
        img90.png
        img91.json
        img91.png
        img92.json
        img92.png
        img93.json
        img93.png
        img94.json
        img94.png
        img95.json
        img95.png
        img96.json
        img96.png
        img97.json
        img97.png
        img98.json
        img98.png
        img99.json
        img99.png

建立模型

在本节中,我们将看到如何使用 Detectron2 构建一个模型来执行泰卢固语字符识别和分段。

注册 COCO 数据集

因为我们遵循上下文中的公共对象(COCO)数据集格式,所以我们需要将训练和测试数据注册为 COCO 实例。代码如下:

我们需要训练集和 dataset_dicts 的元数据,即训练图像的内部格式 os 注释。

让我们来看一些训练样本:

训练数据样本-按作者分类的图像

我们使用的是来自模型动物园的科科预训 R50-FPN 面具 R-CNN 模型。下一步是使用配置文件配置模型,加载权重并设置阈值(在本例中为 0.5)

培训和评估

设置参数

这里,我们使用先前 COCO 注册的数据,即训练和测试数据,工人数量为 4,每批加载模型权重和图像的路径为 2,基本学习率为 0.001,最大迭代次数为 200,类数量为 6。

在这里,您可以看到培训数据的详细信息:

在这里,总损失、分类损失和不同指标等值被描绘为图形,并使用 tensorboard.dev 显示。以下是链接:

[## 培训详细信息—使用 Detectron2 进行泰卢固语字符识别和分段

使用张量板的 tring 图

tensorboard.dev](https://tensorboard.dev/experiment/hjZr4HW0QFq1z4yBGBpBPg/#scalars)

估价

COCOEvaluator用于评估测试数据集,评估结果保存在“输出”目录中。inference_on_dataset函数还为给定的模型和数据集提供精确的速度基准。

以下是输出:

结果

即使平均精度(AP)不大于 0.81%。只考虑 200 幅图像作为训练数据,就能产生几乎准确的预测,这是一个更好的迹象,也是很有希望的。

这里是几个看不见的样本给了模型,结果是:

三分模型对看不见的图像的预测——作者提供的图像

您可以使用这种方法,通过 Detectron2 实现您自己的对象识别和分割系统。

资源

[## Facebook 研究/检测器 2

Detectron2 是脸书人工智能研究所的下一代软件系统,实现了最先进的物体检测…

github.com](https://github.com/facebookresearch/detectron2) [## PyTorch

开源深度学习平台,提供从研究原型到生产部署的无缝路径。

pytorch.org](https://pytorch.org/) [## 脸书艾出版公司

研究领域著名论文近期出版物基础和应用近期项目

ai.facebook.com](https://ai.facebook.com/results/?q&content_types[0]=publication&sort_by=relevance&view=list&page=1) [## 教程—detector 2 0 . 1 . 3 文档

编辑描述

detectron2.readthedocs.io](https://detectron2.readthedocs.io/tutorials/index.html)

CharacterBERT

原文:https://towardsdatascience.com/characterbert-reconciling-elmo-and-bert-for-word-level-open-vocabulary-representations-from-94037fe68b21?source=collection_archive---------29-----------------------

来自字符的单词级开放词汇表示

CharacterBERT 是什么,和 BERT 有什么不同?

CharacterBERT 是 BERT 的一个变体,它试图回到更简单的时代,那时模型为单个单词(或者更确切地说,令牌)生成单个嵌入。在实践中,唯一的区别是不依赖于文字块 , CharacterBERT 使用一个 CharacterCNN 模块 ,就像 ELMo【1】中使用的那个一样。

下图显示了 CharacterCNN 的内部机制,并将其与 BERT 中的原始单词块系统进行了比较。

BERT 与 CharacterBERT 中的上下文无关标记表示(来源:【2】)

我们假设单词“Apple”是一个未知单词(即它没有出现在 BERT 的词块词汇表中),那么 BERT 将其拆分为已知词块:【Ap】和[##ple】,其中##用于指定不在单词开头的词块。然后,使用字块嵌入矩阵嵌入每个子字单元,产生两个输出向量

另一方面, CharacterBERT 没有单词表,可以处理任何*输入标记,只要它不是不合理的长(即少于 50 个字符)。CharacterBERT 并没有拆分“Apple”,而是将它解读为一个的字符序列:【A】,【p】,【p】,【l】,【e】。然后使用字符嵌入矩阵表示每个字符,产生一系列字符嵌入。然后这个序列被送到多个 CNN,每个 CNN 负责一次扫描 n 个字符,n =[1..7].所有 CNN 的输出被聚集成一个单一的矢量,然后被投射到期望的维度,使用高速公路层【3】。这个最终投影是单词“Apple”的上下文无关表示,它将与位置和片段嵌入相结合,然后像在 BERT 中一样被馈送到多个变换器层。

为什么是 CharacterBERT 而不是 BERT?

CharacterBERT 几乎充当了 BERT 的替代品

  • 为任何输入标记生成单个嵌入
  • 不依赖于单词表

第一点显然是可取的,因为使用单个嵌入比每个令牌使用可变数量的单词块向量要方便得多。至于第二点,当在专业领域(如医疗领域、法律领域……)工作时,这一点尤为重要。事实上,在构建 BERT 的专门版本(例如 BioBERT【4】、blue BERT【5】和一些 SciBERT【6】模型)时,通常的做法是在一组专门的文本上重新训练 原始模型。因此,大多数 SOTA 专用模型保留了原来的通用领域词表,这不适合专用领域应用

下表显示了原始通用领域词汇与建立在医学语料库上的医学词块词汇之间的差异:MIMIC【7】和 PMC OA【8】

使用不同领域的词块词汇表对特定领域术语进行标记化(来源:【2】)

我们可以清楚地看到,伯特的词汇是不适合专业术语(例如“胆总管结石”被拆分为【cho,led,och,oli,thi,asi,s】)。医学术语更适用于,但它也有其局限性 (例如,将“borygmi”转换为[bor,bor,yg,mi])。

因此,为了避免任何可能来自使用错误单词表的偏见,并努力回到概念上更简单的模型,提出了 BERT 的变体:CharacterBERT。

CharacterBERT 如何与 BERT 进行对比测试?

BERT 和 CharacterBERT 在一个经典场景中进行比较,在该场景中,通用模型在作为专用版本的预训练的初始化之前被预训练。

: 我们在这里重点关注英语和医学领域。

培训前语料库(来源:【2】)

为了尽可能的公平起见,BERT 和 CharacterBERT 都是在 完全相同的条件下从头开始预训练的。然后,在多个医疗任务上评估每个预训练模型。我们举个例子。

评估任务(来源:【2】)

i2b 2/VA 2010【9】是一项包含多项任务的竞赛,其中包括用于评估我们模型的临床概念检测任务。目标是检测三种类型的临床概念:问题治疗测试。上图的最左边给出了一个例子。

像往常一样,我们通过在训练集上进行首次训练来评估我们的模型。在每次迭代中,模型在单独的验证集上被测试,允许我们保存最佳迭代。最后,在经历所有迭代之后,使用来自最佳迭代的模型在测试集上计算分数(这里是严格的 F1 分数)。然后,使用不同的随机种子将整个过程重复 9 次以上,这允许我们考虑一些方差,并将最终模型性能报告为:均值标准差

: 更多细节详见论文[2]。

结果如何?

来源:[2]

在大多数情况下, CharacterBERT 的表现优于其对应的 BERT

: 唯一的例外是 ClinicalSTS 任务,其中医疗角色 BERT 的得分(平均)低于 BERT 版本。这可能是因为任务数据集很小(1000 个示例,而其他任务平均为 30,000 个示例),应该进行调查。

好处:对噪音的鲁棒性

除了纯粹的性能,另一个有趣的方面是模型是否对噪声输入具有鲁棒性。事实上,我们在 MedNLI 任务【10】嘈杂版本上评估了 BERT 和 CharacterBERT,其中(简单地说)目标是说出两个医学句子是否相互矛盾。这里,X%的噪声水平意味着文本中的每个字符都有 X%的概率被替换或交换。结果显示在下图中。

BERT 和 CharacterBERT 在嘈杂的(拼错的)MEDNLI 版本上进行微调(来源:【2】)

正如你所看到的,医学 CharacterBERT 模型似乎比医学 BERT 更健壮:当向所有分割添加噪声时,两个模型之间大约 1%精度的初始差距增长到大约 3%,当仅在测试集中用噪声给模型带来惊喜时,大约 5%。

CharacterBERT 的缺点呢?

CharacterBERT 的主要缺点是其较慢的预训速度 这是由于:

  1. 训练速度较慢的 CharacterCNN 模块;
  2. 但主要是因为该模型工作在记号级 :
    它在每次预训练迭代中更新大量记号词汇表。

*/!* :然而, CharacterBERT 在推理过程中与 BERT 一样快(实际上,甚至更快一点)并且预训练模型可用所以你可以完全跳过预训练步骤😊!

结论

总而言之,CharacterBERT 是用一个 CharacterCNN(就像 ELMo 一样)代替了 WordPiece 系统的 BERT 的简单变种。对多个医疗任务的评估结果表明,这种变化是有益的:提高了性能和对拼写错误的鲁棒性。希望这个模型能激发更多基于单词级开放词汇转换器的语言模型的研究:将同样的想法应用于艾伯特【11】厄尼【12】

原文:
https://arxiv.org/abs/2010.10392

代号&预训车型:
https://github.com/helboukkouri/character-bert

参考文献:
【1】彼得斯、马修·e 等深层语境化的词语表述。 arXiv 预印本 arXiv:1802.05365 (2018)。【2】El Boukkouri,Hicham,et al .character BERT:调和 ELMo 和 BERT,用于来自字符的单词级开放词汇表示。 arXiv 预印本 arXiv:2010.10392 (2020)。 【3】斯利瓦斯塔瓦、鲁佩什库马尔、克劳斯格雷夫、于尔根施密德胡伯。公路网。arXiv 预印本 arXiv:1505.00387 (2015)。
【4】Lee,Jinhyuk,et al .BioBERT:一种用于生物医学文本挖掘的预训练生物医学语言表示模型。生物信息学36.4(2020):1234–1240。
彭、王一凡、阎、。生物医学自然语言处理中的迁移学习:在十个基准数据集上对 bert 和 elmo 的评估。arXiv 预印本 arXiv:1906.05474 (2019)。
【6】贝尔塔吉、伊兹、凯尔·洛、阿尔曼·科汉。SciBERT:科学文本的预训练语言模型。arXiv 预印本 arXiv:1903.10676 (2019)。
【7】Johnson,Alistair 等《MIMIC-III 临床数据库》(1.4 版)。生理网(2016)https://doi.org/10.13026/C2XW26
【8】PMC OA 语料库:https://www.ncbi.nlm.nih.gov/pmc/tools/openftlist/
【9】uz uner,zlem 等. 2010 i2b2/VA 对临床文本中概念、断言、关系的挑战。美国医学信息学协会杂志18.5(2011):552–556。
【10】Shiva de,柴坦尼亚。“MedNLI —临床领域的自然语言推理数据集”(版本 1.0.0)。生理网(2019)https://doi.org/10.13026/C2RS98
【11】兰,等.阿尔伯特:一个用于语言表征自我监督学习的 lite BERT。arXiv 预印本 arXiv:1909.11942 (2019)。
【12】孙,于等. ERNIE 2.0:语言理解的持续预训练框架。AAAI。2020.
**

完成人: Hicham El Boukkouri 、Olivier Ferret、Thomas Lavergne、Hiroshi Noji、Pierre Zweigenbaum 和 Junichi Tsujii

基于特征的新产品预测相似度

原文:https://towardsdatascience.com/characteristic-based-similarity-for-new-products-forecasting-8ab919d570b3?source=collection_archive---------38-----------------------

安德烈·亨特在 Unsplash 上的照片

这是解决零售商在组合中加入新产品时面临的最大问题之一的方法。

“我能卖多少钱?”是每个零售商在考虑为商店和电子商务添加新材料时都会想到的问题。

我们通常有很多技术来帮助我们预测和预见,但当我们谈论新产品时,我们会面临一个大问题,即如果我们没有新产品的销售数据来用于回归或时间序列算法。

那么…我们如何预测呢?

方法

解决这种数据缺乏的一种方法是找到一种与新产品相似的产品,并复制其历史销售数据的一部分,有了它,您现在可以应用您喜欢的预测技术。

基本上,你可以用几种不同的方法来比较产品,除此之外,每个企业都必须定义在这种分析中使用的理想特性。

定义功能后,这是该过程中最困难也是最重要的一步,您将遵循一个简单的步骤来实现您的目标:

1.对分类数据应用一键编码

应用一个热编码,我们从比较类别名称/文本之间的距离,到比较产品是否与旧产品在同一类别。

2.将定标器技术应用于数值数据

当我们谈论距离时,它总是类似于 A-B=C,但现在我们正在讨论几个特征的距离,结果听起来像是所有的 cs 之和减去所有的 Bs。

这不会有任何问题,只要列中的值的范围都是相同的,我很确定这种情况非常非常少发生。

假设我们有 3 列,一列的值范围是从 200 到 400,另一列是从 15k 到 78k,第三列是从 1 到 10。

这将产生一个问题,因为范围之间的差异将导致不同的距离标度,在这种情况下,分别为 100 秒、10000 秒和 10 秒,如果我们尝试应用距离度量而不应用标度,则第二列的重要程度将大于其他列。

所以,别忘了涂。

3.计算新产品和旧产品之间的距离

我想这是你最期待的部分,对吗?

如果是的话,我希望不会让你失望,因为解决方案真的很简单。

同样,这里您必须做的第一件事是定义您想要使用哪种距离度量。请参见下面简单有用的距离列表:

  • 欧几里得的
  • 曼哈顿
  • 闵科夫斯基

在继续之前,您必须选择最适合您的距离度量。

对于这个项目,我使用了欧几里德距离,所以我们只用两行代码就结束了整个项目:

idx_closest = np.argmin(
    [np.linalg.norm(new_obs_arr - np.array(x)) for x in df_old.values])
df_aux = df_old.iloc[idx_closest]\
    .to_frame()\
    .transpose()\
    .reset_index()

idx_closest 是旧数据帧的参考资料的索引值,用它我们得到整个对应的行并存储在 df_aux。

4.反向独热编码

流程如何考虑物料注册的工厂代码我们必须至少为工厂代码列恢复一个热编码的流程。

要恢复它,我们应该:

  • 定义由一个热编码过程创建的列。
  • 仅选择包含“1”的列。
  • 将其名称转换为原来的名称。
  • 在流程开始时删除由 one hot 编码创建的列。
def reverse_one_hot_encoder(df, col_nm):
    """
    Reverse the one hot encoding process

    Parameters
    ----------
    df : pandas.DataFrame
        data frame object with the old products that are more similar the new products
    col_nm : str
        name of the original column

    Returns
    -------
        df_result : pandas.DataFrame
        data frame object with the old products that are more similar the new products without the OHE procress
    """
    lst_stack = [x for x in df.columns if x.find(col_nm)>=0]
    df_aux = df[lst_stack]
    df[col_nm] = df_aux[df_aux==1]\
        .stack()\
        .reset_index()\
        .drop(0,1)['level_1']\
        .apply(lambda x: int(x.replace(col_nm+'_','')))\
        .to_list()
    for col in lst_stack:
        df = df.drop(col, axis=1)
    return df

5.计算比例因子

现在我们已经完成了比例因子步骤,也称为睡眠时间,因为我已经失去了思考它的时间。

好吧…好吧…我对这个家伙不公平,但我真的浪费了一些时间去思考这个问题,最终,导致了一些看起来太容易做到的事情,所以这可能只是我内心的愤怒试图在这里释放一点。

这就是为什么我在这上面浪费了这么多时间…

好了,记住距离步长的 A-B=C,我们可以猜测“好了,现在我已经定义了新行和旧行。那么,我为什么不,定义比例因子,只是除以 1,得到一个百分比结果呢?”

这种思维方式很好,但它的应用不太好,因为我们现在不是比较两个数字,而是试图从两个完整数据帧行的数组中获得百分比,而且没有简单的方法来做到这一点。

所以我们选择的解决这个问题的方法是定义一个数学函数,它随着我们已经计算过的距离的增加而减少。

我们认为对长距离比短距离进行更多的处罚应该是一件好事,所以我们尝试了“e^(-distance”,如果你是一个细心的人,你会注意到我说了“尝试”,这意味着它没有很好地工作。

问题是我们认为每一个被选择为相似的参考材料都应该和新的材料很接近,对吗?但在某些情况下,我们没有那么多的材料可以比较,我们最终只能得到最好的,而不是完美的匹配。

因此,为了避免距离增长过快,我们添加了结果组的平均距离值,以获得一个缓慢下降的比率。

# import Libs
import matplotlib.pyplot as plt
import statistics
import numpy as np
# simulate distance increasing
x = np.array(np.arange(0, 100, 0.001))
# get average value from distances
avg = statistics.mean(x)
# plot lines
plt.plot(x, np.exp(-(x**2)), 'b-')
plt.plot(x, np.exp(-(x**2/avg**2)), 'r-')
plt.legend(labels=['Original', 'Smothed'])
# add labels
plt.xlabel("Distance")
plt.ylabel("Saling Factor")
plt.show()

来源:作家

另一个要点是看产品价格,因为如果新产品的价格低于参考价格,这意味着它有机会卖出更多,但如果价格高于参考价格,就有可能卖出更少。

为了将这种或多或少的销售机会与比例因子相加,我们决定计算旧产品的价格占新产品的多少。

一旦我们有了基于数学函数和价格比的比例因子,我们就可以将两者相乘得到最终的比例因子。

结果

该算法导出包含五列的. csv 文件:

  • 位置
  • 产品
  • 参考 _ 位置 _ 代码
  • 参考 _ 代码
  • 比例因子

来源:作家

您可以使用它来模拟新产品的历史销售数据,然后对其应用任何预测算法!

最终提示

  • 安排一次会议,与您的主数据团队或任何在您的数据库中注册/创建新产品的团队进行交谈,因为他们可以很容易地告诉您新材料的初始特征。
  • 明智地选择可以作为新产品参考的材料。那些你已经停止工作,但仍然存在于你的数据库中的产品或新产品(自第一次销售后不到两三个月)可能不是最好的决定,因为它们可能没有良好的历史销售曲线。
  • 选择一个产品层次结构进行过滤,这样一旦减少比较样本,就可以加快合作时间,并且可能会比较更相似的产品,而不是在整个产品库中搜索。
  • 不要忘记,一旦你的新产品开始销售,它将收到真正的销售数据,你应该开始使用它来预测,而不是你生成的数据。

这就是了!

嗯,有了这个,我想你现在可以通过找到一个类似的旧材料来改进你的新产品,并扩大它的销售,作为你预测工具的输入!

希望这篇文章对你有帮助!

你可以在这里看到这个项目的代码:

[## rfpcordeiro/python-基于特征相似性的预测

算法来计算和定义数据库中与新产品最相似的产品,这样我们就可以使用…

github.com](https://github.com/rfpcordeiro/python-similarity-to-characteristic-based-forecast)

特别感谢 Pierre Palud,当我澄清了无数个关于定义比例因子的最佳方式的问题时,他一直耐心等待

表征和分析网络

原文:https://towardsdatascience.com/characterizing-analyzing-networks-d3a8f01eecfd?source=collection_archive---------34-----------------------

纽约市交通网络的初步分析

交通网络提供了一个极好的机会来确定当地人口的出行习惯、日常生活和使用数据驱动的方式来增强城市规划决策。在我们的分析中,我们专注于探索纽约市居民在 2015 年使用 1.46 亿次以上的出租车出行的出行模式。完整的代码、可视化和报告可以在 Github 库 中找到

之前工作:

基于 GPS 的交通网络已被详细研究用于交通流量分析和确定社会动态[1]。自行车共享数据集已用于根据使用概况对位置进行聚类[2]并预测自行车需求[3]基于 GPS 的出租车数据集已用于识别中国上海的移动模式[4]。

在[4]中,出行分布被描述为 3 种独立类型的组合,非负矩阵分解被用于从中国上海的 158 万次出行中识别 3 种模式。这是我们方法的核心,因为我们试图用类似的数据集来描述纽约市出租车的使用情况。之前的分析也用于从街道几何图形[5]和地铁地图[6]中生成交通网络图。

数据描述:

a) 原始数据:纽约市出租车&高级轿车委员会自 2009 年起公开提供出租车出行数据集[7]。我们使用这个数据集进行分析。完整的数据集包含每年约 1 . 5 亿次出行&每行代表一次出行,具有起点和终点、行驶距离、出租车费用、耗时等特征。我们使用的是 2015 年的数据集,总共包含 146,112,990 次出行。为了将地理位置数据与人口普查区域结合起来,我们使用了非常有用的纽约市土地使用数据集[8]。

b) 数据转换:我们对每次行程使用以下变量:

  • 行程起始时间戳
  • 起点(横向/纵向)
  • 行程停止时间戳
  • 停止点(横向/纵向)
  • 费用

使用这些行程,我们以给定行程的开始停止位置为节点构建我们的有向图。作为一个附加条件,我们只使用高出行次数的地点(对于给定的一对地点,一年中超过 500 次)。根据之前的工作,我们总结出将位置坐标四舍五入到小数点后两位也是一种选择,鉴于我们在分析包含 40,000 多个节点的数据集时遇到的困难,我们现在正在通过两种不同的方法来简化我们的网络:

  • 5 个曼哈顿街区一个节点
  • 使用 600 万次最频繁旅行获得 1275 条最频繁旅行的边
  • 在我们当前的网络中,每个节点代表其周围 200 米 x200 米的区域,每条边代表给定年份中两个节点之间的总出行次数

我们从时间戳中创建月、日、工作日、一天中的时间段等特征。我们在最初的分析中面临的一个问题是,由于网络本身的地理位置,我们有一个网络,其中多个节点代表具有多个入口的同一个位置(例如,Penn Station 有多个入口和出口&我们的网络有多个节点代表同一个真实世界的位置)

相同位置:多个接近的节点

我们决定将我们的数据集与美国人口普查局的人口普查区合并,这样就解决了上述问题。我们在最终网络中有 580+个节点,并分析了作为节点的人口普查区域和作为边的两个人口普查区域之间的行程数。

探索性分析:

1.每个月的出行量(图 1)在 3 月至 5 月间达到高峰,6 月以后大幅下降。这可以直接归因于天气模式,因为通勤者应该避免在低温或雨天长途步行。

2.对于我们的完整数据集,第一个图显示了度分布,而第二个图显示了 2015 年使用至少 500 次出行的边生成的图的度分布。

3.热图(图三)显示了 2015 年每小时的相对出行密度。根据这些信息,我们总结出最繁忙的时间是早上 6 点到 9 点。我们将大部分流量归因于日常工作通勤的用户,而在周末上午 12 点至凌晨 4 点之间,流量密度显著增加。我们正在寻找一种方法,对从我们的子集生成的网络结构进行类似的分析,以创建时间流量密度可视化。

4.我们分析了旅行的费用与持续时间的关系,发现了有趣的异常数量的恒定费用旅行。我们将这些旅行归因于:

  • 尖端四舍五入到最接近的 5/10
  • 导致延误的相同行程内的交通延误

旅行持续时间与旅行成本

全网络分析

整个网络近似表示为其实际地理位置,我们将节点大小和行程的外度绘制为边厚。我们观察到:

  • 郊区的服务少于曼哈顿、上东区/西区和市中心
  • 交通枢纽也是网络枢纽,办公区是下一个最接近的中心节点
  • 令人惊讶的是,东村和下东区也是整个网络中连接最少的,尽管这些地区在地理上不像郊区那样分开

当我们根据大于或等于 500 和小于 500 的旅行次数将节点分成两个子类别,并根据旅行总次数绘制入度/出度图时,出现了两个鲜明的对比。

图 5 中最上面的两个图形表示行程数大于或等于 500 的节点,蓝色图形表示入度与行程的比率,红色图形表示出度。瓶二图是针对行程数少于 500 的节点。

对于旅行次数> =500 的情况,图表最右侧的大部分异常值的物理位置在麦迪逊广场花园、佩恩车站等市内景点。这意味着大量的人从相对较少的地方来到这些景点,并且这些进来的地方中的大多数位于曼哈顿(例如,来自大约 200 个地方的 250,000 次旅行。平均 1250 次旅行)。

对于出行次数> =500 的情况,图表最右侧的大多数异常值的物理位置都在机场(拉瓜迪亚机场和 JFK 机场),它们的出行与学位比率要小得多,这意味着有少量的人来自各种地方。我们可以通过观察图的“尾部”来轻松识别连通性低的地方,我们发现这个比例越小,节点离曼哈顿越远。

跨纬度和经度的网络节点分布

我们将网络分为 3 个社区,使用 igraph 库中的多级社区检测。上面的图将这些社区按大小映射到全年离开每个节点的旅行次数。这三个社区可以描述如下:

  • 蓝色标签代表社区 A ,节点整齐地落在曼哈顿和邻近的新泽西地区,它们被证明是连接最好的节点。他们与曼哈顿(曼哈顿和新泽西地点)和其他两个社区(仅曼哈顿地点)联系紧密
  • 绿色标签代表社区 B ,它代表与城市北部的出租车连接性最高的位置,这反过来是因为城市交通连接性(公交车/地铁等)最差——通常是向北
  • 红色标签代表社区 C,代表北纽约市,皇后区&布朗克斯区,我们知道它们在同一个社区中,因为总体上向南的连通性最低。
  • 我们想证明 Dash & Rae[11]使用国家数据集确定的郊区结构在地方层面是否成立,这就是为什么这个结果很有趣——基于我们的初步探索,我们的推断是,在一个城市内,它不成立。

我们绘制了离开纽约主要地区的旅行快照,这表明,曼哈顿是所有人中联系最紧密的,而大多数从下东区、东村和布鲁克林出发的旅行最终都前往纽约的北部。一小部分最终进入了社区本身。

  • 城市与其他网络的不同之处在于,较小的重新路由通常非常简单,即绕过一个街区很容易,通常不会导致成本、时间或路由长度的显著变化。
  • 像纽约这样的城市除了结构枢纽(地铁枢纽、机场和公交枢纽)之外,不会有单一的关键位置,这一点从程度中心性分析中非常明显。最接近纽约市中心位置的是它的街道,特别是百老汇和第六大道。百老汇从北向南延伸,而第六大道从南向北延伸(单行道)。
  • 从分析中得出的另一个有趣的观察结果是,东村& below 在出租车使用方面与郊区相似。这令人惊讶,因为正如托布勒所说,地理第一定律是“一切都与其他一切相关,但近的东西比远的东西更相关。”[12]&第一个定律是空间相关性和空间自相关的基础,专门用于空间插值的反距离加权方法[13]。

参考文献:

  1. 页(page 的缩写)卡斯特罗、张、陈、李、潘。从出租车 gps 追踪到社会和社区动态:一项调查。ACM 计算机。Surv,2013 年 12 月。
  2. C.艾蒂安和欧·拉蒂法。基于模型的计数序列聚类在自行车共享系统使用挖掘中的应用。ACM Trans 智能。系统。技术。,2014 年 7 月
  3. D.Singhvi,S. Singhvi,P. Frazier,S. Henderson,E. Mahony,D. Shmoys 和 D. Woodard。预测纽约市自行车共享系统的自行车使用量。2015 年在 AAAI 举行的研讨会。
  4. 彭春、金霞、黄家昌、史敏、P (2012)城市出租车出行中的集体人员流动模式。《公共科学图书馆·综合》7(4):e 34487 . doi:10.1371/journal . pone . 20048363637
  5. 页(page 的缩写)克鲁西蒂、v .拉托拉和 s .波塔。城市街道空间网络的中心性度量。物理评论 E,73(3):036125,2006。
  6. derble S(2012)地铁系统的网络中心性。PLoS ONE 7(7): e40575。doi:10.1371
  7. 纽约市出租车数据:http://www . NYC . gov/html/TLC/html/about/trip _ record _ data . shtml
  8. 纽约市土地使用:【https://www1.nyc.gov/site/planning/index.page
  9. W.崔,周海辉,瞿海辉,黄炳春,李,“基于几何的边聚类在图形可视化中的应用”,IEEE 可视化与计算机图形学学报,第 14 卷,第 6 期,第 1277-1284 页,2008 年 11-12 月 doi: 10.1109/TVCG.2008.135
  10. Holten,D . & Wijk,J,2009,“图形可视化的力定向边缘捆绑”,计算机图形论坛,28,3,第 983-990 页,Business Source Premier,EBSCO 主持人,2016 年 11 月 12 日查看。
  11. Dash Nelson G,Rae A (2016)美国的经济地理:从通勤到大区域。PLoS on 11(11):e 0166083 . doi:10.1371/journal . pone . 0166083
  12. 一部模拟底特律地区城市发展的电脑电影。经济地理 1970 年;46: 234–240.
  13. https://en . Wikipedia . org/wiki/to bler ' s _ first _ law _ of _ geography

原载于nilesh-Patil . github . io

夏琳·钱布利斯:从心理学到自然语言处理和应用研究

原文:https://towardsdatascience.com/charlene-chambliss-from-psychology-to-natural-language-processing-and-applied-research-3845b1c83ac0?source=collection_archive---------20-----------------------

技术领域的女性系列

Primer 公司一位机器学习工程师的采访。艾

图片经 Charlene 许可后重新使用,原文来源:https://towards data science . com/using-word 2 vec-to-analyze-news-headlines-and-predict-article-success-CDE da 5 f 14751

在过去的十年中,人们对数据科学的兴趣呈指数级增长,越来越多的人开始转向该领域。2020 年,关于转入数据科学职业的文章和 YouTube 视频比比皆是。然而,对于许多人来说,关于这种转变的许多关键问题仍然存在:你如何从社会科学背景进入数据科学?心理学等领域中哪些最重要的技能可以应用于数据科学?

Charlene Chambliss 拥有一条鼓舞人心的非传统职业道路。目前,她利用最先进的自然语言处理技术“构建更智能的工具来分析海量信息。”在过去的两年中,她撰写了关于 NLP 主题的文章,包括用于命名实体识别的 BERT 和用于新闻标题分析的 word2vec 等等。然而,在她目前担任机器学习工程师之前,她曾在市场营销、心理学、研究领域担任职务,并在护肤品行业担任数据科学家。

Amber:你能告诉我们一些你的背景吗?
夏琳:当然!我走了一条不同寻常的数据科学之路,所以我将从头开始,详细阐述一下这条路对我的意义。

我在一个农业小镇(加利福尼亚州的莫德斯托)长大,我父亲在那里的西夫韦公司工作(现在也是!)而我妈妈是个全职妈妈。他们真的让我意识到认真对待我的教育的重要性,这对我来说很好,因为我喜欢学习,我喜欢让他们以我为荣。

我从小就想成为一名科学家。我喜欢修补和学习事物如何运作。我妈妈满足了我的好奇心,带我去了图书馆(我会带着一摞 12 本书回家),让我在厨房里帮她(烹饪=化学!),偶尔给我买玩具科学包。

这种兴趣一直持续到高中和大学一年级,那时我决定学习化学工程,成为一名香料科学家,因为化学是我最喜欢的学科。我(很可爱地)认为,我应该简单地发明新的口味,让健康食品味道更好,这样人们就可以更容易地吃沙拉和蔬菜,从而整体上更健康。我讨厌吃沙拉和蔬菜,所以 17 岁的我认为我很聪明,这是一个惊人的解决方案。

“一般来说,学习社会科学是习惯于处理模糊、难以定义的问题的一种很好的方式,这种技能是交付决策者实际上会感到舒适的数据科学工作的关键。”

整个高中时期,我都保持着对教育的专注和职业道德,并在斯坦福大学读了本科。坦白地说,这对我来说是非常意外的——我以为如果我真的幸运的话,我会去加州大学戴维斯分校和加州大学伯克利分校。大约一半从我高中毕业的人最终都没有上大学,所以即使是这些人也觉得是相当高的志向。那年,在我的 500 名毕业班学生中,我想只有大约 5 人进入了“顶尖学校”(伯克利、斯坦福、哈佛)。

当我去斯坦福的时候,我真的没有预料到的是我所面临的文化冲击。斯坦福大学的绝大多数学生来自高收入家庭,家庭收入中值为 167,500 美元。总的来说,他们是那种有受过大学教育的专业父母的孩子,上的是镇上最好的、资金最充足的高中,在他们遇到困难的任何领域,都请了家教来帮助他们。与此同时,我在 HH 收入大约是其四分之一的情况下长大,我在某些领域相对于同龄人的准备程度反映了这种差异。(我的父母和老师都很好,已经尽了最大努力,但资源有限,我们能做的也就这么多。)

突然,我发现自己对自己的能力(尤其是数学和计算机科学方面的能力)感到非常不自信,真的怀疑自己是否能达到其他学生的水平。我没有意识到我们的背景如此不同,因为没有人到处谈论这种事情,所以我把表现的差异归因于我自己能力的缺乏。我也是我高中唯一一个在那年去斯坦福的人,所以当我到那里的时候我不认识任何人,也没有人可以谈论我正在经历的事情。在斯坦福大学的日子里,冒名顶替的感觉从未真正消失过,但至少我变得更擅长伪装,直到我成功为止。

我的确在斯坦福上完了学,尽管我最终没有攻读化学工程,而且还需要在大三后休学一年,以帮助处理我父母的离婚(我妈妈是残疾人,需要帮助卖掉我们家的房子并搬出去)。2017 年,我获得了心理学学士学位——这是我直系亲属中第一个获得 4 年制学位的人——但我觉得由于缺乏指导和榜样,我在这一路上犯了很多错误。事实证明,即使只是寻找我的第一份工作也很困难,因为我真的只能向职业中心寻求建议,如何为“受过教育的专业人士”在就业市场上导航。他们提供的小册子和 30 分钟的咨询并不能真正填补所有的空白,但经过大量的研究和参加招聘会后,我找到了一份为一家小机构做社交媒体营销的工作。

作为一个只有学士学位的心理学专业学生,我没有过多地谈论一个人的财务和整体职业前景,但在我从事那份工作的过程中,我清楚地认识到,除非我做出重大改变,否则我不会获得我想要的职业发展。所以在 2017 年底,我决定进入数据科学,特别是专注于机器学习,并投身于 GRE 研究,以便我能在 2018 年秋季入学前及时提交申请。(在下一节中,我将更详细地介绍我为什么选择数据科学,尤其是 NLP。)

我按计划注册了我的硕士学位,完成了我的课程,并在课外尽可能多地学习,尤其关注统计学、线性代数、Python 和机器学习。学位课程都是 R 语言的,所以我完全靠自己学习 Python,结合了在线课程和一本 1500 多页的教科书(学习 Python )。在第一年快结束的时候(2019 年春天),我在 Curology 找到了一份数据科学实习,并在那里工作了整个秋天。然后,在我第二年年初,我通过 SharpestMinds 与一位了不起的导师尼娜·洛帕蒂娜(Nina Lopatina)合作,因为我决定专注于获得一个做 NLP 的角色。在为期 10 周的指导结束时,我开始找工作,并在 2019 年 12 月获得了全职加入 Primer 的邀请。

我需要推迟我的 MS 课程的最后一个学期开始全日制学习,这是一个艰难的决定,但这种经历对我来说更重要,所以我这样做了。事实证明,这个决定非常及时,因为仅仅几个月后,新冠肺炎·疫情就摧毁了最近的毕业生就业市场。我有同学还在努力找工作,我也很容易陷入同样的境地。我意识到我非常幸运,我掷骰子的结果如此之好。

总而言之,从相对较少的数学和编程经验的背景下,从市场营销过渡到全职机器学习工程师角色花了大约 2 年时间。(2017 年之前,我只上过单变量微积分,基础/入门统计,一门 Java 编程课。)

答:在从事数据科学行业之前,你在斯坦福大学学习心理学。你能告诉我们你在那里的经历是如何影响你进入数据科学的职业道路的吗? C:一般来说,研究社会科学是习惯于处理模糊的、难以定义的问题的一种很好的方式,这种技能是交付决策者实际上会感到舒适的数据科学工作的关键。这是一种墨菲定律思维模式,适用于实验结果:我已经变得非常关注任何可能“混淆”或以其他方式影响我的分析结果的东西,并且我可以在适当的时候提醒注意潜在的警告。这样,涉众可以利用他们的领域知识来决定他们认为这些事情对我们的结论是否重要,我们可以相应地调整实验/分析。

除此之外,我可能已经花了整整一年半的时间在心理学实验室进行实验。虽然这类职位涉及很多“繁重的工作”,如数据输入,但你也可以坐在前排,了解科学研究实际上是如何进行的,从数据收集到最终的统计分析,你还可以参与其中的一些决策。这让我为数据科学工作流做好了充分的准备,也给了我一些实用的技能(比如处理电子表格)和一种积极进取的态度,这在以后会很有帮助。

答:之前,你在 Curology 担任数据科学实习生。你能讨论一下数据科学在护肤品行业是什么样的吗?你和你的团队寻求回答什么类型的问题?你在 Curology 工作期间做过的最有趣的项目是什么? C:我认为我在 Curology 的经历是一个很好的例子,说明了数据科学在 D2C(直接面向消费者)业务中的一般情况,尤其是在创业背景下。通常情况下,以消费者为中心的企业首先需要的数据(当然是在数据工程师之后)实际上只是大量的描述性统计数据,通常被称为“消费者洞察”

因为我在用户获取部门工作,所以我特别专注于回答问题,这些问题将帮助我们在许多不同的获取渠道中做出更好的营销决策。80%的时间,我都在针对我们的数据仓库编写 SQL,以更好地理解不同客户群的行为,并跟踪该行为如何随时间发展,并将这些发现转化为可解释的仪表板,供团队的其他成员使用。其余 20%的时间,我使用 Python 来分析和可视化客户的调查反馈,以更好地了解他们喜欢和需要 Curology 的什么。

所以我要问和回答的一些问题是:

  • 顾客的护肤目标如何根据他们的人口统计数据(性别、年龄等)而变化?)?对每一部分客户来说,什么是最重要的,我们如何才能确保满足他们的每一项需求?
  • 我们的哪些渠道拥有“最顽固”的客户,即倾向于与我们呆在一起时间最长的客户?还有其他行为或偏好与订阅时长相关吗?
  • 我们能否建立一个模型,利用我们拥有的客户行为历史数据来预测注册时的客户终身价值(LTV)?(由于抽样考虑,当您的客户群增长迅速时,这实际上非常困难!)

我学到了很多。用 SQL 做数据分析不仅仅是帮助你学习 SQL;它实际上帮助你进行分析性思考,尽管这听起来很老套。您首先必须学会将某人关于客户的自然语言问题翻译成适当的指标(这些指标通常有不同的过滤条件和假设,这取决于预期的用例!),然后还要学习如何使用 SQL 代码以数学和技术上正确的方式实际执行它。有时,您甚至必须确保使用正确的表/数据,因为表已经过时,由于管道中的错误,并非所有数据都进入了表中,或者 X 度量在 6 个月前才开始被跟踪,等等。做这种工作时,你需要牢记许多实际的考虑因素。做坚如磐石的数据分析和机器学习一样具有挑战性,尽管有时出于不同的原因。

图片由 Charlene Chambliss 提供

你一直都知道从事数据科学工作是你想做的吗?是什么激励你从事自然语言处理的职业?另外,你能告诉我们一些关于你的 初级读本的工作吗?Ai 应用研究团队长什么样? C:一点也不!我不认为我们今天在数据科学领域工作的许多人能够预见到这个领域的崛起。直到大学四年级,我才真正了解应用统计学在私营部门的广泛应用。

当我获得学士学位毕业并开始我的第一份市场营销工作时,我很快发现这并不适合我。我开始研究我的替代方案,看看是否有一个职业更适合我的个性和价值观(坦率地说,工资更高,因为入门级的营销工资仅够在湾区过上温饱的生活)。

经过几个月的挖掘,我发现了数据科学。这是一项具有智力挑战性的工作,将对经济和整个社会产生巨大影响。不仅如此,我还注意到从事数据科学职业的人比我在其他地方看到的更关心伦理。看到这一领域的人们真正关心他们的工作会对人们产生怎样的影响,真的让我产生了共鸣,这最终帮助我决定做出转变。

也就是说,我仍然不确定,因为我在大学时有过数学和计算机科学的负面经历,我不确定我能应付得来(哈哈)。在斯坦福大学的第一个学期,我在一门微积分课程和一门计算机科学课程中取得了有生以来最差的成绩,这让我开始认真思考自己是否适合学习这些课程。当我开始这段旅程时,我必须说服自己,我可以通过使用客观的衡量标准而不是自己的感觉来取得成功:“我在 SAT 考试中得了 X 分,而 CS 专业学生在 SAT 考试中的平均分是 Y(其中 X > Y),所以我应该能够像这个领域的其他人一样学习数学和其他材料……”

“我喜欢 NLP,因为我可以直接帮助人们摆脱噪音,开始了解他们需要知道的东西,以便更有效地生活和工作。”

后来,在攻读统计学硕士学位期间,我发现我本科表现不佳的主要原因是缺乏良好的学习习惯,以及对数学这门学科缺乏兴趣。在高中,我可以等到考试前一天晚上才开始学习,并且从不在课外阅读课本,但在斯坦福不再是这样了。随着时间的推移,我改进了我的学习习惯,当我在高年级选修了两门统计学课程时,我已经能够在这两门课程上都获得高分了。类似地,当我开始了解数学和统计数据通过数据科学应用于现实世界的一些令人着迷和意想不到的方式时,我的头脑真正意识到了数学的好处,突然间掌握数学的动力就在那里了。在我注册的三个学期里,我的硕士课程都是全 A。

想到就在几年前,我真的不喜欢数学和编程,但现在我每天都在使用它们,并真正享受其中,这仍然有点疯狂。我很想强调一点,不要把自己放进一个“数学人”/“不是数学人”的盒子里有多重要,编程也是一样。这两种技能都是简单的工具,这些工具具有不可思议的力量,可以让你在你关心的任何其他领域或兴趣中变得更加有效,无论是艺术、法律、社会科学,还是更传统的协同作用,如工程。如果你能克服早期的抗拒和恐惧,一旦你能够开始使用这些工具做你关心的事情,就会有能力和成就感等着你。

至于我为什么特别选择自然语言处理(NLP),有几个原因。在职业层面上,我认为 NLP 社区更欢迎来自非传统背景的人,相对于像计算机视觉这样的领域,我只看到来自计算机科学、数学、物理和电子工程背景的人。在更个人化和基于兴趣的层面上,我认为 NLP 是最适合帮助解决信息过载问题的领域。有无穷无尽的信息要消耗,这加剧了每个人的压力,也削弱了从事知识工作的人的生产力。我喜欢 NLP,因为我可以直接帮助人们摆脱噪音,认真对待他们需要知道的事情,以便更有效地生活、做出明智的决定和工作。

我在 Primer 的工作与信息过载问题直接相关。在 Primer,我们利用强大、先进的 NLP 模型从嘈杂、非结构化的文本数据中提取结构化信息。这有助于我们的客户更快地获得他们需要的信息,而不是让个人亲自研究数据。一些分析师每天工作 12 个小时,只是因为他们没有办法快速阅读和消化他们负责更新的海量信息,我们希望改变这种情况。

我的团队 Applied Research 的任务是培训、测试深度学习模型,并将其用于 Primer 的产品,然后将这些模型集成到我们的数据管道中,或通过 API 将其公开使用。我们还创建可重复使用的脚本和资源,允许人们根据自己的数据训练自己的模型。这项工作不仅涉及模型实验和工程,还涉及与其他团队的大量协作,这些团队更直接地工作在我们的产品和基础设施上。

就周与周而言,我认为一半的时间用于编写模型训练/评估、数据预处理和其他典型的机器学习任务的代码,另一半时间用于交流工作:与产品经理讨论计划、规格和进展,与我们的数据标注团队合作为新的和现有的任务创建数据集,以及向整个公司介绍我们模型的新发展和改进。

答:在 SharpestMinds 实习期间,您开发了一个工具包,用于培训“基于 BERT 的命名实体识别模型”,用于俄英机器翻译中的错误分析前端。你能更详细地描述你的项目并分享你最重要的三点吗? C:TL;该项目的博士是我的导师需要一种方法来训练 BERT 模型进行俄语和英语的命名实体识别,我的任务是学习如何在 PyTorch 中用 BERT 进行 NER,然后以 git repo 的形式构建整个管道,可以在本地克隆和运行。

然后,得到的训练模型可以用于在用户界面中突出显示实体,例如人、地点和组织,其中翻译者可以识别单独的模型(俄语到英语的翻译模型)在将姓名从俄语翻译成英语时是否出现了错误。我认为这——使用这些模型来创建更强大、更人性化的软件——非常酷,这个项目真的激发了我构建 ML 驱动的工具和界面的兴趣。

在我做这件事的时候,正好有一篇关于使用 BERT 来做 NER 的博客文章,代码对我来说并不是现成的,所以不用说:在这个过程中有很多问题需要解决!(不管怎样,感谢作者托拜厄斯·斯特巴克,这是一篇非常有用的帖子;如果没有它,我可能要花更长的时间才能开始。)

对于任何想了解更多细节的人,我在即将结束时为 In-Q-Tel 实验室的博客写了一个关于该项目的 2 部分系列文章。这里是第一部第二部,回购可以在这里找到

图片由 Charlene Chambliss 提供,原文来源于此来源:https://gab 41 . lab 41 . org/how-to-fine-tune-Bert-for-named-entity-recognition-2257 b5 e 5 ce 7 e

你对其他想进入这个领域的女性有什么建议?C:如果你还在上学(尤其是本科),你有三个好的选择:学习计算机科学并接受广泛的计算机科学教育,学习定量学科,如应用统计学、经济学或工程学并结合计算机科学课程,或者学习定性学科,同时自学如何将 DS/ML 应用于你的领域。获得研究经验,特别是如果你想攻读硕士或博士,如果你认为你更喜欢行业,获得行业经验(每年夏天都有实习,甚至可能在学年中兼职)。无论您选择哪种方式,都要意识到对 DS/ML 背后的数学(统计估计和概率、线性代数和微积分)的一些概念性理解和良好的编程技能仍然是大多数角色成功的必要条件。

如果你已经走出校门,想改变自己的职业生涯,那就研究一下业内人士的职业道路。尽量多关注那些背景与你相似的人:例如,如果你来自一个不涉及太多数学或编程的“非技术”领域,注意其他人是如何从非技术领域过渡过来的。找出他们需要做什么来证明他们有足够的技术技能。联系这些人,看看你是否能抽出 30 分钟的时间打个电话,问他们一些具体的、有针对性的问题,比如你需要做些什么才能胜任你感兴趣的职位。

如果你是从一个不相关的背景过渡过来的,需要帮助设计和界定一个令人印象深刻的专业质量的数据科学项目并准备面试,职业转换者也应该强烈考虑参加一个导师项目,如 SharpestMinds。如果你像我一样来自一个收入较低的领域,收入分成协议是一个救星,因为在你真正被数据科学职位聘用之前,你不必支付任何费用。

另外, Vicki Boykis 的文章《现在的数据科学不同了》(去年写的)是任何有抱负的数据科学家的必读之作。我不同意参加 Coursera 课程甚至训练营的每个人都一定有资格进入入门级数据科学领域,但这些角色的竞争绝对是激烈的,你需要做些什么来将自己从众多有志者中区分出来。正如 Vicki 所建议的那样,首先在普通软件工程或数据分析中担任一个相邻的角色,对于培养技能和进入职场非常有用。

答:我们的读者如何与你联系,参与你的项目?你可以在 Twitter 上关注我,在 LinkedIn 上联系我,或者给我发邮件。我现在非常专注于我在 Primer 的工作,但如果我将来开始任何副业,我一定会分享!

除了作为机器学习工程师在 NLP 领域进行创新,Charlene 还是 SharpestMinds 社区的活跃成员。她专注于社会科学和技术的职业道路和多学科经验继续推动女性技术人员在数据科学领域进行创新。今天,Charlene 正在解决 NLG 和 NLU 最棘手的问题,从而给予人们突破噪音和理解大规模世界的力量。作为拥有非传统职业道路的数据科学家的榜样,Charlene 激励来自不同背景的女性民主化 NLP 领域。

特别感谢 Charlene Chambliss 允许我为这个系列采访她,并对 TDS 编辑团队支持这个项目表示衷心感谢。

你认识一位鼓舞人心的科技界女性吗,你希望她出现在这个系列中?你是否正在从事任何你希望我写的很酷的数据科学和技术项目?欢迎给我发电子邮件,向 angelamarieteng@gmail.com 寻求意见和建议。感谢阅读!

[1]从 LinkedIn 获得的其他信息,可向作者索取。

参考资料:

"《斯坦福大学的经济多样性和学生成果》——《纽约时报》. "n.d .于 2020 年 8 月 15 日进入。https://www . nytimes . com/interactive/projects/college-mobility/Stanford-university。

"如何为命名实体识别微调 BERT | Charlene cham bliss | gab 41 . "n.d .于 2020 年 8 月 15 日进入。https://gab 41 . lab 41 . org/how-to-fine-tune-Bert-for-named-entity-recognition-2257 b5 E5 ce 7e。

"夏琳·钱布利斯(@blissfulchar)文章—中等."n.d .于 2020 年 8 月 15 日进入。https://medium.com/@blissfulchar.

“使用 Word2vec 分析新闻标题并预测文章成功| Charlene cham bliss |走向数据科学。”n.d .于 2020 年 8 月 15 日进入。https://towards data science . com/using-word 2 vec-to-analyze-news-headlines-and-predict-article-success-CDE da 5 f 14751。

“(19)夏琳·钱布利斯|领英。”n.d .于 2020 年 8 月 15 日进入。https://www.linkedin.com/in/charlenechambliss/.

"底漆|压机。"n.d .于 2020 年 8 月 15 日进入。https://primer.ai/press/.

在谷歌数据工作室制作美国新冠肺炎病例数据图表

原文:https://towardsdatascience.com/charting-us-covid-19-cases-data-in-google-datastudio-6380aecdc5a5?source=collection_archive---------35-----------------------

谷歌数据工作室可视化美国新冠肺炎数据的逐步入门指南。

新冠肺炎数据工作室仪表板

在这个不确定的时期,你如何理解美国疫情州正在发生的数据海啸?在过去的几个月里,许多美国人发现自己每天都在查看新冠肺炎病例的传播情况。随着美国大多数州进入就地避难模式,像约翰霍普金斯大学和 91-DIVOC 这样的资源成为那些寻求保持信息的人的日常避难所。在今天的帖子中,我们将使用 Google DataStudio 创建我们自己版本的基于网络的、交互式的、视觉上吸引人的新冠肺炎仪表板。这样,我们将更好地理解所使用的数据,决定我们认为最相关的数据类型,并保持对可视化此类数据的最佳方式的控制,以帮助我们的受众最大限度地理解这些数据。在构建这些数据的过程中,我们将利用强大的 GDS 应用程序的各种对象和功能:Google Sheets connector、计算字段、记分卡、表格、地理地图、折线图和组合图、日期范围、过滤控件和最近发布的可选指标,这些是我们将介绍的一些功能,但不是全部。

本文原载于作者的 博客

数据选择和初始准备

任何数据可视化项目的第一步都是确定我们需要绘制的数据类型。在我们的案例中,如果适用的话,按州显示病毒的传播以及其增长率的潜在逆转将是有帮助的。对于我们的项目来说,纽约时报似乎是一个足够可靠的数据来源——幸运的是,他们在 GitHub 存储库上提供了这些数据。事实上,我们可以选择在州或县一级使用这些数据。为了简单起见,我们将在报告中使用州级粒度。看着 NYT 的档案,他们似乎只显示累计 COVID 病例和死亡人数。虽然累积疫情图表似乎主导了新冠肺炎的报告空间(即约翰霍普金斯),但我认为其他也提供增长率的门户网站( 91-DIVOC 等)更适合监测这种疾病的传播。

在累积报告的情况下,我们将始终(除了稍后确定的数据问题)让第二天的数据点等于或大于前一天的数据点;因此,从生成的图表来看,很难确定逐渐增长的水平。或者,只观察新病例,或者更好的是,绘制病例增长图可以帮助我们评估感染是否在下降。

我们还需要承认这样一个事实,即确诊病例数据不能提供美国各州之间的同类比较,因为不同的州在测试其居民时有不同的准备水平。与此同时,在衡量疾病的传播,特别是与 COVID 相关的死亡时,忽视州人口是不负责任的。(可以说,这是对潜在感染率的更准确的衡量,但仍然不准确,因为在按州、市等划分死因时,规则各不相同,而且常常是主观的。)为了查看基于人口的指标,我们还将把美国人口普查数据混合在一起。

使用 NYT 的数据,我们将按州/日期组合计算新增病例和死亡。为了进一步开发我们的数据,我们还可以计算日同比增长率 h 和 7 天移动平均增长率。作为最后的数据准备步骤,我们需要将 COVID 数据与州人口混合,以估计每日人均病例和人均死亡指标。

自然,如果没有一些数据清理,我们的工作就不会完整。根据这一消息来源,佐治亚州的累计新冠肺炎病例总数在本报告从 4/11 的 12261 例增加到 4/12 的 12103 例时,发生了 -158 例的变化。爱达荷州经历了相似的命运,当它的总数因 2 病例从 5 月 2 日报道的 2061 例减少到 5 月 3 日的 2059 例。在这些关键时刻,当我们需要“数据、证据和科学”的时候,这些数据质量问题就显得特别麻烦。世界卫生组织报告我们有 -99(!)周日新增新冠肺炎病例。显然,他们改变了报告方法,以与 CDC 保持一致,但没有想到进行追溯调整。为了说明这些不规则性,并使误导性增长率的影响最小化,我用值 1 替换了所有产生负新情况的计算。这意味着新病例的总和将与累计总数不匹配,但我认为这将是我们在这里处理的两个邪恶中较轻的一个。为了规范我们的图表比例,我对所有超过这个值的读数应用了 200%的日增长率上限。与此同时,我还从该工作表中排除了所有美国地区。

您可以访问结果 Google Sheets 工作簿 以了解我们流程中的后续步骤。请确保将其保存到您的 Google Drive 中。

创建新报告

与许多其他数据可视化应用不同,DataStudio 不需要安装软件,谷歌也不收取使用该程序的任何费用。我们只需要登录我们的谷歌账户,导航到 DataStudio 的主页(最好使用 Chrome 浏览器)就可以开始使用这个强大的工具了。单击左侧面板顶部的大加号或主菜单上的第一个选项,开始一个新报告。

建立与数据源的连接

在我们有机会命名我们的报告之前,我们被要求连接到感兴趣的数据源。如果我们已经为另一个可视化使用了一个数据源,只需要再次使用它,我们可以点击 My data sources 选项卡,从可用的数据源中进行选择。否则,我们必须从 DataStudio 集成可用的 17 个数据连接器中选择一个来创建新的数据源。幸运的是 Google Sheets 是可用的连接器之一,让我们点击它。

然后,我们将导航到包含我们的数据的工作簿,并选择包含它的实际工作表。您可能还记得,我们的文件名为'新冠肺炎 _ 状态日期,工作表名为'状态数据。做出选择后,保留所有其他默认设置,单击“添加”继续,然后通过单击“添加到报告”按钮确认您添加此数据的意图。

然后 Google 向我们展示了一个报告的默认视图。在继续之前,让我们确保我们的数据源为我们的数据使用正确的数据类型。选择“资源”菜单和“管理添加的数据源”子菜单,我们将进入下面的视图,在这里我们需要单击“编辑”来开始我们的探索。

虽然所有其他数据字段似乎都符合我们的标准(稍后将详细介绍),但需要将“State”字段从使用 Text 数据类型调整为使用 Geo 数据,更准确地说是使用 Region 数据。选择后,按“完成”、“继续”和“关闭”按钮顺序操作。

报告格式和布局选项

我们现在已经完成了工作中最繁琐的部分——处理数据,并准备开始进行更有创造性和趣味性的部分——实际的数据可视化。

现在,我们已经准备好命名我们的报告,为我们的仪表板选择合适的样式和大小。要重命名当前标题,只需用您喜欢的名称覆盖页面左上角的文件名即可——我将把这个破折号称为“各州新冠肺炎案例”。然后,让我们通过选择该对象并按下 Delete 键来删除默认情况下为我们创建的不需要的数据表 DataStudio。

谈到报告主题,DataStudio 提供了十几个选项;让我们导航到窗口右侧面板上名为' Edge '的那个,并选择它作为我们的主题。最后,让我们通过将选项卡选择从“主题”更改为“布局”来调整画布的大小—选择适用于此报告上的所有页面,或者右键单击报告并遵循“当前页面设置”来仅对所选页面进行调整。选择“页面”菜单—“当前页面设置”也可以做到这一点。我将设置一个自定义的画布大小1600像素宽和 800 像素高。我们的报告开始成形了:

任何使用 Google Sheets 产品的人都会发现 DataStudio 的界面和功能非常熟悉。

  • File 菜单允许我们使用不同的选项来共享我们的报告(很像同名的 Sheets 功能)、复制现有报告、创建新报告等等。

  • 编辑菜单将让我们执行与该菜单相关的典型功能:复制、粘贴、删除、撤销等。

  • 视图菜单选项乍一看可能相当出乎意料,但随着时间的推移,肯定会变得更有意义。如果您的主题没有删除默认的网格选项,您可以使用此处的命令来控制报告的网格。如果您希望根据数据源中的最新更新来刷新报表,您也可以“刷新数据”(?!)从这个菜单。

我们可以使用页面*菜单向报告添加新页面、重命名、复制/复制现有页面以及浏览报告。

当您的文件中有多个页面时,您可以通过排列*菜单来控制它们(包括它们的过滤器选项)。

我们已经利用了资源*菜单下的“管理添加的数据源”功能,您还可以管理和控制其他报告功能:过滤器、混合数据、参数等。

  • Help 会做你期望从这个菜单中看到的事情,有趣的是,它还可以让你通过请求一个你希望添加到程序中的功能来引起谷歌工程师的注意。

*我们跳过了最有趣的菜单— Insert ,它使我们能够实际添加各种元素:图表、图像、文本、日期和过滤控件,以及报表的形状。

许多这些常用的对象也可以通过点击程序工具栏上的相应图标来调用。单击“添加图表”按钮,我们会看到各种图表对象,可以在报告中使用:数据和数据透视表、记分卡、折线图/条形图/饼图/面积图/散点图/子弹图、地理图和树形图:

使用非图表对象

我们现在准备创建我们的仪表板。我最喜欢的 DataStudio 功能之一是完全控制画布——我们可以将对象放在任何我们喜欢的地方,并且我们可以轻松地调整它们的大小以适应我们的需要。

首先,我们将通过点击文本框对象(也位于插入—文本菜单下)为我们的报告添加一个标题标签。

让我们将这个对象放在页面的左上角,我将它命名为“美国新冠肺炎州案例”。然后让我们调整字体设置——将字体设置为粗体,将默认字体切换为机器人字体,并将字体大小更改为 20 。作为最后一步,谷歌似乎不能识别单词“COVID ”,让我们使用右键菜单选项将它添加到程序的字典中。

如果我们还指定了上次报告日期,这可能会对我们的读者有所帮助,上次报告日期恰好是在撰写本文时于 5/10/20 检索到的 5/9/20 。为了引用我们的来源,我们将使用另一个文本框,并将其放在我们页面的底部。在文本属性面板中的左对齐按钮的正下方,我们可以找到插入链接

按钮,让我们添加一个超链接到我们的文本。通过超链接向导,我们可以提供要显示的文本,共享链接的实际 URL,并确保链接将在新的浏览器选项卡中打开:

GDS 使添加图像到我们的仪表板变得很容易,在工作中你可能会在你的页面上加入公司的标志。出于我们的目的,让我们通过点击图像按钮来添加一个稍微修改的描绘冠状病毒的无属性图像

紧靠文本框的左侧(也可在插入-图像菜单中找到。)我们现在有两个选择:从本地驱动器上传或者提供图片 URL。我们将把这个控件放在我们的画布的右上角。

列表中的下一个是日期范围控件/过滤器

这给我们的报告增加了一层互动性。为了将观众的注意力吸引到这个控件上,让我们继续更改这个日期筛选控件的背景颜色,同时保持一致的字体。我们需要利用位于画布右侧的上下文日期范围属性面板:

我们也有几个选项来管理实际日期范围,考虑到我们的数据集,让我们满足于从 3/8/20 开始的固定日历(大多数州在此之前没有开始报告确认的 COVID 病例,那些开始报告的州:华盛顿州、加利福尼亚州、纽约州各有不到 200 例病例)到 5/9/20(可获得的最后报告日期):

Next control 在技术上被认为是一种图表,但在我的书中,它是一种指标读数,DataStudio 称之为记分卡:

可以通过选择插入菜单并转到记分卡,或者通过工具栏上的添加图表按钮找到该控件。通过记分卡面板使用数据选项卡,我们可以将其指标设置为新案例汇总为总和。这将使我们能够在指定的时间段内对所有确诊病例进行累计。注意日期范围维度设置为我们的日期【日历】控件。我们一次只能对该控件使用不超过一个指标(此处也提供可选指标选择),并且不允许非日期维度:

当谈到样式标签时,让我们确保我们的指标使用的是紧凑的数字(百万、千等),将我们的字体改为 Roboto ,大小为 24 。最后去掉所有边框,让这个控件完全透明。请注意,作为持续改进和推出增强功能的一部分,GDS 最近在其列表中添加了条件格式功能:

为了直观地将该记分卡与其他控件分开,让我们将它包含在两个 lin e 形状(Insert-Line)中。)

我们将重复这些步骤来描述新的死亡人数。

许多与 COVID 相关的可视化中的一个共同主题是,除了一些更好的可视化(已经提到的 91-DIVOC 等)之外,它们通常不会基于群体大小来归一化它们的数据集。加利福尼亚人比怀俄明人多 70 倍。),在了解潜在感染率时考虑这一事实可能是有意义的[是的,我确实知道大多数 COVID 携带者可能没有经过检测,但这些确诊病例数是我们在使用更病态的指标(死亡人数)之外衡量疾病传播的最佳信号。]

虽然我们的数据集已经包括人均病例数和死亡数,但为了更好的可读性,人口统计学家经常使用每 10 万人中的**。将我们的人均价值乘以 100,00 就能得出这一预期结果。这可以通过使用计算字段功能来完成。让我们导航到资源选项卡,并选择管理添加的数据源选项来编辑我们的数据源。然后,我们将单击“添加字段”按钮打开计算字段向导。**

对于每 100K 个字段的种情况,我们可以通过结合使用舍入函数和乘法来删除可能不必要的小数点:**

点击保存,然后完成保存您的更改。重复每 100K 死亡人数*的计算。然后,让我们使用 MAX aggregation 为这些度量创建相应的记分卡—有效地对应于我们的日期范围中使用的最后一个日期。请注意,这将限制我们的计算仅在州一级有效,并阻止我们使用全国范围的指标。要显示的其他值得注意的指标可能是每天新病例的最大数量(确保根据需要重命名此指标)、我们范围内的病例中值数量以及最后一天的 7 天移动平均增长率。在本练习的前面,我们选择不更改源数据中的任何数据类型,幸运的是,我们可以仅为特定控件重新格式化数据类型——让我们确保将数字格式更改为 Percent:*

完成后,我们可以选择类似于下面的指标:

使用地理地图

由于我们将作为数据源中的字段之一,并且我们能够将其重新格式化为地理数据类型,因此我们现在可以构建美国各州的交互式地图。让我们计划将此图表放在计划布局的左上象限。谈到条件格式,我们可以根据任何可用的指标来给这张地图着色,在我们的例子中,我们将使用“每 100K 死亡人数”。进入插入菜单,选择地理地图选项

会让我们从这里开始。

GDS 会自动将日期放入“日期范围维度”部分,识别状态为“地理维度”,我们的工作就是简单地将每 100K 死亡人数指定为“度量”。在“缩放区域”扩展到美国边境之外的可能性不大的情况下,做出适当的改变将是有帮助的。“数据”选项卡中的最后一步是选中“交互”部分下的应用过滤器框。这个强大的鼠标点击将神奇地为我们的地图控件添加交互功能,让我们可以根据状态选择过滤报告的其余部分:

转到面板的“样式”选项卡,我们将使用“地理图”颜色选项来有条件地格式化最大/中间/最小颜色值:

生成的地图快速显示人口调整的 COVID 死亡数据,并允许我们选择感兴趣的州来集中我们的分析工作。它现在看起来也相当像样:

在时间序列图上绘制线性对数值

我从 91-DIVOC 网站上获得的一个很棒的想法是用对数标度绘制数值。这可能是有帮助的,因为在指数增长期间(即 COVID 的初始扩散),使用对数标度更容易发现趋势。利用时间序列图的双轴特性,我们可以两全其美:在线性和对数标度上绘制新的案例值。与此同时,我们将在图表中添加一条趋势线。

**指标部分允许我们在图表上放置多个指标。在本例中,我们将使用“新案例”两次。“样式”选项卡让我们在线条条形图之间选择图表类型,对于我们的时间序列可视化,我们可以通过在轴之间切换来指定偏好的颜色、线条权重和双轴 Ys。趋势线功能允许对趋势进行线性指数和多项式描述。你可能要考虑在这张图表中做出以下选择。

检查适当轴上的对数刻度框后

我们的时间序列图包含所有相关图表,有助于我们更好地评估与 COVID 传播相关的趋势:

在双轴时间序列图上显示折线图和条形图

双轴图的一种更传统的用法是使用不同的刻度,并可能选择不同的图表类型。这正是我们下一步要做的。其中一个坐标轴将在条形图上显示累计病例数,而另一个坐标轴将通过折线图绘制一段时间内新增死亡人数。GDS 的一个受欢迎的新增功能是引入了可选指标。为了帮助我们的用户更好地与我们的仪表板交互,我们现在可以让他们指定感兴趣的指标。例如,我们可以将累积死亡数添加到图表的数据选项卡的适当部分:

假设我们启用了图表标题“悬停时显示”[样式选项卡],用户将能够从指标中挑选并在他们的自定义图表中使用:

这一易于使用的特性可以使我们的受众成为真正的分析师。查看没有可选指标的结果图,我们可以比较两种不同的趋势:**

追踪新病例增长率增长率**

下一张图表无疑是我们仪表板上最重要的图表之一。事实上,它试图帮助我们理解手头的数据——在哪个时间段,我们会经历新案件的增长或相对下降?幸运的是,正如数据准备部分所描述的,我们正好有适合这项任务的指标。我相信你有能力找到正确的方法来绘制新案件日复一日的增长率,以及新案件增长的 7 天移动平均线 T21。看看受灾最严重的州,纽约人的情况似乎有所好转,他们远离了 4 月 4 日 12,312 例新病例的高点,增长率接近或处于负值区域:

使用带横条的数据表

提供原始数据供用户使用是一种常见的做法,可以帮助用户获得信息,这些信息不容易在图表上汇总,因为存在大量的记录和使用不同的测量单位。幸运的是,我们可以合并 DataStudio 的对象,或者更好的是,合并带有条的表[实际数据和所述数据点的可视化表示的组合]来完成这项任务。我们这些从 Google Sheet 或者我敢说 MS Excel 来到 DataStudio 的人会发现这个功能非常熟悉。“样式”选项卡允许您自定义数据的外观。下表显示了在指定时间段内状态级别汇总的每 100K 死亡数、每 100K 病例数新增病例数指标:**

分享我们的工作

恭喜你,我们的工作现在已经完成,最后一步是与我们报告的消费者分享我们的数据。在我们希望向谁提供访问权限以及授予访问权限的类型方面,谷歌提供了很大的控制权。与其他谷歌产品类似,DataStudio 允许我们让网络上的每个人访问我们的工作,限制访问那些有链接的人(我们在这里采取的路线),我们组织内的任何人,我们组织内的任何人链接,或者更确切地说,限制访问我们通过共享他们的电子邮件地址信息呼叫的特定少数人。要找到这些选项,请跟随文件菜单,选择共享,然后点击获取可共享链接:

要查看我们刚刚创建的可视化效果,请随时点击此链接

您会考虑将哪些其他指标添加到该控制面板中?您还想在这个仪表板中加入其他数据可视化吗?

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

追逐数据:冠状病毒

原文:https://towardsdatascience.com/chasing-the-data-coronavirus-802d8a1c4e9a?source=collection_archive---------12-----------------------

冠状病毒,里里外外。来源:疾控中心;在维基百科上引用(http://ow.ly/H1aD50ym8XB)

关于冠状病毒大数据分析的效用(或无用性)(迄今为止)

序言:埃博拉

当我在社交媒体应急管理(SMEM)项目埃博拉病毒信息埃博拉社交媒体联盟(特别是我保存的文件)上投入大量时间时,我经常被留下来追踪数据。报道,甚至来自官方的政府来源,经常是相互矛盾的,姗姗来迟的,或者完全错误的。当我于 2015 年 3 月 28 日提交上一份报告时,已有 24,907 例确诊病例和 10,326 例死亡归因于埃博拉——这听起来约为 40%的死亡率。

尽管我转向了其他项目,但这种疾病仍在非洲肆虐。根据世界卫生组织(世卫组织)一年后于 2016 年 6 月 10 日公布的最终分析,共有 28616 例埃博拉病例,11310 例死亡,死亡率为 39.5%。我离得不远。

在漫长的考验中,世卫组织有时不得不收回数字。有关于这种疾病的虚假报道,后来证明是拉萨热、疟疾或其他疾病。

这导致了各种阴谋论和非理性的恐惧。特别是在非洲,埃博拉是对公共卫生的真正威胁,然而即使在世界各地,病例很少或根本不存在,人们也普遍感觉到了埃博拉。

埃博拉病毒触动了很多人的神经。感谢《连线》杂志激起了人们最大的恐惧。

连线撰稿人玛丽恩·麦肯纳细菌女孩 的进一步冒险,回想起来特别有启发性(目前是前五页的结果)。它记录了人们把自己逼入的非理性的疯狂状态。例如,美国海关对那些从哥斯达黎加丹尼尔·奥杜伯·基罗斯国际机场出发的人来说是个问题,仅仅因为它位于哥斯达黎加利比里亚镇。

(CBP 提示:利比里亚,哥斯达黎加≠利比里亚蒙罗维亚)

在全球范围内,2014 年至 2016 年期间,全球总人口为 74 亿,其中发现了 28,616 例埃博拉病例。这是一个只有 0.00038%的发病率(感染埃博拉病毒的几率),即每 10 万人中约有 0.38 人。与日常癌症相比,发病率为十万分之439.2,你比埃博拉 多了 x1,135 个患癌几率。

这并不是要低估疫情的严重性,也不是要低估任何实际接触或感染这种疾病的人,或任何认识受感染者的人的困境,无论是经济损失、情感创伤、痛苦还是死亡。

然而,对世界其他地区来说,这是一个我称之为“显微镜/望远镜”的非理性放大问题:那些远离疾病中心的人将它视为直接临近并威胁着他们的生命。就好像,通过望远镜观察,你认为木星在你的膝盖上。(提示:如果是的话,你可能已经因为 2.5 克的重力而喘不过气来,并被可怕的低温瞬间冻结了。)

新型冠状病毒(又名 2019-nCov 又名 COVID19)

目前 2019 年中国爆发的冠状病毒也出现了同样的模式。起初很难掌握这些数字。由于方法的改变,最近的病例在一夜之间从大约 45,000 例增加到 60,000 例。他们一直使用实验室确认的病例来计算疾病。这是“准确的”数据,但不是“及时的”实验室处理的滞后使得计数少得可怜。因此,对于每日更新来说,这最终是不准确的。当他们最终揭示了这种滞后,并转而转向基于临床症状的诊断时,这就是导致人数激增的原因。根据症状,一天内报告了 13,332 例额外病例,另有 1,820 例实验室确认病例。这是 15,152 次跳跃,其中只有 12%是实验室确认的。

其中一些病例最终会被认为是误诊而不予考虑。但他们宁愿在谨慎和数据的即时性方面出错,也不愿在计算潜在病例时多花几天或几周时间。

本质上——请原谅这种类比——中国和世界卫生组织不得不将公共卫生突发事件从高度一致但无法跟上病例吞吐量的数据集转变为高度可用、最终一致的数据集(最终将排除误报)。这是我现在的雇主 ScyllaDB 恰好是理解的专家。

就公共数据集而言,公众必须意识到你无法看到原始信息。想象一下,在美国,HIPAA 合规性会带来怎样的隐私权问题。公共卫生官员不会分享受影响者的确切姓名和身份,更不用说他们数周内的所有可疑接触。公众所能期望的最好结果是分析汇总的、轶事的或偶然的数据和元数据——比如社交媒体帖子或全球航班信息。一些公司如 T2 蓝点 T3 和 T4 meta biota T5 已经有了提供这类数据分析的服务。但是,这些都不是公开的数据集。

你也不会看到任何一种像魔法间谍电影一样的电脑特效,直接放大到谁被确诊的记录,过去几天或几周内他们所有接触者的霓虹色图表,然后快进到他们在那段时间可能在哪里的所有监控录像。(“看!那里!厨子没洗手!”)虽然关于中国政府监控的算法监控已经讨论了多年,但很明显,这种系统无法像某种超级科学一样阻止疾病爆发。

科罗纳诺亚已经来了

没过多久。科罗纳诺亚已经来了。灾难奸商已经在试图让你购买他们的产品或服务作为灵丹妙药或灾难预防。例如,今天在我公司的收件箱里出现了这个:

不,这是真的。我希望不是。由于冠状病毒,今年在巴塞罗纳举行的世界移动通信大会刚刚收起了帐篷。

  • 西班牙人口:4666 万
  • 西班牙迄今冠状病毒病例总数:2
  • 西班牙冠状病毒发病率:4.28632662e-8,即十万分之 0.00428
  • 2019 年世界移动通信大会与会者总数:109,500 人
  • MWC 感染冠状病毒的估计人数:0.0046

那么,为什么要取消一项几乎没有人会感染冠状病毒的活动呢?请注意,参加会议或在飞机上生病仍然有更大的统计概率感染基本的流感——流感波动很大,美国每年有 3%-20%的人感染流感。然而,很少有人因为害怕流感而放弃某项活动。

那么,为什么取消冠状病毒?好吧,科罗纳诺亚。西班牙的那两起案件,再加上游客从中国来西班牙的可能性,导致整个节目崩盘。一个接一个的多米诺骨牌倒下了。诺基亚、沃达丰、德国电信退出了。爱立信、索尼、英特尔、LG、亚马逊……

具有讽刺意味的是,中国巨头华为想要坚持到底。地区卫生官员 Alba Verges 说“没有公共卫生理由取消任何活动”并且该地区“冠状病毒的风险非常低”,这并不重要

主要的主播赞助商已经放弃了。嘣。表演结束了。

这场演出预计将为当地经济带来大约 5 亿美元的收入(确切地说是 5 . 13 亿美元,以及 13,900 个临时工作岗位)。但是波及范围将远远超出加泰罗尼亚。联合航空公司专门为 WMC 增加了航班,将观众带到西班牙,并向 T4 提出接受取消航班并免除他们的费用。更不用说全球业务因重大产品发布中断而搁置,无法捕捉的线索和密室谈判现在被扼杀,这通常发生在这样一个重大的贸易活动中。

由于担心中国游客,这不是唯一取消的活动。耶鲁大学的模拟联合国活动最近也被取消了。在他们的活动取消五天后,结果是学生得了…你猜对了,流行性感冒。

更新[2020 年 2 月 14 日]: IBM 刚刚退出 RSA 会议。正如他们在《双峰》中所说,“又发生了。”

虽然科罗纳诺亚将对许多人的生命和死亡产生实际影响,但它对中国经济的负面影响超出了其实际比例,对整个全球经济的影响较小。由于其影响,中国自身在一个季度内的 GDP 增长将减少 1.5%(全年 0.6%,因为经济学家预计会出现反弹)。

最佳信息来源

因此,尽管冠状病毒的一个重大健康风险,并且如果你生活在受影响的地区或与来自那里的人接触过,有的理由担心,但重要的是每个人都不要因为无知和过于频繁的种族主义冠状病毒而陷入膝跳反应。

那么,从哪里获得你的事实呢?

鉴于我在 SMEM 的背景,在 Twitter 上,像 @COVID19Info@DataCoronavirus 这样的弹出柄让我深受鼓舞。干得好,伙计们!

然而,我自己的最新和最权威的统计数据网站是基于 Esri GIS 系统的约翰霍普金斯 CSSE 冠状病毒新冠肺炎全球病例 仪表盘。

截至 2020 年 2 月 13 日 09:14 太平洋时间的冠状病毒数据

在一家大数据公司工作时,我想知道是什么样的系统在驱动这一切。一定很大,对吧?

没有。

对我来说,值得注意的是用于构建它的数据集的大小是如此之小(你可以在 Github 这里找到它)。下载整个回购文件会产生一个巨大的 158kb 的未压缩文件夹。每天的案例更新大约为 1-2kb。确诊病例、死亡病例、康复人员的时间序列文件分别为 11kb、8kb、9kb。总共有 58 份文件。

这不是大数据。这是非常小的数据。它能装在 1976 年的 5 英寸 360 千字节软盘上。

非常抱歉。

是啊。很明显,这不是原始数据,而是汇总的数据。比如说。time _ series _ 2019-ncov-confirmed . CSV 文件的前几行如下所示:

Province/State,Country/Region,Lat,Long,1/21/20 22:00,1/22/20 12:00,1/23/20 12:00,1/24/20 0:00,1/24/20 12:00,1/25/20 0:00,1/25/20 12:00,1/25/20 22:00,1/26/20 11:00,1/26/20 23:00,1/27/20 9:00,1/27/20 19:00,1/27/20 20:30,1/28/20 13:00,1/28/20 18:00,1/28/20 23:00,1/29/20 13:30,1/29/20 14:30,1/29/20 21:00,1/30/20 11:00,1/31/20 14:00,2/1/20 10:00,2/2/20 21:00,2/3/20 21:00,2/4/20 9:40,2/4/20 22:00,2/5/20 9:00,2/5/20 23:00,2/6/20 9:00,2/6/20 14:20,2/7/20 20:13,2/7/20 22:50,2/8/20 10:24,2/8/20 23:04,2/9/20 10:30,2/9/20 23:20,2/10/20 10:30,2/10/20 19:30,2/11/20 10:50,2/11/20 20:44,2/12/20 10:20,2/12/20 22:00,2/13/20 10:00,2/13/20 21:15
Anhui,Mainland China,31.82571,117.2264,,1,9,15,15,39,39,60,60,70,70,70,106,106,106,152,152,152,200,200,237,297,408,480,480,530,530,591,591,591,665,733,733,779,779,830,830,830,860,889,889,910,910,934
Beijing,Mainland China,40.18238,116.4142,10,14,22,26,36,36,41,51,68,68,72,80,80,91,91,91,111,111,111,114,139,168,191,212,212,228,253,274,274,274,297,315,315,326,326,337,337,337,342,342,352,366,366,366
Chongqing,Mainland China,30.05718,107.874,5,6,9,27,27,57,57,75,75,110,110,110,132,132,132,147,147,147,165,182,211,247,300,337,337,366,376,389,400,400,415,426,428,446,450,468,473,486,489,505,509,518,525,529

实际上,在 Github 中查看它更容易,看它告诉你什么:

它基本上是一个简单的电子表格格式的 CSV 文件,包含每个城市的每个报告期。1 月 21 日 22:00 更新。1 月 22 日和 1 月 23 日,中午 12:00 收到报告。然而,1 月 24 日有两份报告;一个从 0 点(午夜)开始,一个从中午 12 点开始。有些日子有三天(1 月 25 日有 0:00、12:00、22:00)。其他人有字面上(数字上)的奇数偏移(1 月 26 日有 11:00,23:00)。不幸的是,没有元数据指示使用什么时区偏移(GMT?中国标准时间?).

在像 Scylla 或 Cassandra 这样的现代数据库上,这些数据库可以扩展到 TB 和 Pb,这个数据集很容易作为一个 blob 放入一个小记录中。尽管这可能不是最好的数据模型。你肯定想把它分成几列,这样才有用。但是,如果这就是您要向其提供的所有数据,那么甚至不值得启动集群。

然而,这一小块微小的数据是约翰霍普金斯仪表板需要告知世界传染病的传播。

公平地说,你仍然可以用它做一些分析,即使是对这一点点数据。普华永道的数据科学家 Kamran Ahmad 前几天写了一篇很棒的博客,用 NumPy 分析了这一小部分数据,并通过 MatplotlibSeaborn 将其可视化。编辑:[2020 年 2 月 14 日 Lewis Chou 的另一篇博客刚刚发表在走向数据科学上,其中他用各种数据来源整理了一些非常方便的图表,其中一些可能会让那些分析行为模式的人感兴趣。迁移和旅行数据分析、远程办公模式和一些医院仪表板。虽然没有直接使用新的冠状病毒数据集,但这种分析是 BlueDot 和 Metabiota 为他们的客户做的事情。

但是……人们仍然需要寻找关于新型冠状病毒本身的真正大数据。千兆字节在哪里?兆字节在哪里?

当你搜索“冠状病毒”时,HDX 只有约翰·霍普金斯大学的数据(在 COVID19 或 2019-nCov 上搜索,结果除了大量的误报之外什么都没有。)

Data.gov搜索结果出现 6 个“冠状病毒”数据集不幸的是,这些结果都是针对我们已知的另一种主要冠状病毒——SARS。不适合新的、独立的 2019 菌株。

再说一次,我确信像世卫组织这样的政府间机构,各种政府和公共卫生组织,医院,实验室和非政府组织有更多的数据,他们不能,也永远不会公开分享。但是希望,随着时间的推移,可以有一些更丰富的数据集可以与世界共享。或者,至少,与数据科学家和数据工程师专业人士在一些分析公私合作伙伴关系。

对于联系人追踪,我个人倾向于像 JanusGraph 这样的图形数据库。如果你有成千上万个案例,每个案例可能有数百个联系人要跟踪数周,这很容易导致数千万条边。您可以构建许多 Gremlin/Tinkerpop 查询。

对于各种时间序列分析,你可以看看锡拉。但是,同样,只有当你当前或预期的数据集是巨大的时。坦率地说,即使 Scylla 中有 100,000 条记录,考虑到我们一秒钟可以扫描 10 亿行,还是有点令人失望。

目前,那些拥有大数据背景、希望进行分析并从数字方面贡献自己的技能来解决这一问题的人需要有一点耐心。原始数据集对公众来说并不存在。但我确信,在适当的时候,你的技能和才能会对疫情前线的当权者有用。

聊天图像到文本对话

原文:https://towardsdatascience.com/chat-images-to-textual-conversation-c44aadef59fe?source=collection_archive---------41-----------------------

使用基于深度学习的光学字符识别(Tesseract 4)从聊天图像中提取 JSON 格式的消息

UnsplashRachit 坦克拍摄

最近,社交媒体上流传着许多聊天图像,可能是与客户服务的聊天图像,或者只是来自 WhatsApp 或脸书的有趣聊天图像,也可能是任何重要的群体对话。这些数据在互联网上随处可见,却没有得到很好的利用。

Messagink 向我介绍了这个问题的一个有趣的用例。任务是将聊天图像中的信息提取成 JSON 格式。所以,我想为什么不探索这个领域,看看是否能在这个特定的领域有所成就。

我开始的任务是接收聊天图像并从中提取 JSON 对象。这个看似简单的任务包含了许多错综复杂的问题。每一个都要求我迭代我的方法,并使用机器学习概念来解决它们。让我们详细研究一下这些问题。

首先,我必须找到一个好的库,能够以非常高的精度检测图像中的文本。我搜索了很多,通读了很多库的利弊,最终敲定了谷歌的 tesseract 库(从 2006 年开始由谷歌赞助,在此之前由惠普实验室开发)。传统宇宙魔方是一个多阶段的过程。首先使用阈值对图像进行二值化,随后确定连接的部分和它们之间的连接,字符分类和聚集字符以形成单词、行、段落。更多细节可以在这篇论文中读到。

2018 年 10 月,他们推出了 tesseract 4,该产品在底层使用双向 LSTMs 来完成 OCR 任务。此后,他们进行了多次改进,最新版本于 2019 年 12 月 26 日发布。要了解更多关于宇宙魔方 4 如何使用深度神经网络的信息,请阅读这里的。我们将在所有任务中使用宇宙魔方 4。

宇宙魔方(谷歌照片)

最初,我只是输入一些聊天图像来吐槽文字。我用“宇宙魔方”包装宇宙魔方,因为使用它的结果是精确和准确的。我从图像中获取文本,但最难的部分是从这些文本中获取一些意义。例如,如果是两个人之间的聊天,我们如何分离文本信息,我们如何从图像中删除不想要的文本,我们如何检测信息的时间。所以这是接下来需要关注的几个挑战。

为了能够解决所有这些问题,主要问题是检测文本行周围的边界框。下图显示了文本周围的红色边框

红色边框(作者照片)

理想情况下,我想检测每个消息周围的边界框,但很难找到这样的工具。而“pytesseract”正在检测字符周围的单个边界框,这不符合我的目的。我在 tesseract 周围找到了另一个包装器“tesserocr ”,它展示了检测每行文本周围的边界框的功能,但是“tesserocr”的文本识别不如 pytesseract 准确,因此我决定使用 tesserocr 进行边界框检测,并使用 pytesseract 的 image_to_string 函数来识别该边界框中的文本。下面的代码片段显示了 tesserocr 和 pytesseract 的基本功能

final = cv2.imread(img, cv2.IMREAD_UNCHANGED)
# since tesserocr accepts PIL images, converting opencv image to pil
pil_img = Image.fromarray(cv2.cvtColor(final, cv2.COLOR_BGR2RGB))
#initialize api
api = tesserocr.PyTessBaseAPI()try: # set pil image for ocr
 api.SetImage(pil_img) boxes = api.GetComponentImages(tesserocr.RIL.TEXTLINE,True) height, width, c = final.shape
 print(height, width)
 inc = int(0.01*width) for i, (im,box,_,_) in enumerate(boxes): x,y,w,h = box['x'],box['y'],box['w'],box['h']

   crop_img = final[max(0, y-inc):min(y+h+inc,height), max(0, x-inc):min(x+w+inc, width)]

   cv2_imshow(crop_img)
   cv2.waitKey(0)
   extractedInformation = pytesseract.image_to_string(crop_img)
  print(extractedInformation)

最后,我们有了边界框和文本。现在必须好好利用这些边界框。考虑两个人聊天,第一个主要任务是准确分离他们之间的消息。我只是使用了每个边界框的起始边缘的 X 坐标,并将其与阈值进行了比较。阈值根据图像的宽度决定,以处理不同分辨率的图像。所以我希望 threshold 是这样一个值,即左边消息的边界框起始边缘的 X 坐标小于 threshold,而右边消息的边界框起始边缘的 X 坐标大于 threshold。在对 whatsapp 图像进行大量实验后,发现将阈值保持为图像宽度的 10%比较合适。这有助于隔离两个人之间的信息。下图显示了阈值如何映射到图像上。蓝点表示阈值,而红框是文本上的边界框。

隔离邮件的阈值(蓝色)(作者提供图片)

因为“tesserocr”每行检测一个边界框,所以长于一行的消息被分成多行。我不得不把属于同一信息的所有行整理在一起。文本周围的边框在这里也扮演了重要的角色。所以我注意到,同一封邮件中的边框的 Y 坐标之间的差异小于不同邮件中的边框。因此,我们可以再次使用一个阈值来决定是否对文本行进行排序。对不同分辨率的 whatsapp 图像进行实验,结果表明使用阈值作为图像宽度的 1%是最佳选择。在下图中,你可以看到同一封邮件中的行是如何足够近,而不同邮件中的行又是如何的远。绿色注释显示两个不同消息边界框之间的 Y 坐标差异,蓝色注释显示同一消息各行之间的 Y 坐标差异。

将文本行整理成消息的逻辑(作者提供照片)

不错!所以现在我们把文本行整理成信息,并在两个人之间分开。输出的下一个问题是在图像的页眉或页脚检测到了不必要的噪声。例如,在 whatsapp 聊天图像中,如果全屏拍摄,会在图像的顶部或底部检测到一些东西,如下所示。现在困难的部分是我们如何知道图像是裁剪过的还是完整的图像。我试着从字体大小中找出标题,或者试着把名字映射到头像图片附近,但是都没有给出有希望的结果。然后,我突然想到,来自同一来源的图像会有完全相同的模板。也就是说,如果截图来自特定人的 IOS 设备,它们将具有相同的标题和底部模板。我肯定可以使用图像减法来检测差异,并只取包含所有差异的最大边界框。但是实现比这个想法更难,我使用 opencv 的功能来提取这样一个边界框。我将使用来自同一来源的 2 个聊天截图来解释以下过程:

左:图片 1,右:图片 2(作者照片)

  • 首先,我们逐像素地减去两幅图像。这有助于突出两幅图像的差异。然后,我们将这些图像的大小调整为 1/4,以加快处理速度。

两幅图像的差异(作者提供照片)

  • 然后我们执行形态学闭运算。它在关闭前景对象内的小孔或对象上的小黑点时很有用。从而允许将附近的差异聚集在一起。我们执行 20 次闭合操作迭代两次,以完全聚集差异。

形态学封闭操作:先扩张后侵蚀(作者摄影)

  • 然后,我们对从步骤 2 获得的结果应用阈值来加强差异。

使用阈值像素值 20 进行阈值处理(图片由作者提供)

  • 之后,我们从结果图像中提取连接的组件,并在每个连接的组件周围绘制实体边界框。这会使图像中被主要差异包围的整个区域变亮。

连接组件分析后的输出(作者提供照片)

  • 在此之后,我们运行最终的连接组件分析,以提取每个区域的边界框,在我们的情况下,我们希望提取中间的白色大框,因为这将有实际的聊天内容。
  • 我们裁剪从图像中获得的第一个区域,因为它将包含人们之间的实际聊天,消除图像顶部或底部的任何噪声。在我们的例子中,结果如下:

左:裁剪后的图像 1,右:裁剪后的图像 2(作者提供的照片)

因此,最后我们能够裁剪图像,如果任何页眉或页脚存在。下一步是消除从边框中识别文本时遇到的一些噪声。在某些行中,“pytesseract”也探测到了时间,它被附加在文本的末尾。我们不得不把这段时间从文本中删除。 我们使用 12 小时和 24 小时格式的时间正则表达式来检测文本中的时间,并相应地将其去除。

在执行了所有这些步骤之后,算法就准备好了,并且对测试图像给出了良好的结果。我们在 messagink.com 部署了它,你可以在下面的网站上看到它正在工作。(您必须创建一个故事并选择导入选项。)

[## Messagink -讲述你的故事

发现有趣的故事。使用我们的编辑器创建您自己的文本故事。免费发布。

messagink.com](https://messagink.com/)

然而,当我们开始在这上面扔随机图像时,出现了几个问题。我们的目标是尽快解决下面列出的所有这些问题:

  1. 脸书/电报图像—除了消息之外,他们还有头像,所以我们必须相应地改变我们的 X 轴阈值。
  2. 启用黑暗模式的截图效果不佳。
  3. 表情符号检测是一个巨大的挑战,这是我们接下来要做的。
  4. 需要处理来自连续图片的消息之间的重叠。
  5. WhatsApp 图片需要去除蓝色勾号。

我将在下一篇博客中公布我找到的解决这些问题的方法。让我开始黑这些,回头见…

感谢 Akshat Sharma 在这项工作中的合作:)!

更新:我也发表了博客的第二部分,请在这里阅读:

[## 聊天图像到文本对话:第 2 部分

所以我又来了,第二部分是从聊天图像到文本对话。如果您还没有阅读第 1 部分,我…

towardsdatascience.com](/chat-images-to-textual-conversation-part-2-8260c09a032e)

聊天图像到文本对话:第 2 部分

原文:https://towardsdatascience.com/chat-images-to-textual-conversation-part-2-8260c09a032e?source=collection_archive---------35-----------------------

在识别聊天图像中的文本消息时集成表情检测和识别

丹尼尔·科尔派在 Unsplash 上拍摄的照片

因此,我在这里再次与第二部分的聊天图像到文本对话。如果你还没有读过《T4》第一部,我强烈推荐你点击下面的链接阅读:

[## 聊天图像到文本对话

最近,社交媒体上流传着许多聊天图像,可能是与客户的聊天图像…

towardsdatascience.com](/chat-images-to-textual-conversation-c44aadef59fe)

问题与探索

这篇博客专门解决了第 1 部分没有解决的一个主要问题——“聊天图像中表情符号的检测和识别”。

这对我们来说只是一个开放性的问题,所以我和 Akshat Sharma 尝试了几种不同的方法。显然,这看起来像是物体检测和识别问题,所以我们想先检测表情符号,然后将它们分成几个类别。我们研究了解决这类问题的几种方法,发现人们通常使用卷积神经网络(CNN)。同样在这个领域,我们有大量的选择。这篇名为“深度学习的对象检测:综述”的论文对从基于区域的卷积神经网络 RCNNs 到只看一次(YOLO)的方法进行了很好的综述,这些方法可以专门用于对象检测和识别。通过几个博客和研究结果,我们得出结论,更快的 RCNN 是最准确的。虽然 YOLO 和单次检测器足够快,但在这些博客中有几次提到它们不适合小物体检测:( 12 )引用了几篇研究论文。

方法一:训练更快——RCNN

现在我们想训练一个深度神经网络,我们需要大量的训练数据。在这种情况下,训练数据将只是使用边框和表情符号的 unicode 来注释表情符号的聊天图像,以确定它们属于哪个类别。我们在互联网上找不到任何这样的数据集,决定编写自己的脚本来生成假的聊天图像以及表情符号注释信息。受到计算的限制,我们能够生成大约 1500 个聊天图像及其相应的表情符号注释。我们首先想尝试仅使用这么多训练数据。我们在训练(1300 幅图像)和测试(200 幅图像)之间划分数据集。下面是使用我们的脚本生成的示例图像:

左:使用我们的脚本生成的样本图像,右:生成的图像的注释

总共有 88 个表情类,每个类在训练集中有超过 350 个样本。

我基本上搜索了一下,找到了两个 Faster-RCNN 的实现。第一个是由 Kbardool 创作的,另一个是由 eleow 创作的。我不能让第一个实现在 GPU 上工作,因为它需要旧的 CUDA 和 CUDNN 版本,而 Google Colab 不允许降级。使用第二种方法,我能够在训练图像上训练网络,在 60 个时期的 1300 幅图像上训练几乎需要一天时间。最后,我对结果感到兴奋,但是,它没有像预期的那样工作,并且在聊天图像中检测到随机的表情符号。我认为这可能是因为我们的数据集非常小,聊天图像中可以检测到的表情符号的大小几乎是恒定的,非常小(15x24 / 24x24)。

我们回到绘图板,开始探索更多可以解决表情识别问题的方法。我在 CNN 领域做了更多的研究,发现 YOLOv3 和 RetinaNet 是单级检测器,并在以前的实现基础上进行了改进,用于更小的物体检测。然而,受计算能力和培训时间的限制,我们决定在再次探索这一领域之前,先坚持并尝试一些经典方法。

方法 2:经典图像处理和机器学习

我们再次从头开始,阅读并研究了现有的经典图像处理方法,这些方法可能对我们的问题有所帮助。现在我将讨论我们如何使用一些经典的图像处理以及机器学习来实现表情检测和识别的目标。

因此,首先让我们谈谈为了实现我们的目标需要解决的子问题。我们发现了以下子问题:

  1. 最初,我们希望准确地检测聊天图像中的表情符号。
  2. 下一步将是识别检测到的表情符号,并为它们分配正确的标签/类别。
  3. 然后,我们希望成功地将识别的表情符号与聊天图像中现有的文本识别相结合。
  4. 最后一步是最终模型的部署。

表情检测

让我们从第一步开始,检测聊天图像中的表情符号。为了检测表情符号,我们基本上使用图像处理技术来绘制感兴趣区域周围的边界框,其中存在表情符号/图标的可能性。因此,这里的基本思想是能够使用颜色/亮度来检测表情符号存在的可能区域。

  1. 首先,我们将输入图像转换为灰度图像,以便进一步处理。

2.下一步是降低聊天图像中物体的亮度,使它们看起来更暗,而背景仍然是亮的。这是为了能够区分物体和背景。下面是步骤 2 的代码片段:

maxIntensity = 90.0 # depends on dtype of image data# Parameters for manipulating image data
phi = 1.5
theta = 0.9# Decrease intensity such that
# dark pixels become much darker, 
# bright pixels become slightly dark 
newImage = (maxIntensity/phi)*(inputImage/(maxIntensity/theta))**1.5
newImage = array(newImage,dtype=uint8)

以下是步骤 1 和 2 的结果:

左:原始图像,中:灰度图像(步骤 1),右:降低强度后的图像(步骤 2)

3.现在,我们在图像中有了更暗的点,但是为了能够清楚地将物体从背景中分离出来,我们想要对图像进行阈值处理,并将每个像素转换为白色/黑色。

# image manipulation to change every as black/white pixel value 
# based on some threshold value (here 140)for x in newImage:
 for pixel in range(0,len(x)):
  if(0 < x[pixel] < 140):
   x[pixel] = 0
  if(x[pixel] >= 140):
   x[pixel] = 255

4.我们想使用cv2 . connectedcomponentswithstats()来找到聊天图像中对象周围的边界框,这个 cv2 函数只有在黑色背景和白色对象在它上面的情况下才能很好地工作。因此,我们使用高斯自适应阈值和反向二进制阈值将步骤 3 的结果图像转换为我们想要的形式。

binaryImg = cv2.adaptiveThreshold(newImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 131, 15)

5.现在,在从步骤 4 获得的结果图像中,我们可以使用cv2 . connectedcomponentswithstats()来查找图像中对象周围的边界框。具体来说,在提取盒子时,我们设置了一些阈值,以便根据表情符号的大小进行过滤。

_, _, boxes, _ = cv2.connectedComponentsWithStats(binaryImg)# first box is the background
boxes = boxes[1:]
filtered_boxes = []for x,y,w,h,pixels in boxes:
  if(pixels < pixelsthresh and h < heightupperthresh and w <   widthupperthresh and h > heightlowerthresh  and w >  widthlowerthresh):
  #we only want boxes which contain emoji in them
  filtered_boxes.append((x,y,w,h,pixels))

步骤 3、4、5 的输出显示如下:

左图:根据阈值更改单个像素值后的图像(步骤 3),右图:自适应阈值处理后的图像(步骤 4)

表情符号检测阶段的最终输出(步骤 5)

表情识别

现在,一旦我们从图像中获得了所有的对象,我们的第二步就是能够对它们进行分类。由于表情符号图像永远不会与地面真相有所不同,在方向或方向上不会有任何变化,所以逐个像素地比较它们是有意义的。我们研究了可用于此任务的几种方法,其中一种是使用 python 中的 Imagehash 模块,我们使用它进行了几次实验,但是对于不同的相似图像集,散列值变化很大,我们无法确定能够更好地概括所有相似图像集的单个阈值。

因此,我们想出了另一种方法来比较使用尺度不变特征变换(SIFT)算法生成的表情图像的 SIFT 特征。我们决定使用这种算法,因为它最适合我们的表情识别用例。因为在我们的例子中,我们只有不同大小的表情符号,而没有任何几何形状或方向的变化,并且 SIFT 特征对于图像的平移、旋转和缩放是不变的,所以我们预计它可能会解决我们的问题。现在,我们需要一个基本事实表情数据库,这样我们就可以找到检测到的表情符号的可能匹配。我收集了 29 个不同的流行表情图像,并使用 opencv 中可用的 SIFT 算法提取 SIFT 关键点和描述符进行初始测试。接下来,我们使用 David G. Lowe 在他的论文中描述的 K 近邻 SIFT 匹配算法,将第一步中检测到的每个对象的 SIFT 特征与表情数据库中的每个图像进行比较(地面真实 SIFT 关键点和描述符特征)。我们使用从 github 报告中获取的基本评分标准来返回提取图像和真实图像之间的最终得分。

def calculateScore(matches,keypoint1,keypoint2):
  return 100 * (matches/min(keypoint1,keypoint2))

最后,我们挑选得分高于 8 的最高得分表情图像作为输入图像的最佳可能匹配。如果没有分数大于 8 的表情图像,则不存在可能的匹配,这有助于过滤掉在第一步中提取的非表情图像。这样,我们在步骤 1 中为每个提取的图像分配标签(表情 unicode)。

表情识别与现有文本聊天识别代码的集成

所以在第二步之后,我们已经成功地检测和识别了聊天图像中的表情符号。现在下一步/第三步是将前两步的结果整合到我们现有的文本聊天识别代码中。因此,为了在识别的文本中嵌入表情符号,我们使用了在步骤 2 中提取的表情符号边界框和在本博客第 1 部分中为每一行文本提取的文本边界框。这个想法是,文本的边界框应该几乎包含表情符号的边界框,缓冲区为+5/-5 px,以包括一些边缘情况。虽然这无助于确定表情符号在线与线之间的位置,但是我们可以成功地将表情符号添加到线的末尾。假设大多数人在队伍的最后使用表情符号,我们认为这将是一个很好的开始。将来为了使它更精确,我们可以寻找其他方法来处理这种情况。在步骤 3 之后,我们得到了一个成功运行的模型,在输出中,我们可以看到表情符号嵌入在输出 JSON 中。

部署

现在,第四步是在 Messagink 的应用程序( ios Android)和 网站 上部署这个模型,并在聊天故事格式中看到一些令人兴奋的结果。我们只是更新了服务器上的代码,并将 Messagink 的后端代码配置为在 Conda 环境中运行模型。我只是附上原始聊天图像和相应的聊天从这些图像生成的截图。可能会有一些差异,因为我们不能声称我们的模型是 100%准确的,但对高质量的图像来说,结果是惊人的,如下所示:

原始 Whatsapp 聊天图像(出于显示目的降低了质量等级)

由 Messagink 应用程序上的表情符号+聊天识别模型使用以上两张原始图像创建的故事。

正如我们在这里看到的,图像导入看起来非常好。要尝试此功能,请点击以下链接,使用 Messagink 网站编辑器中的导入按钮:

[## Messagink -发现文本故事

阅读你最喜欢类型的对话和文本故事。免费写你自己的文字故事。

messagink.com](https://messagink.com/editor/new)

我们成功地将表情识别集成到了现有的文本聊天识别模型中。万岁!!

但是我觉得这个模块还有很多地方需要改进。我们的下一个目标将按照优先顺序。

  • 处理图像中的噪声,正如我们在上面生成的文本中看到的,每行的末尾都有很多噪声。我们将在这种情况下寻找噪声处理的方法。
  • 此外,我们将在下一版本中加入对黑暗模式图像的支持。

到那时再见!再见!

聊天图像到文本对话:第 3 部分

原文:https://towardsdatascience.com/chat-images-to-textual-conversation-part-3-49cdee0f2c72?source=collection_archive---------50-----------------------

处理聊天图像中的噪声,并为黑暗模式图像添加功能

照片由 Unsplash 上砌墙

感觉很好,回到这个项目的最后一部分:“聊天图像到文本对话”。但是在深入研究这篇文章之前,我建议先阅读前两部分:分别是聊天识别(第一部分)和表情检测(第二部分)。

我要感谢 Akshat Sharma 为这个项目做出的所有贡献。

现在让我们来看看我们的目标,然后我们来看看我用来实现这些目标的方法:

1.处理黑暗模式图像

第一步是识别图像是暗模式还是亮模式。为此,我们使用一个非常简单的技术来寻找聊天图像的平均像素值,如果图像大于阈值,那么我们将其标记为“亮”,否则为“暗”。对于我们的用例,我们使用阈值 127。

numpyImg = cv2.imread(img)  
if(np.mean(numpyImg) > 127):      
   mode = 'Light'    
else:      
   mode = 'Dark'

现在,对于第二步,我们知道 tesseract 检测白色背景上的黑色文本具有 100%的准确性,但是它在检测黑色背景上的白色文本时无情地失败了。我们在我们的管道中使用了一个简单的技巧,如果图像是“暗的”,在第二个博客中进行强度处理后(表情检测中的步骤 2)屏蔽当前图像。

#Masking
#newImage1 is obtained from step 2 in [Emoji Detection Blog](/chat-images-to-textual-conversation-part-2-8260c09a032e)
mask = cv2.bitwise_not(newImage1)

2.从输出中消除噪声

输出中出现的大部分噪声是因为 tesseract 将表情符号、蓝色记号、时间戳识别为一些特殊字符,如@、#、W、Y、(、$。时间戳已经在聊天识别(第 1 部分)中进行了处理,使用正则表达式去除行尾的匹配部分。

当 tesseract 检测到聊天图像中的文本时,它也会检测到蓝色勾号,并在其周围绘制一个边界框,但是与其他边界框的面积相比,该边界框的面积非常小。因此,我们只计算每个边界框的面积,如果它小于阈值,就忽略它。我们用于聊天图像的阈值根据图像大小进行缩放,我们将其设置为

blueTickArea = 0.00128 * width * height

下一步是消除表情符号引起的噪声,我们已经有了另一种方法来检测第二部分中的表情符号,所以这里我们不希望 tesseract 检测表情符号。基本上,我们可以让表情符号在图像中不可见,然后输入宇宙魔方。我们使用一个非常简单的技术来实现这个想法。

在第 2 部分中进行表情符号检测时,我们已经发现了表情符号周围的边界框。对于浅色模式的图像,我们只是用白色填充这些表情符号边框,而深色模式的图像则使用黑色。这项技术阻止了 tesseract 检测图像中表情符号的任何特殊字符。

下面是实现上述想法后的输出。黑暗模式不是很准确,因为它错过了 2 心,但仍然表现很好。

表情符号的去噪——左:用白色填充的表情符号(浅色模式),右:用黑色填充的表情符号(深色模式)

因此,我们最终消除了聊天图像中的噪声,最终输出非常流畅。下面是在结束时第二部分中图像的输出。现在,您可以在下面的输出中看到改进,没有不必要的字符,这些字符以前大多出现在文本行的末尾。

故事由最终聊天+表情符号识别模型创建,Messagink 应用程序使用来自第二部的两幅输入图像去除了噪声。

这就是聊天图像到文本对话的全部内容。希望你喜欢看我的博客。

您可以通过点击以下链接,使用 Messagink 网站编辑器中的导入按钮,尝试将聊天图像导入文本故事的最新功能:

[## Messagink -发现文本故事

阅读你最喜欢类型的对话和文本故事。免费写你自己的文字故事。

messagink.com](https://messagink.com/editor/new)

也可以尝试一下 Messagink 的 app 中可用的编辑器中的功能( ios Android)

再见

与前政府人工智能顾问聊天

原文:https://towardsdatascience.com/chat-with-an-ex-government-artificial-intelligence-consultant-e4c2b93ac749?source=collection_archive---------42-----------------------

转行的主要收获

付费墙后面的股票?点击这里和我的 好友链接 一起看故事。

注意:这篇文章没有任何美国政府的秘密,工具,或者任何类似的东西。这是一个关于真正的摇滚明星“幕后”数据科学家的故事。

华盛顿到处都是在政府部门工作的人,他们的工作需要高度保密。当你问一个经典的“你是做什么的?”时,不要问更多关于工作的事情,这是一个无声的社会规则而他们的回答是“我在政府机关工作”,仅仅是因为他们不能说,如果说了,那很可能就是表面文章或者谎言。

几天前,我们邀请了一些朋友和家人来吃早午餐。赶上这一年,我的丈夫提到今年我过渡到了数据科学,由于这一点,我最终与约翰(化名)进行了一次关于人工智能的惊人的职业导向的对话。

我发现他的故事引人入胜,鼓舞人心。我请他给我这样的人工智能新从业者提建议。我将与你分享我们谈话的一部分,但首先,让我告诉你一些关于他的事情。

约翰正处于职业生涯的最后十年,他计划在 7 年左右退休。在美国国防部和中情局的一些项目中工作了几年后。他获得了侧重于人工智能的计算机科学硕士学位和计算机科学博士学位。他的博士研究重点是使用 C 和 C++进行图像识别。

他认识到,与我们现在拥有的工具相比,20 年前他不能充分发挥他以前知识的潜力,因为计算机能力如此之小,如此之贵。每个项目都是一个挑战。现在,他对计算能力如何改变人工智能的方式感到惊讶,特别是在过去的 3 年里,它彻底改变了这个行业。

在接近退休时进行职业变动并不常见,也不被视为明智之举,但他觉得他工作的政府部门在采用这些新的强大工具方面行动太慢,他不想在朝九晚五的时间里呆在那里,等待批准做他的工作。

他转到了私营部门,现在他很高兴拥有一个部门,但在他职业转变的开始,他遇到了一个问题:人工智能工具在过去 3 年中进步如此之大,即使他对行业和数学的整体理解很强,他也需要赶上新的工具和趋势。

他对继续保持行业相关性的建议总结为三点

永不停止学习

太明显了?

过去的 5 年改变了数据科学的研究方式,新的工具、新的编程语言、新的预训练算法以及更多的数据。该行业的所有这些进步都将继续推进,尽管他预测在未来 8 年内我们的处理能力将达到一个上限,但他几次提到了永不停止学习的重要性。

“在科技行业,你能做的最糟糕的事情就是相信自己什么都懂,并且只对一种编程语言感到舒服。我们这些技术人员往往对自己的知识有很强的自我意识,这种自我意识让我们处于权力的位置,也可能把我们踢出这个行业。”

我问他是否有一个他喜欢学习东西的地方,他提到他不是只和一个学习风格的平台“结婚”。博士后,在这个家校上过课,在 Coursera 上刷新过 SQL 技能,在 DataCamp 上刷新过 Python 3 和面向对象编程,在 MIT 上用 Python 深度学习,在华盛顿大学上在线课,在 YouTube 上,在 StackOverflow 上,在 Quora 上解决具体问题。

对于项目管理,他参加了 PMP,重点是敏捷和其他工作所需的培训和认证。

尽管他没有特别推荐,但他喜欢以演讲者或与会者的身份参加与行业相关的会议。他发现这是一个惊人的工具,可以有条理地了解“那里有什么”,并与新老行业参与者交谈。

与人交谈

“抱歉,如果我对技术人员有成见,但我们不倾向于与人交谈!”他说。“你不知道工具进步的速度有多快,等到做了一些教程,写了一篇论文,或者组织了一个研讨会,新的“东西”已经过时了。与人交谈是了解如何改进工作的最快方式”。

“我仍然一个月至少去两次聚会。这很奇怪,因为大部分时间都是年轻人,而我是白人少数群体中的一员

我想补充一个额外的好处:建立专业社区是无价的。除了拥有第一手的知识,你还可以从“一直在那里”的人那里得到支持和指导。如果你在华盛顿特区,想成为 女性 in Data 或/和 拉丁裔 in Tech 的一员,请给我发邮件至 hola[at]brendahali.com

学会有效沟通

有效的沟通技巧被低估了。新【人工智能】从业者需要学会,没有人在乎你的过程,没有人在乎你是怎么得到那个 p 分的。人们和管理者希望看到什么结果。尽可能高效地传达这些结果是你的责任。试图理解你不是他们的责任。”

“但是你如何提高你的沟通技巧呢?你是如何提高自己的能力的,有什么具体的方法吗?”——我问。

“读书,批判性地大量阅读。不仅仅是关于这个行业,而是阅读小说、传记、文章和明显有效的沟通书籍。 记录下你自己的谈话或陈述,然后分析你需要改进的地方。有效的沟通是需要练习的,也是可以学习的。”

总结

约翰几次提到他有多高兴,因为我决定现在开始这个职业运动,以及一个年轻的拉丁人在构建算法和收集数据方面有多重要。用他的话说,“我们生活在人工智能的黄金时代,我们需要更多的人进入这个领域”。

人工智能正在快速发展,无论你的资历、你应用技能的领域,还是你开发项目的预算,都无关紧要。为了确保你的工作和技能是相关的,你应该永不停止学习,建立一个网络,学习如何有效地沟通。

使用 Rasa 2.0 轻松构建聊天机器人:一步一步的教程

原文:https://towardsdatascience.com/chatbots-made-easier-with-rasa-2-0-b999323cdde?source=collection_archive---------5-----------------------

实践教程

从安装到与之聊天

照片由来自佩克斯的广安哈阮拍摄

什么是 Rasa?

Rasa 是一个开源的机器学习框架,用于自动化的文本和基于语音的对话。理解消息,进行对话,并连接到消息传递通道和 API。

Rasa 2.0 有什么新功能?

易于初学者使用,用 YAML 替代 markdown。

Rasa 的安装

这里的基本先决条件是 Anaconda 。它有助于处理包并防止不同的代码依赖相互干扰。

无论您使用的是 Windows 还是 Linux 系统,这些命令都应该有效:

conda create -n rasa python=3.6
conda activate rasa# pip install rasa[full] # adds all dependencies of rasa
pip install rasa

就是这个!

如果你使用pip install rasa[full],它将为每个配置安装 Rasa 的所有依赖项(spaCy 和 MITIE ),让你的生活更轻松。

注意:

在安装过程中,Tensorflow 和 Rasa(即 NumPy)的依赖关系存在冲突。Tensorflow 需要 Numpy <0.19, while Rasa requires 0.19.4.

If you try running Rasa, you will run into a runtime error.

To solve that, just downgrade your Numpy:

pip install numpy==0.19

Before We Start

Let’s understand some basic concepts in Rasa.

Source: Author

Intent

What is the user intending to ask about?

Entity

What are the important pieces of information in the user’s query?

Story

What is the possible way the conversation can go?

Action

What action should the bot take upon a specific request?

Let’s Start

The first thing to do is:

rasa init

You will then be prompted to create a sample Rasa project in the current folder.

Source: Author

This is what the sample project will look like. 模型文件是在我们训练模型后创建的。

第一站:nlu.yml

nlu.yml(来源:作者)

这是文件的样子。一开始是很直观的。

为了创建你自己的定制聊天机器人,你必须把一些意图编码进去。如果你正在为一个城市制作聊天机器人,目标应该是旅游目的地、餐馆等。

确保意图名称不重复。

为了放置一个新的意图,我们只需要跟随上面的任何一个意图。意图告诉我们意图的名称。例子告诉我们关于这个意图的语言是什么样的。确保至少给出 2 个例子。

第二站:actions.py

actions/actions.py(来源:作者)

为了创建您自己的自定义操作,可以遵循此示例。

你必须创建一个动作的子类,它将有两个功能,名字运行。函数 name 将返回聊天机器人将使用的动作名称。函数 run 将保存您的动作所执行的功能,例如计算一些数字、从互联网上获取数据等。使用 dispatcher.utter_message,您可以通过聊天机器人发送回复,例如计算的答案。

确保任何两个动作的名称不冲突。

第三站:domain.yml

domain.yml(来源:作者)

domain.yml 包含聊天机器人的领域知识,即它需要操作的信息(人们会问什么,它必须回复或做什么?).

如果您想在您的聊天机器人中使用动作,那么您还需要将动作部分添加到该文件中。如果没有,跳过这一部分。

actions:
  - action_1
  - action_2

动作部分下,输入您在上一步中创建的动作的名称。

意图部分,你必须输入你的定制意图。

下一步将是在响应部分下创建话语,即当用户提出关于意图的问题时,你的聊天机器人将给出的答案。

确保响应名称不重复。

给出独特的回答名称,并在它们下面给出当被问及某个特定意图的问题时你想给出的答案。

第四站:stories.yml

stories.yml(来源:作者)

这是我们把所有东西缝合在一起的地方。

故事部分下面是用户和聊天机器人之间对话的各种方式。对于你的聊天机器人,你把你的故事放在这里。

按照上面的例子,你将首先把一个故事名称和步骤放在里面。你可以在故事的动作部分输入话语和动作的名称。

因此,你的意图进入故事的意图部分,而你的行动和话语进入故事的行动部分。

训练聊天机器人

现在,您已经将关于您的自定义聊天机器人的所有信息放在了不同的文件中。让我们来训练你的聊天机器人。

rasa train

简单地说,输入上面的命令,让奇迹发生吧!

运行聊天机器人

现在,你可以将这个聊天机器人集成到你自己的网站中,Facebook Messenger,Slack,丨t丨e丨l丨e丨g丨r丨a丨m丨s丨,Twilio,Microsoft Bot Framework,Cisco Webex Teams,RocketChat,Mattermost 和 Google Hangouts Chat。你也可以将聊天机器人连接到任何其他平台,但你必须创建自己的定制连接器

现在,让我们在 localhost 上测试它。

注意:如果你已经在你的聊天机器人中使用了 actions ,那么,你需要取消注释 endpoints.yml 中的 action_endpoint 部分。然后,打开一个单独的终端。确保您在 Rasa 文件夹中。然后,你必须运行rasa run actions

现在,关键时刻到了。

有两种方式运行 Rasa:在 shell 中和在本地主机上。

在酝酿中

要在 shell 中运行 Rasa,只需在 Rasa 文件夹中打开的终端中键入命令:

rasa shell

这个命令将启动 Rasa 服务器,您将可以在终端中与聊天机器人对话。

Rasa Shell(来源:作者)

在本地主机上

另一种方法是在本地主机服务器上运行 Rasa。为此,只需从 Rasa 文件夹中打开的终端运行以下命令:

rasa run

这将在您的本地系统上运行 Rasa,并在本地主机的 5000 端口上公开一个 REST 端点。

与聊天机器人交谈

在酝酿中

如果你正在运行rasa shell命令,那么你可以直接在终端中与聊天机器人进行交互。像这样:

Rasa Shell(来源:作者)

机器人回答“嘿!“你好吗,”向我问好。

在本地主机上

为了与 Rasa 服务器公开的 REST 端点通信,您可以使用 cURL 命令(针对 Linux 爱好者)或 Postman。我更喜欢邮差,因为它好用。

来源:作者

您必须向 URL 发出一个 POST 请求:

http://localhost:5005/web hooks/rest/web hook

在请求的正文中,选择 Postman 中的 raw 选项。

在 JSON 格式中,你要指定两个键:发送方消息

在发送者中输入一个虚拟值,这个消息将成为你对聊天机器人的查询。

您将返回一个 JSON,包含关键字: recipient_id文本文本将有聊天机器人对您的查询的回复,并且收件人 id 将与您在请求中发送的发件人密钥相同。

摘要

我们知道使用 Rasa 创建聊天机器人是多么容易。我们理解了 Rasa 框架中的基本概念,即意图、实体、行动和故事。我们知道如何创建一个适合我们自己需求的定制聊天机器人。我们知道如何在 shell 和本地主机上运行 Rasa(并与之交互)。我们也了解了安装和运行 Rasa 时可能出现的各种陷阱。

聊天机器人和自然语言搜索

原文:https://towardsdatascience.com/chatbots-natural-language-search-cc097f671b2b?source=collection_archive---------33-----------------------

入门

集成搜索的三层聊天机器人架构

这是对我们在设计聊天机器人时经常面临的技术选择的一种非正式看法,即我们应该构建聊天机器人还是自然语言搜索(NLS),或者两者兼而有之?两者的主要动机都是让企业数据和应用程序(更)易于被每个公司员工访问,以促进知识共享和协作。为此,我们探索了两种集成架构:

  • 支持搜索的聊天机器人
  • 对话式搜索

介绍

关于聊天机器人已经说了很多,也写了很多。然而,大多数讨论都集中在面向消费者的机器人上——这种价值数百万美元的机器人将从根本上改变你公司的形象,并让你在场外节省几百万美元。不用说,建造这样一个独特的机器人也需要几十万美元的投资。尽管如此,如果数学加起来;收获就是收获,不要问任何问题!

在本帖中,我们将关注另一种慢慢抬头的机器人——企业内部面对机器人的“内部”员工。

如果你在任何一家拥有 10000 多名员工的公司工作,你会看到一些机器人在你的公司里到处涌现,让你(或至少承诺让你)可以轻松访问财务、人力资源、IT 服务台等。系统。我们将这些机器人称为面向员工的机器人。Gartner 在其研究报告中也强调了这一趋势:“聊天机器人的部署不再只是面向客户,而是越来越多地面向企业内部的员工”

这些面向员工的机器人不同于上述面向消费者的机器人,至少有以下 4 个特征:

  1. 这种机器人的主要动机是让公司的每个员工都可以(更)访问企业数据和应用程序,促进协作,等等。问一问一家相当大的公司的任何员工,他们都会一致同意所有的企业数据都会进入“黑洞”。您会听到这样的说法,“企业搜索不起作用,不可用”,“数据分布在各个小仓库中”,等等。
  2. 一个组织内的多名员工面对机器人,而“一个”消费者面对机器人,这是公司的形象。
  3. 这种机器人的投资回报率通常很低,这意味着他们的预算有限。因此,我们基本上需要以更低的价格提供相同或相似质量的机器人。当然,有人可能会说,很难量化这种员工面对机器人的“创新”方面,这通常是员工的满意度和/或通过使用新的创新技术获得的知识。
  4. 每个面向 bot 的员工所使用的技术是不同的。因为它们很可能是由组织内的不同团队开发的,所以它们偏向于单个团队的技术偏好。这导致了一个由 IBM Watson Assistant、Google DialogFlow、Amazon Lex 组成的分散世界——再加上一些更专业的初创公司——你就明白了。

这种分散景观的问题是,虽然它在实验水平上工作,但操作和维护它是相当不可能的。多样化的技术堆栈进一步暗示,作为一个组织,您将不会从商业产品的任何批量折扣中受益。因此,这种方法根本不可伸缩;机器人死亡率将很快开始与您组织中新出现的机器人数量竞争。

现在,让我们把重点放在一个有趣的技术选择上,这是我们在研究/设计这类机器人时经常面临的,也就是说,

我们应该建立一个聊天机器人还是一个自然语言搜索(NLS)工具,或者两者兼而有之?

定义

让我们尝试定位这两种技术:

IT 服务台聊天机器人(图片由作者提供)

聊天机器人 :对话型。

在其非常基本的形式中,给定一个由人类用自然语言提出的问题(我们离机器人对机器人的交流有点远),机器人用其相应的答案来回答,最好也是用自然语言。

(还有其他类型的机器人,它们更加面向操作,例如提出服务请求或采购订单。在本文中,我们主要关注以信息检索为主要目标的机器人和搜索工具。

自然语言搜索(NLS) :介绍搜索最好的方式当然是想到 Google。我们每天都用谷歌搜索,但是今天我们基本上是利用“基于关键词的搜索”。稍微思考一下,你就会想起我们是如何在谷歌中输入关键词之前将我们的查询分成关键短语/关键词的。

有了 NLS,我们谈论的世界将不再需要使用它,而是以句子的形式直接在谷歌中输入查询,就像你今天和朋友聊天一样。如果你没有尝试过,谷歌今天确实支持 NLS。它基本上使用了被称为“知识图”的东西,这是一个巨大的人工管理的知识库,捕捉真实工作实体和事件之间的关系;因此很快就达到了极限。例如,尝试以下查询序列:

自然语言搜索的局限性(作者截图)

从截图中可以注意到,第二个后续查询回复到通常的基于网页的列表响应,尽管后续问题的答案“烟雾和有毒空气”清楚地存在于其知识库(KB)中。(免责声明:谷歌的内部工作每天都在变化,但我希望基于关键词的搜索和 NLS 的区别从叙述中清晰可见。)到目前为止,我们只探索了 NLS 的查询部分。

对于答题部分,答案也应该是自然语言的句子,而不是谷歌目前显示的段落摘录。生成这样的答案/句子包含在自然语言处理的一个子领域中,称为自然语言生成(NLG)。

最先进的

在一个理想的世界里,没有技术限制,就没有必要进行这种讨论;即需要区分聊天机器人和 NLS。给定自然语言的用户查询,机器人能够做以下 4 件事:

  1. 理解用户意图;
  2. 从知识库中检索相关内容(实时);
  3. 合成答案并回复用户(用自然语言);
  4. 保留对话内容,以回答用户的任何后续问题。

问题是,目前在实现上述工作流程时存在多种技术限制。下图试图对不同的技术进行定位。

聊天机器人的智商(图片来自作者)

当前的聊天机器人引擎在第二列,我们需要提供一组问题、问题变体和它们相应的答案来构建一个机器人。

这些问题可以分为“意图”几类。问题变体,在机器人术语中称为“话语”,指的是最终用户可以提出相同问题的样本变体。这个想法是提供 5-10 个这样的话语(每个问题)作为输入,基于此,机器人将有希望能够理解问题的 50 种不同的变化。大多数 bot 引擎使用统计 NLP 技术,例如 tf-idf、n-grams、词袋、文本分类(SVM),来将最终用户的查询映射到意图。

这在合理的程度上是可行的;然而,主要的挑战是关于硬编码的答案,需要提前提供,这反过来限制了机器人可以回答的问题的范围。

更具伸缩性的方法是在这里使用 NLS。有了这样的集成,只需将机器人指向一个 KB(文档存储库)就足够了,机器人将能够在运行时通过搜索 KB 文档(第 3 列)来检索用户查询的答案。

这里的技术限制是,搜索文档可能比将用户查询映射到意图的准确度低得多。此外,大多数当前的搜索技术致力于相关性度量(相似性分数)。因此,搜索输出是相关段落的列表,而不是自然语言中的“精确”答案——NLG 还没有出现。

总而言之,聊天机器人和 NLS 目前都还没有成熟到可以互相替代的程度。这两者是互补的,在续集中,我们将重点介绍一些有趣的方法来集成它们。

聊天机器人-NLS 集成架构

支持搜索的聊天机器人

一个独立的聊天机器人通常是不够的。扩展了搜索功能的聊天机器人在大多数情况下是有意义的。

计划一个三层聊天机器人架构,如下图所示:

1.带有预定义问答集的聊天机器人仍然是切入点,可以把它看作是第一道防线。

2.如果机器人遇到无法映射到其预先配置的意图之一的用户查询,它会对其知识库执行 NLS。这是第二道防线。

3.如果用户甚至对搜索结果都不满意,请计划最终移交给现场代理。

三层聊天机器人架构(图片由作者提供)

三层策略非常强大,我们发现它在客户服务、帮助台等方面非常有用。用户查询的范围可能非常一般的场景类型。保留聊天机器人作为入口点是有意义的,至少对于那些用户查询可以匹配现有意图的情况是如此;答案将是精确而中肯的——提高用户满意度。与此同时,我们不能无休止地向聊天机器人的问答库添加问答,因为这样会影响意图识别的准确性。因此,建议采用如上所示的分层架构。

我们将在随后的博客文章中提供我们的 NLS 堆栈的更多细节。就目前而言,足以说明我们正在使用一个整合了 ElasticSearch 和 DRQA 的定制解决方案(在 2019 年柏林 Buzzwords 上展示, link ),这是一个神经网络架构,可以回答脸书研究公司的开放领域问题。

对话搜索

对话式搜索(图片由作者提供)

在这种情况下,聊天机器人的主要目标是“搜索”。将聊天机器人与搜索整合在一起允许用户以更对话的方式进行搜索。

用户可以与机器人交互以:

  • 获取有关可用搜索过滤器的更多详细信息。当用户是该领域的新手时,这可能非常有帮助,并且机器人可以帮助用户导航搜索过滤器,例如标签、本体、文档类型。
  • 逐步细化搜索结果,直到他们找到他们正在寻找的文档/报告。

对话式搜索作为一种查询 SQL 数据库的方式越来越受欢迎,例如 Power BI — NLP 搜索Salesforce Photon

进一步阅读

  • E.里恰尔代利·比斯瓦斯。基于强化学习的自我改进聊天机器人。第四届强化学习与决策多学科会议( RLDM ,2019 ( 论文)。
  • D.比斯瓦斯。保护隐私的聊天机器人对话。关于保护隐私的机器学习的第 34 届 NeurIPS 研讨会( PPML ),2020 年 12 月(论文)。
  • 长度比斯瓦斯·巴利甘德。用 ElasticSearch 和脸书的 DrQA 构建企业自然语言搜索引擎。2019 年第十届柏林流行语大会。

作弊代码,以更好地与 Plotly Express 可视化

原文:https://towardsdatascience.com/cheat-codes-to-better-visualisations-with-plotly-express-21caece3db01?source=collection_archive---------40-----------------------

使用 Python 的 Plotly Express 库创建各种交互式数据可视化的快速指南。

Matplotlib 和 Seaborn 是数据科学中用于可视化的两个最流行的库。我想展示如何使用 Plotly 库中的 Plotly Express 模块,我们可以获得 Seaborn 和 Matplotlib 的简单性,但实现更深入和交互式的可视化。

Plotly Express 是一个简单易用的 Plotly 库的高级接口。那么,让我们看看如何开始。

进口

import plotly.express as px

让我们看看 Plotly Express 模块中已有的一些数据集:

tips = px.data.tips() 
#total_bill, tip, sex, smoker, day, time, sizegapminder = px.data.gapminder() 
#country, continent , year, lifeExp, pop, gdpPercap, iso_alpha, iso_numgapminder_canada = gapminder.query("country=='Canada'")
gapminder_oceania = gapminder.query("continent=='Oceania'")
gapminder_continent = gapminder.query("continent != 'Asia'")iris = px.data.iris() 
#sepal_length, sepal_width, petal_length, petal_width, species, species_idelection = px.data.election() 
#district, Coderre, Bergeron, Joly, total, winner, result, district_id

柱状图

让我们来看看使用直方图的 tips 数据集,因为该数据包含许多分类变量。对于第一个示例,我将使用总账单作为变量来绘制直方图。

fig = px.histogram(tips,             #dataframe
                   x = "total_bill", #x-values column
                   nbins = 30        #number of bins
                   )
fig.show()

总账单价格直方图

使用 Plotly Express,我们可以创建一个交互式直方图。我们可以看到 x 轴上的 bin 范围、total_bill 值以及光标悬停时每个点的计数。

让我们通过考虑第二个变量——性别来提升直方图:

fig = px.histogram(tips,             #dataframe
                   x = ”total_bill”, #x-values column
                   color = ”sex”     #column shown by color
                   )
fig.show()

与性别相关的总账单价格直方图

现在,我们可以看到男性和女性在总账单中的数量,但是除了悬停交互之外,我们还可以隔离直方图以显示男性、女性或两者。

直方图的另一个小更新可以是添加地毯图、箱线图或小提琴图:

fig = px.histogram(tips,                     #dataframe
                   x = ”total_bill”,         #x-values column
                   color = ”sex”,            #column shown by color
                   marginal = ”rug”,         #plot type (eg box,rug) 
                   hover_data = tips.columns #extra info in hover
                   )
fig.show()

与性别相关的总账单价格直方图,包括数据点的地形图

在这里,我使用了一个地毯图,现在我们可以在直方图中看到与下面的条块相关的数据点。正如你可能想知道的,你也可以和地毯图互动。

散点图

散点图是另一种流行且有效的可视化形式,它不仅简化了表达,还增强了表达。这里我们看到的是虹膜数据集;不同植物种类的大小。

fig = px.scatter(iris,               #dataframe
                 x = "sepal_width",  #x-values column
                 y = "sepal_length"  #y-values column
                 )
fig.show()

间隔宽度和间隔长度散点图

我们可以通过添加颜色、大小和更多的交互数据,使这个散点图更加动态,信息更加丰富。

fig = px.scatter(iris,                        #dataframe
                 x = ”sepal_width”,           #x-values column
                 y = ”sepal_length”,          #y-values column
                 color = ”species”,           #column shown by color
                 size = ’petal_length’,       #col shown by plotsize
                 hover_data = [‘petal_width’] #extra info in hover
                 )
fig.show()

间隔宽度和间隔长度散点图(颜色=种类,大小=花瓣长度)

能够在一组轴上通过添加不同的颜色将植物隔离或分组,有助于我们不必创建三个单独的地块来进行比较。

线图

传统的线图也很简单,用 Plotly 表示。

fig = px.line(gapminder_canada, #dataframe
              x = "year",       #x-values column
              y = "lifeExp"     #y-values column
              )
fig.show()

60 年间加拿大人预期寿命的线形图

折线图对于比较数据集中的两行非常有用,这可以通过向图中再添加一个属性来实现。在这种情况下,颜色代表国家。

fig = px.line(gapminder_oceania, #dataframe
              x = "year",        #x-values column
              y = "lifeExp",     #y-values column
              color = 'country'  #column shown by color
              )
fig.show()

澳大利亚人和新西兰人 60 年间的预期寿命线图

这里我们有两个来自大洋洲的国家,所以它们都被分配了一种颜色,而不必提及国家的名称,只是颜色参数的列名。

除了大洋洲之外,我们还可以添加更多的洲,但是我们如何避免图表变得过于庞大呢?

将洲显示为颜色,然后将线组设置为国家,这样我们就可以直观地看到不同洲的预期寿命,而不必计算该洲内所有国家的平均预期寿命。

fig = px.line(gapminder_continent,    #dataframe
              x = ”year”,             #x-values column
              y = ”lifeExp”,          #y-values column
              color = ”continent”,    #column shown by color
              line_group = ”country”, #group rows of a column
              hover_name = ”country”  #hover info title
              )
fig.show()

60 年间世界各国预期寿命的折线图(不包括亚洲)

如果个人观察是首选的,我们可以再次隔离大陆的线,以及检查每条线所代表的国家的悬停能力。

条形图

更简单的条形图代码。

fig = px.bar(gapminder_canada, #dataframe
             x = ’year’,       #x-values column
             y = ’pop’         #y-values column
             )
fig.show()

加拿大 60 年人口柱状图

我们可以添加更多关于加拿大人口随时间变化的信息,包括使用颜色的预期寿命。使用条形图的标签属性将 axis 标签 pop 升级为 population of Canada,并为悬停功能添加更多详细信息。

fig = px.bar(gapminder_canada,                     #dataframe
             x = ’year’,                           #x-values column
             y = ’pop’,                            #y-values column
             hover_data = [‘lifeExp’, ‘gdpPercap’],#extra hover info
             color = ’lifeExp’,                    #column by color
             labels = {‘pop’:’population of Canada’}#label change
             )
fig.show()

加拿大 60 年人口柱状图(带颜色=预期寿命)

上面,我们可以用一张图表有效地描绘出加拿大人口随时间变化的两种趋势。

回头看看 tips 数据集,我们可以将更多的信息叠加到一个柱状图可视化中。

fig = px.bar(tips,               #dataframe
             x = ”sex”,          #x-values column
             y = ”total_bill”,   #y-values column
             color = ”smoker”,   #column shown by color
             barmode = ”group”,  #separate filter (smoker)
             facet_row = ”time”, #name of grid row
             facet_col = ”day”,  #name of grid column
             category_orders= {“day”: [“Thur”, “Fri”, “Sat”, “Sun”],
                               “time”: [“Lunch”, “Dinner”]}
                                 #grid arrangement
             )
fig.show()

男性和女性在周四至周日午餐和晚餐期间支付的总账单的条形图(带颜色=吸烟者)

我们可以观察数据集的五列,并伴有一些交互性。通过使用行和列方面,我们有一个网格布局,用于一周中的日期和用餐时间;由较小的条形图组成,其中包含人员类型(吸烟者和性别)及其总账单的摘要。

三维散点图

来个 3D 吧。在这里,我们正在查看选举数据集,其中按地区比较了蒙特利尔市三名市长候选人的投票和结果。

fig = px.scatter_3d(            
        election,                #dataframe
        x = ”Joly”,              #x-values column
        y = ”Coderre”,           #y-values column
        z = ”Bergeron”,          #z-values column
        color = ”winner”,        #column shown by color
        size = ”total”,          #column shown by size
        hover_name = ”district”, #hover title
        symbol = ”result”,       #column shown by shape
        color_discrete_map = {“Joly”: “blue”, “Bergeron”: “green”, 
                               “Coderre”:”red”}
                                 #specific colors for x,y,z values            )fig.show()

蒙特利尔不同地区市长候选人票数的三维散点图(颜色=候选人获胜,形状=获胜类型

结合 Plotly 的悬停交互性,该图可以显示选举数据集中的所有信息。

地理学的

地理图表用于更独特的情况,但也可以使用 Plotly Express 轻松完成。

fig = px.scatter_geo(gapminder,               #dataframe
                     locations = ”iso_alpha”, #location code
                     color = ”continent”,     #column shown by color
                     hover_name = ”country”,  #hover info title 
                     size = ”pop”,            #column shown by size
                     animation_frame = ”year”,#column animated
                     projection = ”orthographic”#type of map
                     )
fig.show()

一段时间内各国人口变化的正射曲线图

我们对观想有一个非常有用的补充;也就是动画交互性。对于这个数据集,我选择了年份作为动画帧;因此,我们可以自动播放所有年份,也可以手动选择年份。

虽然上面的球形可视化看起来很有趣,但下面的地图可视化对一个人观察和分析信息会更好。

fig = px.choropleth(gapminder,                #dataframe
                    locations = ”iso_alpha”,  #location code
                    color = ”lifeExp”,        #column shown by color
                    hover_name = ”country”,   #hover info title
                    animation_frame = ”year”, #column animated
                    range_color = [20,80]     #color range
                    )
fig.show()

各国预期寿命随时间变化的 Choropleth 图

现在,我们有了一个非常清晰的图像,显示了随着时间的推移,世界各地的预期寿命。

动画散点图

动画散点图(气泡图)是我最喜欢的可视化,因为它很好地解释了信息,并且非常动态。

px.scatter(gapminder,                  #dataframe
          x = "gdpPercap",             #x-values column
          y = "lifeExp",               #y-values column
          animation_frame = "year",    #column animated
          animation_group = "country", #column shown as bubble
          size = "pop",                #column shown by size
          color = "continent",         #column shown by color
          hover_name = "country",      #hover info title
          log_x = True,                #use logs on x-values
          size_max = 55,               #change max size of bubbles
          range_x = [100,100000],      #axis range for x-values
          range_y = [25,90]            #axis range for y-values
          )

各国人均国内生产总值、预期寿命和人口随时间变化的气泡图

因此,使用 Plotly Express,我们可以实现具有交互性的可视化,只需要几行直观的代码。

Google Colab 的备忘单

原文:https://towardsdatascience.com/cheat-sheet-for-google-colab-63853778c093?source=collection_archive---------3-----------------------

在本教程中,您将学习如何充分利用 Google Colab。

形象演职员表: 中等

介绍

Google Colab 是一个了不起的工具,它让我们建立并执行一个杰出的数据科学模型,并为我们提供了一个记录我们的旅程的机会。由于 Google Colab 为我们提供了代码单元格来键入代码,它还为我们提供了文本单元格来添加文本。在本教程中,我们将更多地关注文本单元格,看看我们如何通过使用一些我将在本教程中讨论的简单命令来掌握它。如果你喜欢记录(像我一样),那么你会喜欢阅读本教程。你可以从下面的链接开始探索 Google Colab。相信我,这是一个神奇的工具。

[## 谷歌联合实验室

编辑描述

colab.research.google.com](https://colab.research.google.com/)

小抄

下面我将讨论一些主要的便利技巧和快捷方式,它们可以被使用并成为文档记录的专家。如果你知道 MarkdownXMLHTML 编码,那么这可能是一件轻而易举的事情,或者如果你对其中任何一个都不熟悉,那么今天是学习它们的好时机。Google Colab 支持 MarkdownHTML 文档。你可以把其中的任何一个记录下来。只需注意,本教程的完整代码也可以在下面我的 GitHub 资源库 中找到:

[## 塔努-北帕布/Python

github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/Cheat_sheet_for_Google_Colab.ipynb)

好了,我们开始吧。

使用“文本单元格”来试验所有这些命令

图片来源于作者(塔努·南达·帕布)

标题

下面是标题的快捷命令。从标题 1 到标题 6 有不同类型的标题。

降价

使用**# heading-name**,添加的**#**越多,标题的尺寸越小,如下图所示:

图片来源于作者(Tanu Nanda Prabhu)

超文本标记语言

类似地,您可以使用 HTML 标签,如**h1, h2, h3, h4, h5 and h6**作为标题,如下所示:

图片来源于作者(Tanu Nanda Prabhu)

大胆的

加粗使文本加粗并增加文本的可见性。

降价

****** (两颗星)将文本包围,使其在 markdown 中加粗,例如****Text-to-be-bold****

图片来源于作者(Tanu Nanda Prabhu)

超文本标记语言

使用 HTML,我们可以通过使用**b**标签来加粗文本,如下所示:

图片来源于作者(Tanu Nanda Prabhu)

在字下划横线

与粗体相似,文本也可以是斜体

降价

使 markdown 中的文本变为斜体,用***** (一颗星)将其包围,例如***Text-to-be-italicize***

图片来源于作者(Tanu Nanda Prabhu)

超文本标记语言

同样,这也可以使用如下所示的**i** 标记在 HTML 中编写:

图片来源于作者(Tanu Nanda Prabhu)

删除线

用于删除文本。一条水平线画在文字中间。

降价

为了删除线,markdown 中的文本用两个波浪号字符**~~**包围,例如**~~Text to be striked~~**

图片来源于作者(塔努·南达·帕布)

超文本标记语言

在 HTML 中我们可以使用**s** 标签来删除文本。

图片来源于作者(塔努·南达·帕布)

结合

此外,我们可以组合所有的格式命令并设置文本样式,如下所示。

降价和 HTML

图片来源于作者(Tanu Nanda Prabhu)

列表

众所周知,有两种类型的列表:

  1. 有序列表
  2. 无序列表

顾名思义,有序列表有一个顺序(1,2,3,…或其他)。但是无序列表没有顺序,如下所示。

Markdown 中的有序和无序列表

在有序列表的 markdown 中,你可以直接输入类似于**1, 2, 3, and so on**的数字。但是对于无序列表,你可以从一个***** 开始,这个实习生创建一个项目列表。

图片来源于作者(Tanu Nanda Prabhu)

超文本标记语言

我们可以使用 HTML 标签来处理列表,如下所示:

有序列表

有序列表中有普通列表,类型 1,A,A,I,I 类型如下图所示:

正常列表

使用**ol**标签,列表内容使用**li** 标签,如下所示:

图片来源于作者(Tanu Nanda Prabhu)

Type = "1"

只需在**ol** 标签中添加**type = "1"**,这将创建一个由 1、2、3 等等组成的有序列表。列表项将用数字编号(默认)。

图片来源于作者(Tanu Nanda Prabhu)

Type = "A"

只需在**ol** 标签内添加**type = "A"**,这将创建一个由 A、B、C 等等组成的有序列表。列表项目将用大写字母编号。

图片来源于作者(塔努·南达·帕布)

Type = "a"

只需将**type = "a"**添加到**ol** 标签中,这将创建一个由 a、b、c 等等组成的有序列表。列表项目将用小写字母编号。

图片来源于作者(塔努·南达·帕布)

Type = "I"

只需将**type = "I"**添加到**ol** 标签中,这将创建一个有序的列表,包含 I、II、III 等等。列表项将用大写罗马数字进行编号。

图片来源于作者(塔努·南达·帕布)

Type = "i"

只需将**type = "i"**添加到**ol** 标签中,这将创建一个有序的列表,包含 i、ii、iii 等等。列表项将用小写罗马数字进行编号。

图片来源于作者(Tanu Nanda Prabhu)

无序列表

有序列表中有正常列表、圆盘、正方形、圆形和无类型,如下图所示:

正常列表

使用**ul** 标签,列表内容使用**li** 标签,如下所示:

图片来源于作者(Tanu Nanda Prabhu)

圆盘

只需在**ul** 标签内添加**type = "disc"**即可创建一个圆盘形列表。

图片来源于作者(塔努·南达·帕布)

圈子

只需在**ul** 标签内添加**type = "circle"**即可创建一个圆形列表。

图片来源于作者(塔努·南达·帕布)

方形

只需在**ul** 标签内添加**type = "square"**即可创建一个方形列表。

图片来源于作者(Tanu Nanda Prabhu)

只需在**ul** 标签内添加**type = "none"**即可创建一个无形状列表。在这种情况下,列表将没有点,如下所示

图片来源于作者(塔努·南达·帕布)

描述列表

描述列表是一个术语列表,包含每个术语的描述。**dl** 标签由定义列表名称的**dt**和描述每个列表的**dd** 标签组成。

图片来源于作者(塔努·南达·帕布)

嵌套列表

嵌套列表基本上是列表中的列表。

图片来源于作者(Tanu Nanda Prabhu)

控制列表计数

有序列表将从 1 开始计数。如果要从指定的数字开始计数,可以使用如下所示的**start** 属性:

图片来源于作者(塔努·南达·帕布)

要更深入地了解 HTML 中的列表,请参考下面的文章:

[## HTML 列表

自己试试”无序列表以标签开始。每个列表项都以标签开始。

www.w3schools.com](https://www.w3schools.com/html/html_lists.asp)

链接

链接或超链接允许用户从一页点击到另一页。

降价

在 markdown 中,将链接的标题写在方括号**[ ]**内,将网页地址写在圆括号或圆括号**( )**内。确保先写标题,再写链接。

图片来源于作者(塔努·南达·帕布)

超文本标记语言

在 HTML 中对于超链接,可以使用**a****href** 标签如下所示:

图片来源于作者(Tanu Nanda Prabhu)

形象

有时候一张图片胜过千言万语。人们可以很容易地通过看到图像来更好地理解这些概念。

降价

与链接类似,您需要在括号内插入图像的链接。一定要在开头加上**!** 。如果你的链接被破坏或者无效,那么**alt text**将被显示。

图片来源Makeameme.org

图像悬停

您可以同时将鼠标悬停在文本上来查看图像的标题。为此,您可以将您选择的文本放入命令中,如下所示:

![alt text](https://media.makeameme.org/created/online-class-cant.jpg "**Online Class Memes**")

超文本标记语言

在 HTML 中,我们可以使用**img** 标签来包含图像,并且您需要向**src**标签提供图像的来源。

调整高度和宽度

您可以调整图像的高度宽度。同样,你也可以嵌入一个 GIF 图片,如下图所示。

图片来源于Giphy.com

图片和说明文字

这是一个很好的实践,给来自不同来源的图片(我的意思是引用图片或提供说明)以信任。在**p** 标签的帮助下,我们可以为图片提供标题。

【Makeameme.org】图片来源 图片来源

您可以尝试使用**align** 标签,并根据您的喜好调整标题。

格式化代码

这里有两件事你需要明白:

  1. 内嵌代码
  2. 语法高亮显示

内嵌代码

有时,您可能希望插入一些可以使用内联代码的代码示例。要使用内联代码,可以使用反斜杠(`` `)。如上图用反勾将其包围。

图片来源于作者(Tanu Nanda Prabhu)

语法突出显示

当你在 Google Colab 的文本编辑器中编写多行代码时,就会用到这个。有时使用内联代码包含巨大的 python 代码片段并不是一个好主意,在这种情况下使用语法高亮。您必须将代码嵌入到````**`中,如下所示

默认语法高亮显示

这与任何编程语言无关。

图片来源于作者(塔努·南达·帕布)

Python 语法高亮显示

这可以明确地用于 python 编程。你应该在开头加上**python**这个名字。

图片来源于作者(塔努·南达·帕布)

Javascript 语法高亮显示

这可以明确地用于 JavaScript 编程。你应该在开头加上**javascript** 这个名字。

图片来源于作者(塔努·南达·帕布)

C 编程语法高亮

这可以明确用于 C 编程。你应该在开头加上名字**c**

图片来源于作者(Tanu Nanda Prabhu)

如上所述,您可以突出显示基于不同编程语言的代码片段。

桌子

有些时候,您可能希望以表格的形式表示信息。

降价

您必须使用**|** 作为不同列的运算符。默认情况下,表格标题会以粗体显示。

图片来源于作者(塔努·南达·帕布)

冒号可以用来对齐列。

如果您需要创建任何表格,那么使用下面的 工具 为您生成表格。你所要做的就是选择表格生成器的类型,比如 Latex、HTML、Markdown 等等。输入表格中的内容,然后点击生成。然后,您可以在文本编辑器中复制粘贴生成的代码,并毫不费力地看到一个漂亮的表格。

[## 在线创建 LaTeX 表格—TablesGenerator.com

使用表格/设置尺寸菜单选项设置所需的表格尺寸。将表格数据输入表格:复制…

www.tablesgenerator.com](https://www.tablesgenerator.com/)

超文本标记语言

在 HTML 的情况下,你必须使用**table** 标签和**tr** ,后者用于表格行,而**th**用于表格标题(在这种情况下是公司名称和创始人)。**td** 为表格描述。

图片来源于作者(塔努·南达·帕布)

您也可以使用**align** 标签并相应地对齐内容。

缩进

当您需要区分一些文本,如注释、提示或任何额外的有用信息时,这非常有用。

降价

你需要使用**>**进行缩进。

图片来源于作者(塔努·南达·帕布)

超文本标记语言

同样,在 HTML 中,你可以使用**blockquote** 标签来达到同样的目的。

图片来源于作者(Tanu Nanda Prabhu)

水平标尺

在你写作的时候,在每一章或者任何一个概念后面画一个横坐标通常是一个很好的练习。这有助于区分不同的事物。

降价

在降价的情况下,你只需要使用 3 个**---**(减号)。

图片来源于作者(Tanu Nanda Prabhu)

超文本标记语言

对于 HTML,您需要使用标签**hr**来插入一个水平标尺。

图片来源于作者(Tanu Nanda Prabhu)

证明合法

很多时候你会在笔记本上写下大段文字,但有时你可能想调整它们,只是为了让它看起来整洁。在这里,可以使用**align** 标签,用**justify** 作为值。

图片来源于作者(塔努·南达·帕布)

图片来源于作者(Tanu Nanda Prabhu)

同样,你可以用**right****left****center**的值和的值相应地对齐的段落。****

换行符

有时你可能想开始一个新的段落,所以你需要在它们之间换行。这里有两个选项,要么你可以直接按下回车键,在中间留一行空格,要么你可以使用**br** 标签,也称为换行符。

图片来源于作者(Tanu Nanda Prabhu)

数学公式

如果你用笔记本做研究,那么你需要写很多方程式和数学符号。

符号

确保您在第一个**$**之后的**\** 之间书写符号名称。

图片来源于作者(塔努·南达·帕布)

方程式

遵循相同的规则,即围绕**$** 之间的等式,从第一个**$**后的**/** 开始。

图片来源于作者(Tanu Nanda Prabhu)

要查看更多关于数学方程式和符号的内容,请参考下面的 链接 :

****[## 在 Markdown 中编写数学公式

在这篇文章中,我将向你展示如何在 markdown 中编写数学符号。因为我在写博客,所以…

csrgxtu.github.io](https://csrgxtu.github.io/2015/03/20/Writing-Mathematic-Fomulars-in-Markdown/)****

好了,各位,教程到此结束。我希望你今天学到了很多新东西。我试图保持这篇教程的简短,但是因为有很多概念,我不得不把它最大化。但是这份备忘单在大多数面试(技术文档)中或者当你记录你的木星笔记本时会很有用。如果我找到更多的提示和技巧,那么我会在这里提供细节。在那之前,注意安全,祝你有美好的一天。下次见。

NLP 备忘单:迄今为止我的 NLP 学习历程总结

原文:https://towardsdatascience.com/cheat-sheet-for-nlp-a-summary-of-my-nlp-learning-journey-thus-far-6ee753943890?source=collection_archive---------23-----------------------

说实话,我一开始也没想到要学 NLP。但是由于它广泛而有趣的应用,NLP 一直吸引着我去更深入地挖掘和探索更多的乐趣。与许多机器学习算法不同,NLP 在可视化方面特别丰富,因此易于理解、解释和应用于现实生活中的问题。在本文中,我将介绍 NLP 中的几个领域,并分享它们背后的思想(以及代码和视觉效果!).以下是你应该期待的:

tweet 数据集包含 2292 条 Twitter 用户的推文。尽管这个数据集不能代表 Twitter 上的所有人,但我们的结论仍然很有见地。代码都上传在 Github 里。

情感分析

我总是觉得情绪分析很有趣,因为它可以嵌入到任何地方。我们,人类,与情感相连,与观点进步。更具体地说,商业是以客户为中心的。分析公众对一种产品或一家公司的看法有助于公司定位和改进。因此,情感分析可以用作商业中的绩效指标/反馈。

  • 幼稚情绪分析

让我们从简单的方法开始,了解情感分析背后的思想。在朴素情感分析中,我们将每个词编码为正面或负面,然后遍历整个文本,计算正面词和负面词。

这个代码片段展示了如何为肯定/否定单词生成单词列表,这些单词列表以后可以作为字典使用,我们可以在其中查找单词。Github 中包含完整版本的代码。

import requests
def sentiment_words(url):
    request = requests.get(url)
    print("retriving data >>> status code: ",request.status_code)
    text = request.text
    word_list = text[text.find("\n\n")+2:].split("\n")
    return word_listpos_url = '[http://ptrckprry.com/course/ssd/data/positive-words.txt'](http://ptrckprry.com/course/ssd/data/positive-words.txt')
neg_url = '[http://ptrckprry.com/course/ssd/data/negative-words.txt'](http://ptrckprry.com/course/ssd/data/negative-words.txt')
pos_list = sentiment_words(pos_url)[:-1]
neg_list = sentiment_words(neg_url)[:-1]

下图是 Twitter 用户的情绪分布。总的来说,Twitter 用户积极的多于消极的。有些用户甚至有接近 0 的负分的高正分。

Twitter 用户的情感分布,来源于作者

仔细观察一个用户:我们能够察觉这个用户情绪的变化。不幸的是,我们没有更准确的时间信息,否则我们甚至可能发现一些情绪变化的周/季模式。

一个用户的情感分数的变化,按作者来源

  • NRC 情感词典

与朴素情绪分析的机制相似,NRC 提取了另外 8 种情绪,如喜悦、信任、悲伤等。有了更丰富的信息,可以添加更多的视觉效果/功能。例如,雷达图是情绪诊断的潜在视觉效果。用户 1(蓝色)似乎比用户 2(红色)更积极,在积极情绪(喜悦、信任、期待)上得分更高,在消极情绪(悲伤、愤怒、厌恶)上得分更低。

用于情绪诊断的雷达图,来源于作者

  • VADER

VADER(化合价感知词典和情感推理机)的功能超出了单词级别。相反,它在句子级别/内容级别上分析情感。此外,它提供了情绪的极性(积极/消极)和强度。在 Python Vader perspection 库中,它返回 4 个分数——正、负、中性和复合。

from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
analyzer = SentimentIntensityAnalyzer() 
pos=neg=neu=compound=0
sentences = nltk.sent_tokenize(text.lower())
for sentence in sentences:
    vs = analyzer.polarity_scores(sentence)
    pos += vs["pos"]/len(sentences)
    neg += vs["neg"]/len(sentences)
    neu += vs["neu"]/len(sentences)
    compound += vs["compound"]/len(sentences)

“中性”与“积极”显著负相关,这是有道理的,因为当我们表达情绪时,很难保持中立。然而,大多数用户被检测为高度中立。是我们的分析仪不够灵敏,还是现实生活中的真实情况?

VADER 分数分布,按作者来源

VADER 情绪得分的雷达图,来源于作者

WordCloud

词云是很多人说起 NLP 时想到的。它计算单词的频率,并根据它们的频率调整每个单词的大小。一个词出现的频率越高,在词云中就越突出。这个想法简单而有效。

from wordcloud import WordCloud, STOPWORDS
wordcloud = WordCloud(stopwords=STOPWORDS,background_color='white',width=3000,height=3000).generate(text)
plt.imshow(wordcloud)          
plt.axis('off')           
plt.show()

Wordcloud 覆盖整个数据集,按作者排序

命名实体识别

命名实体识别使我们能够理解谈论的是什么或谁,它反映了人类用语言语法处理句子的方式。该代码片段逐句扫描文本,如果单词被识别为“实体”,则标记每个单词。完成后,我们在大块中搜索树,并询问“你被贴上标签了吗?”— hasattr(树,“标签”)。如果树回答是,我们将在 tree.leaves() 中获取实体,并存储标签 tree.label()

def entity_identity(text):
    sentences = nltk.sent_tokenize(text)
    entity = []
    for sentence in sentences:
        words = nltk.word_tokenize(sentence)
        tagged = nltk.pos_tag(words)
        chunked = nltk.ne_chunk(tagged)
        for tree in chunked:
            if hasattr(tree,"label"):
                entity.append([tree.label()," ".join(c[0] for c in tree.leaves())])
    entity = pd.DataFrame(entity,columns=['label','entity'])
    return entity

实体快照,按作者排序的来源

如果将命名实体与情感分析/词云相结合,事情会变得更有趣。我们先来看云这个词里的一个例子。该函数可以获取任何类型的实体,并抓取该类型中的所有实体以形成单词云。它可以作为一个监视器,监视人们在谈论什么/谁。

def wordcloud_entity(entity,label="PERSON"):
    text = " ".join(list(entity[entity["label"]==label]["entity"]))
    wordcloud =  WordCloud(stopwords=STOPWORDS,background_color='white',width=3000,height=3000).generate(text)
    fig,ax = plt.subplots(1,1,figsize=(8,8))
    plt.imshow(wordcloud)          
    plt.axis('off')
    plt.show()

分别代表 GPE(地缘政治实体)和个人的 Wordcloud,来源于作者

好了,现在我们意识到 twitter 用户正在大量谈论香港、美国、特朗普、宝琳娜·辛基娜……进一步分析一下与这些词相关的情绪如何?接下来,我搜索包含这些单词的句子,并使用 VADER 情感分析器。

def sentiment_entity(text,entity="New York"):
    sentences = nltk.sent_tokenize(text)
    analyzer = SentimentIntensityAnalyzer()
    pos=neg=neu=compound=count=0
    for sentence in sentences:
        if entity.lower() in sentence.lower():
            vs = analyzer.polarity_scores(sentence)
            pos += vs["pos"]
            neg += vs["neg"]
            neu += vs["neu"]
            compound += vs["compound"]
            count += 1
    return pos/count,neg/count,neu/count,compound/count

这个数据集在它所代表的用户群(例如大学生)和我提取它的时间方面是有偏见的,但至少它表明了我们如何能够将情感分析纳入命名实体识别。

美国、纽约和香港的情感比较,按作者分类

特朗普和宝琳娜·辛基娜之间的情感比较,由作者提供

文本摘要

在前三部分中,我们主要集中在单词级和句子级的分析。现在我们来分析段落中的文本。通常,一篇文章包括开头、正文和结尾。开头或结尾的一些句子是总结文章主题的关键句子。文本摘要对每个句子进行排名,并挑选排名靠前的句子。天真地说,我们可以计算每个单词的频率,并以此为标尺对句子进行排序。最后,我们挑选词频最高(最有代表性)的句子。还有另一种计算 TextRank 的复杂方法,它被打包在一个名为 gensim 的包中。看看这段代码!推文比文章短,因此可能不太适合摘要。我将 ratio 参数设置为小至 0.003,以挤压 tweets 的输出大小。

import gensim
gensim.summarization.summarize(text,ratio=0.003)

一个文本摘要的例子,作者来源

主题分析和相似性

现在事情越来越抽象了。主题分析是一种无监督的学习技术,我们试图从文本中提取维度。我这里介绍的技术是 LDA(潜在狄利克雷分配)。LDA 需要词典和语料库为主题抽取做准备。单词字典对文本中的每个代码进行编码。语料库是一个列表的列表,其中文本中的单词存储在一个列表中,所有文本分别存储在不同的列表中(“单词包”)。

words_list = []
users = []
for user,text in tweets.items():
    users.append(user)
    words = nltk.word_tokenize(text.lower())
    words = [word for word in words if word not in STOPWORDS and word.isalnum() and len(word)>=2]
    words_list.append(words)num_topics = 3 #self-defined
dictionary = corpora.Dictionary(words_list)
corpus = [dictionary.doc2bow(words) for words in words_list]
lda = LdaModel(corpus, id2word=dictionary, num_topics=num_topics)

现在我们得到 3 个主题及其相应的代表词。要显示特定主题的样子,请尝试以下代码:

# Topic is 0 indexed, 1 indicates the second topic
lda.show_topic(1)

某个主题的热门词汇,来源于作者

要获得用户/文档的主题组件,请尝试以下代码:

# corpus[2] refers to the tweets of a user
sorted(lda.get_document_topics(corpus[2],minimum_probability=0,per_word_topics=False),key=lambda x:x[1],reverse=True)[output] [(0, 0.51107097), (1, 0.48721585), (2, 0.0017131236)]

比较不同用户之间的主题相似性,这是 LSI 的亮点。LSI 接受与 LDA 相同的输入—字典、语料库—并将一个新文档与现有的语料库进行比较。

lsi = models.LsiModel(corpus,id2word=dictionary, num_topics=3)  
words_new = nltk.word_tokenize(doc.lower())
words_new = [word for word in words if word not in STOPWORDS and word.isalnum() and len(word)>=2]
vec_bow = dictionary.doc2bow(words_new)     
vec_lsi = lsi[vec_bow]
index = similarities.MatrixSimilarity(lsi[corpus])
sims = index[vec_lsi]       
sims = sorted(enumerate(sims), key=lambda item: -item[1])

我没有输入新的推文。相反,我随机选择了一个用户。这就是为什么我们得到一个相似性分数 1。

相似性表(语料库 id,相似性得分),来源按作者

pyLDAvis 包为 LDA 提供了很好的视觉效果,通过它我们能够知道主题如何与关键词相关联,以及如何解释主题。这需要相当长的时间,因此我只为一个用户绘图。

lda_display = pyLDAvis.gensim.prepare(lda, corpus, dictionary, R=15, sort_topics=False)     
pyLDAvis.display(lda_display)

LDA 可视化示例(一个用户),按作者排序

语言模型(文本生成)

通过以上步骤,我们开始了解文本的情感、实体、关键词、主题。现在让我们教我们的机器如何像人一样说话。我们将为一个 twitter 用户建立一个简单的 RNN 模型,并模仿这个用户如何说话。

对系列数据应用机器学习有两个主要障碍。首先,序列的顺序不能反映在传统的 DNN 模型中。这就是 RNN 的用武之地。RNN 非常适合系列数据,就像 CNN 适合图像一样。多对一 RNN 结构将文本中的前 n-1 个单词作为输入,第 n 个单词作为输出。RNN 可以传递以前位置的信息,从而可以连续保留订单。第二,系列数据可以有不同的长度。推文可以短至 3 个字符,也可以长达几个句子。Padding 就是专门针对这个问题设计的。

首先,我们对每个单词进行标记,因为机器不能直接识别单词,然后每个句子被编码成一个整数列表。例如,“现在”在句子中被编码为 198。word_index 是解密的字典。

tokenizer = Tokenizer() # can set num_words to tokenize
tokenizer.fit_on_texts(sentences)
sequences = tokenizer.texts_to_sequences(sentences)
word_index = tokenizer.word_index
index_word = {index:word for word,index in word_index.items()}

接下来,为了统一长度,每个句子要么添加 0 来弥补空格,要么将其本身截断以适应框。前 n-1 项取 X,每句最后一项取 y。

max_length = 15
trunct_type = "post"
padding_type = "pre"padded = pad_sequences(sequences,padding=padding_type,truncating=trunct_type,maxlen=max_length)vocab_size = len(word_index)+1
X = padded[:,:-1]
Y = padded[:,-1]
Y = tf.keras.utils.to_categorical(Y,num_classes=vocab_size)

在构建 RNN 模型时,我们添加了一个嵌入层。这是一种表示单词的方法,并且比一键编码表示法有一定的优势。在一个热编码中,每个字是相互独立/正交的。单词嵌入为每个单词生成一个向量,并支持非正交关系。有些单词可以彼此更接近和相似。比如“猫”比“西边”更接近“狗”。因此,我们能够将我们的知识移植到我们以前没有见过的句子中。机器能够从原来的句子“猫在跑”中学习“狗在跑”。

LSTM 是一种解决消失梯度和加强长期串联连接的技术。

model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size,embedding_dim,input_length=max_length-1),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(512,return_sequences=True)),
tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(256)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(vocab_size,activation="softmax")
])model.compile(loss='categorical_crossentropy',optimizer="adam",metrics=["accuracy"])model.fit(X,Y,epochs=100,verbose=1)

让我们生成文本来看看我们会说话的机器人是如何工作的。

choice = random.randint(0,len(padded)) 
seed = padded[choice,1:].reshape(1,max_length-1)
tweet_robot = sentences[choice]
for i in range(5):
    predicted = model.predict_classes(seed,verbose=0)
    seed = np.append(seed,[int(predicted)])[1:].reshape(1,max_length-1)
    tweet_robot = tweet_robot + " " + str(index_word[int(predicted)])

一个会说话的机器人的例子,由作者提供

原始句子是一条完整的推文,我们的说话机器人通过挑选适当的单词来帮助扩展句子。结果不如我期望的那样令人满意。我们的会说话的机器人似乎只是在扔单词,而不是产生一个组织良好的句子。但是,所选的单词显示出与主题的一些一致性。

要提高性能,还有很多工作要做。文本清理是我的首要任务。Tweets 很短,不正式,这导致了很多用词和句子组织的不优雅。数据集中有很多噪音。

我正站在 NLP 宏伟宫殿的门口,敲门。我前面的路还很长。我写下这篇文章来提醒我走过的路,并鼓励我继续冒险。

github:https://github.com/JinPu-dududu/NLP

在 Python 中实现选择最佳集群数量的 7 种方法的备忘单

原文:https://towardsdatascience.com/cheat-sheet-to-implementing-7-methods-for-selecting-optimal-number-of-clusters-in-python-898241e1d6ad?source=collection_archive---------1-----------------------

基于多个聚类验证指标(如间隙统计、轮廓系数、Calinski-Harabasz 指数等)选择最佳聚类数。

Mehrshad Rajabi 在 Unsplash 上拍摄的照片

细分为检查有意义的细分提供了一个数据驱动的角度,高管可以使用它来采取有针对性的行动和改善业务成果。许多高管冒着基于过度概括做出决策的风险,因为他们利用一刀切的方法来评估他们的商业生态系统。然而,分段通过提供多个有意义的透镜来分解数据并采取行动,从而改善了决策。

我们在试图对客户或产品进行细分时面临的最令人困惑的问题之一是选择理想的细分数量。这是 K 均值、凝聚聚类和 GMM 聚类等多种聚类算法的关键参数。除非我们的数据只有 2 或 3 维,否则不可能直观地理解数据中存在的聚类。而在大多数实际应用中,我们会有 3 个以上的维度。本博客将帮助读者理解并快速实现选择最佳集群数量的最流行技术:

  1. 差距统计
  2. 肘法
  3. 轮廓系数
  4. 卡林斯基-哈拉巴斯指数
  5. 戴维斯-波尔丁指数
  6. 系统树图
  7. 贝叶斯信息准则(BIC)

在这个练习中,我们将使用一家为孕妇提供服装的在线商店的点击流数据。它有从 2008 年 4 月到 2008 年 8 月的数据,包括产品类别、图片在网页上的位置、IP 地址的来源国以及产品的美元价格等变量。在选择最佳的聚类数之前,我们需要准备数据进行分割。

我建议您在继续下一步之前,阅读下面的文章,深入了解为分段准备数据的不同步骤:

One Hot 编码、标准化、PCA:python 中分割的数据准备

差距统计

差距统计是由斯坦福大学的研究人员蒂布拉尼、瓦尔特和哈斯蒂在他们 2001 年的论文中提出的。他们的方法背后的想法是找到一种方法来比较聚类紧密度与数据的零引用分布,即没有明显聚类的分布。他们对最佳聚类数的估计是原始数据上的聚类紧密度落在该参考曲线之下最远的值。此信息包含在以下差距统计公式中:

作者图片

其中,Wk 是基于类内误差平方和(WSS)的聚类紧密度的度量:

作者图片

误差平方和的类内计算由KMeans函数的inertia_属性进行,如下所示:

  • 每个点到聚类中心的距离的平方(误差平方)
  • WSS 分数是所有点的这些平方误差的总和

在 python 中计算 k 均值聚类的间隙统计包括以下步骤:

  • 将观察到的数据在不同数量的聚类上进行聚类,并计算我们的聚类的紧密度
  • 生成参考数据集,并用不同数量的聚类对每个数据集进行聚类。参考数据集是使用random_sample函数根据“连续均匀”分布创建的。
  • 计算参考数据集上聚类的平均紧密度
  • 根据参考数据和原始数据的聚类紧密度差异计算间隙统计数据
# Gap Statistic for K meansdef optimalK(data, nrefs=3, maxClusters=15):
    """
    Calculates KMeans optimal K using Gap Statistic 
    Params:
        data: ndarry of shape (n_samples, n_features)
        nrefs: number of sample reference datasets to create
        maxClusters: Maximum number of clusters to test for
    Returns: (gaps, optimalK)
    """
    gaps = np.zeros((len(range(1, maxClusters)),))
    resultsdf = pd.DataFrame({'clusterCount':[], 'gap':[]})
    for gap_index, k in enumerate(range(1, maxClusters)):# Holder for reference dispersion results
        refDisps = np.zeros(nrefs)# For n references, generate random sample and perform kmeans getting resulting dispersion of each loop
        for i in range(nrefs):

            # Create new random reference set
            randomReference = np.random.random_sample(size=data.shape)

            # Fit to it
            km = KMeans(k)
            km.fit(randomReference)

            refDisp = km.inertia_
            refDisps[i] = refDisp# Fit cluster to original data and create dispersion
        km = KMeans(k)
        km.fit(data)

        origDisp = km.inertia_# Calculate gap statistic
        gap = np.log(np.mean(refDisps)) - np.log(origDisp)# Assign this loop's gap statistic to gaps
        gaps[gap_index] = gap

        resultsdf = resultsdf.append({'clusterCount':k, 'gap':gap}, ignore_index=True)return (gaps.argmax() + 1, resultsdf)score_g, df = optimalK(cluster_df, nrefs=5, maxClusters=30)plt.plot(df['clusterCount'], df['gap'], linestyle='--', marker='o', color='b');
plt.xlabel('K');
plt.ylabel('Gap Statistic');
plt.title('Gap Statistic vs. K');

图 1:不同聚类值的差距统计(图片由作者提供)

如图 1 所示,29 个聚类的差距统计最大,因此,我们可以选择 29 个聚类作为 K 均值。

肘法

这是确定最佳聚类数的最常用方法。该方法基于计算不同数量的组(k)的组内误差平方和(WSS ),并选择 WSS 变化首先开始减小的 k。

肘形法背后的思想是,对于少量的聚类,所解释的变化迅速变化,然后它变慢,导致曲线中形成肘形。拐点是我们可以用于聚类算法的聚类数。关于这种方法的更多细节可以在袁春辉和杨海涛的论文中找到。

我们将使用 YellowBrick 库,它可以用几行代码实现 elbow 方法。它是 Scikit-Learn 的包装器,并且有一些很酷的机器学习可视化!

# Elbow Method for K means# Import ElbowVisualizer
from yellowbrick.cluster import KElbowVisualizer
model = KMeans()
# k is range of number of clusters.
visualizer = KElbowVisualizer(model, k=(2,30), timings= True)
visualizer.fit(cluster_df)        # Fit data to visualizer
visualizer.show()        # Finalize and render figure

图 2:肘法结果(图片由作者提供)

对于介于 2 到 30 之间的聚类值范围,KElbowVisualizer函数适合于KMeans模型。如图 2 所示,拐点是用 8 个集群实现的,它由函数本身突出显示。该函数还通过绿线告知我们为不同数量的聚类绘制模型需要多少时间。

轮廓系数

i 的轮廓系数定义如下:

作者图片

其中 b(i) 是点 i 到任何其他聚类中所有点的最小平均距离,而 a(i)i 到其聚类中所有点的平均距离。例如,如果我们只有 3 个聚类 A、B 和 C,并且 I 属于聚类 C,那么通过测量 i 到聚类 A 中每一点的平均距离,即 I 到聚类 B 中每一点的平均距离,并取最小结果值来计算 b(i) 。数据集的轮廓系数是单个点的轮廓系数的平均值。

轮廓系数告诉我们各个点是否被正确地分配到它们的簇中。使用轮廓系数时,我们可以使用以下经验法则:

  1. S(i) 接近 0 表示该点在两个聚类之间
  2. 如果它更接近-1,那么我们最好将它分配给其他集群
  3. 如果 S(i) 接近 1,则该点属于“正确的”聚类

关于这种方法的更多细节,请参考 N. Kaoungku,K. Suksut,R. Chanklan 和 K. Kerdprasop 的这篇 2018 年论文。我们将使用KElbowVisualizer函数来实现 K 均值聚类算法的轮廓系数:

# Silhouette Score for K means# Import ElbowVisualizer
from yellowbrick.cluster import KElbowVisualizer
model = KMeans()
# k is range of number of clusters.
visualizer = KElbowVisualizer(model, k=(2,30),metric='silhouette', timings= True)
visualizer.fit(cluster_df)        # Fit the data to the visualizer
visualizer.show()        # Finalize and render the figure

图 3:剪影评分结果(作者图片)

基于轮廓得分的最佳聚类数是 4。

卡林斯基-哈拉巴斯指数

Calinski-Harabasz 指数是基于这样一种想法,即(1)本身非常紧凑的聚类和(2)彼此间隔良好的聚类是好的聚类。该指数是通过将单个对象到其聚类中心的距离的平方和的方差除以聚类中心之间的距离的平方和来计算的。卡林斯基-哈拉巴斯指数值越高,聚类模型越好。卡林斯基-哈拉巴斯指数的公式定义为:

作者图片

其中 k 是聚类数,n 是数据中的记录数,BCSM(聚类间散布矩阵)计算聚类间的分离度,WCSM(聚类内散布矩阵)计算聚类内的紧密度。

KElbowVisualizer函数还能够计算卡林斯基-哈拉巴斯指数:

# Calinski Harabasz Score for K means# Import ElbowVisualizer
from yellowbrick.cluster import KElbowVisualizer
model = KMeans()
# k is range of number of clusters.
visualizer = KElbowVisualizer(model, k=(2,30),metric='calinski_harabasz', timings= True)
visualizer.fit(cluster_df)        # Fit the data to the visualizer
visualizer.show()        # Finalize and render the figure

图 4:卡林斯基哈拉巴斯指数(图片由作者提供)

如图 4 所示,对于 K 均值聚类算法,当聚类数为 2 时,Calinski Harabasz 指数最大。要更深入地了解这个指数,请参考和徐玉生的论文

戴维斯-波尔丁指数

戴维斯-波尔丁(DB)指数定义为:

作者图片

其中 n 是聚类的计数,而 σi 是聚类 i 中所有点距聚类中心 ci 的平均距离。

像剪影系数和 Calinski-Harabasz 指数一样,DB 指数同时捕获了聚类的分离度和紧密度。这是因为测量的“最大值”语句重复选择平均点距离其中心最远的值和中心最接近的值。但与剪影系数和 Calinski-Harabasz 指数不同,随着 DB 指数的下降,聚类得到改善。

# Davies Bouldin score for K meansfrom sklearn.metrics import davies_bouldin_scoredef get_kmeans_score(data, center):
    '''
    returns the kmeans score regarding Davies Bouldin for points to centers
    INPUT:
        data - the dataset you want to fit kmeans to
        center - the number of centers you want (the k value)
    OUTPUT:
        score - the Davies Bouldin score for the kmeans model fit to the data
    '''
    #instantiate kmeans
    kmeans = KMeans(n_clusters=center)# Then fit the model to your data using the fit method
    model = kmeans.fit_predict(cluster_df)

    # Calculate Davies Bouldin scorescore = davies_bouldin_score(cluster_df, model)

    return scorescores = []
centers = list(range(2,30))for center in centers:
    scores.append(get_kmeans_score(cluster_df, center))

plt.plot(centers, scores, linestyle='--', marker='o', color='b');
plt.xlabel('K');
plt.ylabel('Davies Bouldin score');
plt.title('Davies Bouldin score vs. K');

图 5:戴维斯·波尔丁得分(图片由作者提供)

如图 5 所示,Davies Bouldin 分数在 4 个聚类中最小,可以考虑用于 k 均值算法。关于 DB 分数的更多细节可以在斯洛博丹·佩特罗维奇的一篇论文中找到。

系统树图

这种技术是特定于凝聚层次聚类方法的。聚类的凝聚层次方法首先将每个点视为一个单独的聚类,然后开始根据点和聚类的距离以层次方式将点连接到聚类。在另一篇博客中,我们将重点介绍这种方法的细节。为了获得分层聚类的最佳聚类数,我们使用了一个树形图,这是一个显示聚类合并或分裂顺序的树形图。

如果两个聚类合并,树状图会将它们连接成一个图,连接的高度就是这些聚类之间的距离。我们将使用scipy库中的dendogram函数来绘制图表。

# Dendogram for Heirarchical Clustering
import scipy.cluster.hierarchy as shc
from matplotlib import pyplot
pyplot.figure(figsize=(10, 7))  
pyplot.title("Dendrograms")  
dend = shc.dendrogram(shc.linkage(cluster_df, method='ward'))

图 6:树状图(图片由作者提供)

如图 6 所示,我们可以根据树状图的层次结构选择最佳的集群数量。正如其他聚类验证指标所强调的,4 个聚类也可以被考虑用于聚集层次结构。

贝叶斯信息准则

贝叶斯信息准则(BIC)评分是一种对使用最大似然估计框架的模型进行评分的方法。BIC 统计数据的计算方法如下:

BIC = (kln(n)) — (2ln(L))*

其中 L 是模型的似然函数的最大值,k 是参数的数量,n 是记录的数量

BIC 分数越低,模型越好。我们可以将 BIC 分数用于聚类的高斯混合建模方法。我们将在单独的博客中讨论这个模型的细节,但这里需要注意的关键是,在这个模型中,我们需要选择聚类的数量以及协方差的类型。我们尝试了参数的各种组合,并选择了具有最低 BIC 分数的模型。

# BIC for GMMfrom sklearn.mixture import GaussianMixture
n_components = range(1, 30)
covariance_type = ['spherical', 'tied', 'diag', 'full']
score=[]
for cov in covariance_type:
    for n_comp in n_components:
        gmm=GaussianMixture(n_components=n_comp,covariance_type=cov)
        gmm.fit(cluster_df)
        score.append((cov,n_comp,gmm.bic(cluster_df)))
score

BIC 评分(图片由作者提供)

结论

在这篇文章中,我们学习了 7 种不同的方法来为不同的聚类算法选择最佳的聚类数。

具体来说,我们了解到:

  • 如何计算用于选择最佳集群数量的各种指标
  • 使用这些指标选择最佳集群数量的经验法则
  • 如何在 python 中实现集群验证方法
  • 如何解释这些方法的结果

最后,给定用于选择最佳集群数量的多个指标,我们可以将各种指标的平均值/中值/众数作为最佳集群数量。

你对这个博客有什么问题或建议吗?请随时留言。

感谢您的阅读!

如果你和我一样,对人工智能、数据科学或经济学充满热情,请随时添加/关注我的 LinkedInGithubMedium

参考

  1. Tibshirani R,Walther G 和 Hastie T,通过间隙统计估计数据集中的聚类数,统计学家杂志。社会主义者 B (2001) 63,第二部分,第 411-423 页
  2. 袁 C,杨 H,K-Means 聚类算法的 K 值选取方法研究,,2019 . 6 . 18
  3. Kaoungku 和 Suksut,k .和 Chanklan,r .和 Kerdprasop,k .和 Kerdprasop,Nittaya。(2018).用于聚类和关联挖掘选择图像特征的轮廓宽度准则。国际机器学习和计算杂志。8.69–73.10.18178/ijmlc.2018.8.1.665
  4. 王 X &徐 Y,基于剪影指数和 Calinski-Harabasz 指数的聚类验证改进指数,2019 IOP Conf。爵士。:板牙。Sci。英语。569 052024
  5. 佩特罗维奇 S,“剪影指数”和“戴维斯-波尔丁指数”在标记 IDS 聚类中的比较

检查表:为 Google BigQuery 选择正确的数据转换服务

原文:https://towardsdatascience.com/check-list-selecting-the-right-data-transformation-service-for-google-bigquery-bd99307da581?source=collection_archive---------26-----------------------

哪种 Google 云服务可以让您的数据为分析做好准备?

凯尔·格伦在 Unsplash 上的照片

好消息是,在移动和转换基于 BigQuery 的分析和 AI/ML 数据时,谷歌云提供了过多的原生选择。坏消息是,你必须在许多选项中做出选择,以确保该技术符合你的需求,并证明是可持续的。

本文是一份帮助您选择最适合您的技术(或技术组合)的清单。如果您计划将 BigQuery 用于您的分析和数据科学项目,这意味着您将需要批量和/或微批量地清理、转换和组合数据。为此,我已经排除了 Google BigQuery 数据传输服务,它只能将数据移入 BigQuery,而不能进行转换。此外,我将我的研究仅限于原生谷歌云数据转换服务,包括云数据处理云数据流云数据融合云数据准备。当然,使用 SQL 也可以在 BigQuery 中进行转换,这是一种非常强大的语言(我花了很多年来构建利用 SQL 和存储过程的应用程序);然而,由于多种原因,SQL 并没有为企业数据转换服务提供一个可持续的解决方案,而且也有很好的理由说明为什么有这么多技术被发明出来用于转换数据(这本身就需要一篇完整的文章)。

那么,为了选择正确的技术,你应该问自己什么问题呢?

问题 1:您是否希望用编程语言为您的解决方案编写代码?

如果软件工程师或开发人员必须开发和集成各种组件来创建一个包括大规模数据转换的应用程序,那么您应该考虑云数据流或云数据块。这些是基于代码的解决方案,需要 Java、Python、RestAPI 或 Apache Spark 等编程技能。这些都需要相当的技术知识。有了这些服务,您已经知道需要创建哪些转换,并且您需要一个开发工具来编码这些转换。为了弄清楚是选择云数据流还是云数据块,阅读这篇文章,它提供了使用其中一个的很好的论据。

问题 2:你的数据已经在 Google Cloud 了吗?

如果你的数据还不在谷歌云中,那么谷歌基于开源项目 CDAP 开发的云数据融合(Extract,Transform,and Load,ETL)解决方案提供了许多连接器,可以将数据导入谷歌云和 BigQuery。或者,您可以利用您内部已有的其他 ETL 解决方案,将数据引入 Google Cloud。谷歌推荐这些 ETL 厂商,包括 Matillion、Fivetran、Informatica,以及更多。云数据融合等 ETL 解决方案最适合开发大规模数据管道,从本地和云资源移动数据,以“水合”数据湖或数据仓库(DWH)。数据工程师、ETL 开发人员和数据架构师将从云数据融合中受益最多。他们将能够开发可靠的实时和批量数据转换管道。云数据融合和 ETL 在构建稳定的数据管道以定期将数据移动到 DWH 或数据湖方面表现出色。它们并不意味着创建经常变化的管道,也不意味着将管道交给某些业务用户。

问题 3:您的数据计划是否需要灵活性来经常适应业务需求?除了数据工程师之外,您的项目是否需要业务用户或不太懂技术的专业人员进行自助式数据转换?

数据准备是数据转换技术的最新发展,将这些功能交给了技术含量较低且通常位于业务线的数据驱动型专业人员(除了数据工程师等常见的技术数据专家之外)。这些专业人员比任何人都更了解数据,但是,他们可能缺乏清理、组合和丰富数据以满足其需求的技术技能。通常他们会知道 Excel、Google Sheets 和 SQL。Cloud Dataprep(与 Trifacta 合作开发)提供了一个基于网格的、机器学习指导的可视化界面,以实现敏捷的数据探索和评估,从而为 BigQuery for analytics 提炼、标准化和组合数据。用户与数据内容进行交互,以反复提炼和汇集数据,用于下游业务驱动的分析。

云数据准备或云数据融合的附加问题:你更倾向于云数据处理还是云数据流?

云数据融合生成云 Dataproc 代码来转换数据,而云 Dataprep 生成一些数据流代码来转换数据。基于您的用例以及您以前的经验,两者都有各自的优势。这也可能是支持在 BigQuery 之上提供分析的特定技术的一个因素。

最终,您可能需要结合多种解决方案来为 BigQuery 创建端到端的分析或机器学习解决方案。我们经常看到 ETL 将数据放入云 DWH 或数据湖,然后使用数据准备技术将数据公开给消费者。

下表总结了这些技术的特征,以指导您的选择。

原载于【www.trifacta.com】

用 Pylint 检查你的代码质量

原文:https://towardsdatascience.com/check-the-quality-of-your-code-with-pylint-f5d829bb441d?source=collection_archive---------8-----------------------

PEP 8 指南的 10 条规则将使你的代码更容易阅读

罗纳河上的星夜——文森特·梵高

PylintPython 编程语言的质量检查器,遵循 PEP 8 推荐的风格。本文提供了用 Python 编写清晰代码的指南,主要目标是提高代码的可读性和一致性。代码被阅读的次数要比被编写的次数多得多,这就是为什么遵守约定是如此重要,这将帮助我们或其他人更容易地理解可用的代码。在本文中,我们解释了 PEP 810 条规则,它们可以让你的 Python 代码更容易被其他人阅读,以及我们如何用 Pylint 检查它们。我们开始吧!💪

安装 Pylint

Pylint 是第三方库,在 Python 中默认不可用。由于 Pylint 不是 Python 标准库的一部分,我们需要单独安装它。这可以通过使用 pip 组件轻松实现。 PipPython 的标准包管理器,允许安装和管理不包含在 Python 标准库中的包。要检查是否安装了 pip ,您可以在 Windows 终端中执行以下命令:

**pip --version**

如上图所示,版本 10.0.1 在我们的系统中已经有了。现在,我们可以安装 pylint ,在命令行运行:

**pip install pylint**

还安装了 pylint 所需的所有依赖项。注意 pip 下载了最新版本的包。

使用 Pylint

一旦我们安装了 pylint ,我们可以通过运行命令 pylint 和文件名来轻松使用它,如下所示:

**pylint filename.py**

现在!我们已经准备好看到一些代码示例💪。在本文中,我们将详细解释用 Python 编码时的 10 个编码约定。此外,我们将证明 pylint 如何检测它们。

编码约定(PEP 8)

PEP 8 是一个风格指南,它定义了你的 python 代码应该如何被格式化以最大化它的可读性。在这篇文章中,我们将只涉及一些关键点;因此,如果你想更详细地研究这个话题,我建议你看一下指南。

[## PEP 8 风格的 Python 代码指南

Python 编程语言的官方主页

www.python.org](https://www.python.org/dev/peps/pep-0008/)

1.多行语句

在 Python 中,我们在排比句( () )、中括号( [] )、大括号( {} )内部使用隐式延伸线隐式意味着我们不写行继续符( ** )来表示我们将一个语句扩展到多行。

当使用隐式延续行时,被包裹的元素应该垂直对齐,或者使用悬挂缩进。在 Python 的上下文中,悬挂缩进意味着带括号的语句的左括号是该行的最后一个非空白字符,随后的行缩进直到右括号。

不良做法

括号内的参数没有垂直对齐,或者使用悬挂缩进。

Pylint 输出

Pylint 检测到一个错误的缩进。

良好实践

括号内的参数垂直对齐。

括号内的参数使用悬挂缩进对齐。

2。操作员

始终用一个空格将这些运算符括起来:

  • 赋值 (=)
  • 扩充赋值 (+=,-=,等等)
  • 比较运算符 ( <,>,< =,> =,==,!=)
  • 逻辑运算符(与、或、非)
  • 隶属运算符(在,不在)
  • 身份运算符(是,非是)

不良做法

运算符没有被空格包围。

我们可以很容易地禁用 pylint 中的警告,在代码顶部添加一个注释,如上所示( #pylint: disable=C0114 )

C0114 警告表示模块文件串丢失。docstring 是作为模块、函数、类或方法定义中的第一条语句出现的字符串。根据 PEP 257(包含 docstring 约定的指南),所有模块的开头都应该有一个 docstring,描述该模块做什么。

在本文中,为了简单起见,我们不打算在每个模块的顶部添加一个 docstring。但是,强烈建议在实践中编写 doctrings。和以前一样,如果你想了解更多关于如何在 Python 中使用 doctrings,我推荐你仔细看看 PEP 257 指南。

[## PEP 257 -文档字符串约定

这个 PEP 的目的是标准化文档字符串的高层结构:它们应该包含什么,以及如何表达…

www.python.org](https://www.python.org/dev/peps/pep-0257/)

Pylint 输出

如下所示,pylint 检测到比较运算符

但是,pylint 没有检测到 if 语句中的成员资格操作符也应该被空格包围。Pylint 并不完美!😢

良好实践

运算符两边各有一个空格。

3。逗号、分号或冒号后面的空格(但不是在前面!)

在逗号、分号或冒号之后,我们必须使用空格。然而, PEP 8 建议在即将到来之前避开它们。

不良做法

在下面的代码中,我们可以观察到以下不良做法:

  1. 分隔列表中每个元素的逗号后面缺少空格。
  2. 字典中分隔每个键值对的冒号(:)后面缺少空格。
  3. 在分隔元组中每个元素的逗号之前有一个空格。

Pylint 输出

如上所示, pylint 检测到在分隔列表元素(数字)的每个逗号后面需要一个空格。另外, pylint 检测到元组(坐标)中逗号前有一个空格。但是,它无法检测到分隔每个键-值对的冒号后面缺少的空格。

我想澄清的是,PEP8 指南并没有提到逗号、冒号或分号后需要空格。然而,这是一种普遍的做法,被大多数样式检查器检测为 pylint

良好实践

每个逗号、冒号和分号后面有空格,但前面没有。

4.圆括号、方括号或大括号中的空格。

不良做法

在圆括号、方括号或大括号中会立即使用空格。

Pylint 输出

Pylint 检测圆括号、中括号或大括号前后不允许有空格。

良好实践

圆括号、中括号或大括号内没有直接使用空格。

5.关键字和默认参数

关键字参数

参数是在调用函数时传递给它的值。Python 函数接受两种类型的参数:(1) 位置参数,以及(2) 关键字参数。使用位置参数调用函数时,参数必须以正确的顺序包含。相反,关键字参数可以以任意顺序提供,因为这些参数前面有一个标识符(关键字=值)。根据 PEP8 ,当使用关键字参数调用函数时,我们不必在=符号周围使用空格。

默认参数

函数参数可以有默认值。如果在调用函数时没有提供参数,参数将采用默认值。和以前一样,在定义默认参数时,等号两边不使用空格。

不良做法

当使用关键字默认参数时,在=符号周围使用空格。

Pylint 输出

Pylint 检测关键字参数周围不允许有空格。

良好实践

等号两边不使用空格。

6.捕捉异常

Python 中的错误消息可以分为两种:语法错误异常语法错误Python 无法解释代码时出现,说明程序语法有问题。另一方面,异常发生在代码执行过程中发生意外的事情时。

在下面的代码块中,Python 提供了一条消息,表明我们在尝试将字符串转换为十六进制数时遇到了类型错误,因为十六进制函数需要一个整数作为输入。

为了在 Python 中处理异常,我们使用了 tryexcept 语句。 try 子句包含可以引发异常的操作, except 子句包含处理异常的代码。 try 子句逐个语句执行。但是,如果出现异常,则停止执行 try 语句,然后执行除语句之外的

不良做法

这里,except 块中的代码在 try 块执行期间发生任何类型的异常时都会被执行。根据 PEP8 指南,不建议使用除 子句之外的裸,因为它们会捕捉所有异常,包括 SystemExitKeyboardInterrupt 异常,使得用 Control-C 中断程序更加困难

Pylint 输出

Pylint 检测到使用了除条款之外的空白

良好实践

我们应该在 except 块中指定要处理的错误,如下所示:

现在,程序捕捉到了类型错误异常,但没有捕捉到其他异常。

7.布尔变量

不良做法

if 语句中,使用=is 比较布尔变量与是不正确的。

Pylint 输出

Pylint 检测到与 True 的比较应该只是表达式( is_raining )。

良好实践

我们必须在 if 语句中直接使用布尔变量,如下所示:

8.检查前缀和后缀

不良做法

使用字符串切片来检查前缀或后缀是一种不好的做法。

Pylint 输出

然而, pylint 并没有检测到这个风格问题,虽然它包含在 PEP 8 guide 中。

良好实践

根据样式指南 PEP8 ,我们必须使用 str.startswith()str.endswith() 来检查前缀或后缀。

str.startswith(prefix,start,end) 函数检查字符串是否以给定的前缀开头。如果字符串以指定的前缀开始,函数返回True;否则,返回开始结束是可选参数,指定检查开始和结束的索引。

如果字符串( str )以指定后缀结尾,函数将返回 True 。如果不是,则返回。与之前一样,该函数有两个可选参数 startend 来指定测试开始和结束的索引。

9。进口

一个模块是由 Python 代码组成的文件。如果您正在处理大型项目,将您的代码组织到多个文件中,并在必要时将它们导入到其他 Python 文件中是有意义的。要导入一个 Python 模块,我们只需输入语句 import ,后跟文件名。除了导入我们自己的模块,我们还可以导入 python 标准库中以及第三方库中可用的内置模块。根据 PEP8 准则,导入写在 Python 脚本的顶部,每一个都在一个单独的行上。此外,进口应按以下顺序分组:

  1. 标准库导入
  2. 第三方进口
  3. 本地脚本导入

不良做法

导入没有写在单独的行中,也没有按正确的顺序分组。

Pylint 输出

Pylint 检测到模块 pandas 和 matplotlib 没有写在单独的行上。此外, Pylint 检测到 Python 标准库模块(csv)应该放在第三方导入(pandas 和 matplotlib)之前。正如我们在下面所看到的,Pylint 也认识到所有的导入都是未使用的,因为为了简单起见,我们没有添加更多的代码。

良好实践

导入写在单独的行中,并按正确的顺序分组。

10.λ表达式

Lambda 表达式是匿名短期函数,语法如下:

λ自变量:表达式

这些函数可以有多个参数,返回由表达式 提供的值。我们不仅可以在 Python 中找到它们;其他编程语言也支持 lambda 函数。

根据 PEP8 指南,不建议将 lambda 函数直接分配给标识符。在这种情况下,建议使用常规函数(用 def 关键字定义)。

不良做法

lambda 表达式直接分配给标识符(乘法)。

Pylint 输出

Pylint 没有检测到这个问题,尽管它包含在 PEP 8 guide 中。

良好实践

我们用关键字 def 创建函数。

Pylint 并不完美,但它确实有助于提高代码质量!请记住,代码被阅读的次数要比被编写的次数多得多,这就是为什么坚持有助于他人理解您的代码的约定如此重要。此外,清晰的代码显示了专业性😉。这就是为什么我鼓励你使用像 Pylint 这样的质量检查器(还有很多!)来检查你的代码。看起来会更清晰,更专业👌

在你和你的团队分享你的实验结果之前,检查这 4 件事

原文:https://towardsdatascience.com/check-these-4-things-before-you-share-your-experiments-results-with-your-team-16dac876f435?source=collection_archive---------35-----------------------

经典的实验文献默认实验将运行一次,所有参与者一起到达,并被记录和管理治疗。Web 实验(A/B 测试)在一段时间内收集用户,分别记录暴露和处理,并连续运行。这就产生了一些陷阱——下面是如何测试它们的方法。

我也犯过一些分析错误,有些花费了团队成员数周的时间来做错误的事情,或者更糟——错过了一个很好的机会。但通过这些,我收集了一份分析中一些常见陷阱的清单,无论是实验(A/B 测试)还是观察数据。

1.异质处理效果

这种说法仅仅意味着你看到的效果是不同用户群的不同效果的平均值。例如,也许你的网站的新版本在转化男性方面比女性好得多:男性的转化率比以前高 23%,而女性的转化率略差(-2%)。但是如果你网站的观众 80%是女性,你会认为新版本是个好主意:平均转化率上升了 3%。现实中你的大部分用户喜欢的略少,只对一小部分用户更好。

很少用户非常高兴+大多数用户略微悲伤可能看起来是一个总体良好的结果(图片由作者提供)

为了避免这种情况,通常没有其他办法,只能通过你收集的任何维度(例如,人口统计、地理、设备等)对你的用户进行细分。)并寻找组间效应大小的主要差异。然而,如果你做得太多,你需要小心多重比较(本质上,随机发现不存在的效果)。

不过在某些情况下,你可以通过绘制效果分布图来更直接地测试这一点:有多少%的用户体验到了分配给他们的治疗所带来的效果。例如,当测量类似“用户一个月访问你的服务的平均天数”这样的重复活动时,你可以检查一个实验是否将每个人向上移动了 3%(橙色线),或者是否有+3%的平均效果,但实际效果的分布很广,一些用户受到了变化的伤害(紫色)。然后,尝试找出这些用户的不同之处。

橙色实验对每个人都有同样的效果;紫色实验有一系列的影响(图片由作者提供)

2.混合班次

我检查的一个相关问题是绘制随时间变化的数据时。最糟糕的错误之一是不正确的趋势:如果数据在“方向上”是正确的,但错误了一个常数(所以,当它上涨时,你认为它上涨了,只是没有你想象的那么上涨),这对大多数商业决策来说通常是没问题的。但是当你认为某样东西在上升的时候下降了,你可能会停止一个成功的活动或者倾向于一个有害的活动!

当同时存在异质效应时(因此两个或更多组具有不同的结果,例如保留率)随着时间的推移,一个组在总体中所占的比例在增长,就会出现混合变化。随着时间的推移,这造成了一个错误的趋势,它来自于人口的变化,而不是行为的变化。在上面的例子中,如果你的网站开始搅动女性用户(在我们做出改变后,她们的体验变得更差),你会认为整体转化率在提高——但实际上只有剩下的男性转化得更好,而不是企业成功的整体改善。

从 F 到 M 的种群变化可能会使相同的实验看起来有所改善(图片由作者提供)

3.检查曝光

一个非常微妙的话题,但在线实验的现实是,当我们记录一个人被随机分配到一个实验组时,以及当他们的实际经历发生变化时,有时我们会分离出来。这里有一个例子:在一个电子商务网站上,我可能有一个实验,一半登录的用户在结账时会得到 10%的折扣,另一半不会。天真地说,我可能会在用户进入网站的那一刻就把他们分成两个实验组,A 组和 B 组,并把这个记录在我们的数据库中。然后,我对 A 组和 B 组中哪一组的结账率更高进行了分析,并计算了实验的功效——基本上是确保我有足够多的用户进行实验,以得出关于其效果的具有统计意义的结论。对吗?

嗯,差不多了。事情是这样的,我记录了哪些实验组的用户第一次访问这个网站的时候。但是他们中的很大一部分人(比如说 90%)甚至没有最终购买任何东西。所以他们实际上没有看到优惠券——他们有着与完全没有优惠券的对照组完全相同的体验。因此,他们的购买行为当然不会改变。但是计算实验效果背后的数学方法在这里是误导性的:我们在稀释实验的效果,因为很多人没有购买优惠券。结果,我们最终认为实验是无效的,或者没有达到我们期望的统计显著性水平,并放弃了它。这是“过度暴露”——你把实际上没有接受治疗的人登记到实验中。

过度曝光和曝光不足都会让实验看起来不稳定。签名。当他们是。(图片由作者提供)

在更罕见的相反情况下,我们可能会在记录之前暴露用户在一个实验组中——这可能发生在复杂的设置中,例如,我们只在他们实际结账时记录暴露,而不是当他们第一次看到购物车中的优惠券时——结果我们暴露不足,也冲淡了我们实验的效果(或者更糟糕的是,如果暴露与某些行为相关,可能会得出错误的结论)。

底线是始终确保你清楚用户在哪里第一次遇到实验的任何可能效果,然后才将其纳入实验组(或控制组)

4.一千次(统计上无关紧要)削减造成的死亡

我们知道我们可能会错误地发现一种效应(XKCD 在一项实验中很好地测试了不同颜色的软糖和痤疮之间的联系)。但我们也可能会错过一个效果,因为我们的实验动力不足(很难发现你做的事情提高了 0.1%的转化率,因为这通常需要成千上万的用户)。虽然 0.1%的改进通常对企业的成功并不重要,我们也不应该关注它,但 0.1%的下降一直在发生,很难发现,并且会增加。这里有一个例子:假设我们是一个成长团队,正在试验我们应用程序的各个部分,其中许多测试对我们的日常活跃用户产生了很好的结果。

但是,我们并不傻——我们也检查对长期记忆的影响。如果一个实验对记忆有显著的负面影响,我们会拒绝它。然而,长期保留是一个嘈杂的指标,用更少的用户和更少的能力来衡量,其影响往往更微妙。他们通常平均得出轻微的负面或轻微的正面结果,但是置信区间意味着他们在统计学上是不显著的:我们不能确定他们是负面的。不过,他们中的许多人可能会。我们可能会不知不觉地对记忆力产生微小的负面影响。因此,有了“千刀万剐”(脸书的一位同事创造的)。

在每个单独的实验中,对性能的影响是轻微的,但不是统计的。签名。但是综合起来看,这显然对 Perf 有害。(图片由作者提供)

防止这种情况的主要方法是长期抵制。长期抵制者是一组不接受任何新实验的用户,即使这些实验已经推广到其他用户群。然后,您可以测量所有其他实验一起对长期维持的影响,并查看其他用户的体验是否与维持有显著差异——实质上,维持是对许多实验一起的影响的控制。

我想知道为什么我在职业生涯中花了几年时间才了解这些,结果是在经典实验中不会发生这种情况,在经典实验中,所有参与者通常会被一起放在一个房间里,接受治疗,然后在测量结果后再也不会见到他们。因此,所有关于实验的文献通常都忽略了这些考虑。但是如果你在做在线 A/B 测试,那么保持一小部分用户在“永久控制组”中,观察治疗效果的分布而不仅仅是平均治疗效果,当你观察治疗效果时固定分组,并同时仔细检查你的任务和暴露记录将帮助你避免许多常见的陷阱。

在平台迁移期间检查数据一致性

原文:https://towardsdatascience.com/checking-data-consistency-during-platform-migrations-83eed17479c5?source=collection_archive---------33-----------------------

检查数据的一致性是一项具有挑战性的任务(图片尤利娅·卢卡申娜)

实践教程

确保平稳的数据迁移:我自己在 Salesforce、SAP 和许多其他公司的经验,包括实际例子、图表和代码块

什么是“平台”,它与数据科学有什么关系?

对于平台,我指的是以某种方式永久存储数据的所有软件。不一定是数据分析平台,而是 CRM、ERP(企业资源规划)、活动管理平台等。

十年前,平台迁移曾经是一件独特而罕见的事情。如今,许多公司每隔几年就迁移一次工作流程。有时,他们这样做是因为更好的技术已经到来。更常见的是,一个老的甚至工作良好的人被安排退休。

该平台收集的数据通常用于业务分析报告。通常,业务平台有一个分析扩展。一个很好的例子是 Salesforce 平台及其爱因斯坦分析扩展。在某些情况下,必须定期在第三方工具中提取、处理和可视化数据。

什么是数据一致性,平台迁移有什么问题?

每个平台及其分析扩展都有用于计算和可视化关键性能指标的例程。这些例程因平台而异。有些提供 ETL 工具;有些没有,所以您可以直接在可视化界面中进行一些数据清理。

但是作为企业所有者或经理,您需要一个共同标准,即您日常决策中使用的所有关键 KPI 的标准表示。您还希望确保基础计算可能导致相同或几乎相同的结果,尽管结果可能不同。

迁移结束后,您打开一个新构建但不熟悉的 KPI 仪表板。这些数字对你来说一定还是有意义的。

另一个潜在的陷阱是实现新的计算程序意味着新的数据管道。新的数据存储。从原始位置弹出数据的新方法。一份闪亮的商业报告需要很多步骤才能完成。出现错误的可能性很大。

几个实际例子

到目前为止,这听起来可能太理论化了——这是我过去的几个例子。

亚马逊 S3 的传统平台

几年前,我参与了一次平台迁移,这是因为需要更大的数据存储和更快的基于云的数据管道。该公司决定用亚马逊 S3 云取代传统平台。

客户以。他们保存在 SFTP 服务器上的 CSV 文件。亚马逊 S3 数据管道将对它们进行消化、处理,并创建一个 SQL 数据库。数据库连接到多个 Tableau 仪表板。新数据每天都有。

在向客户展示新系统之前,我们同时运行了一段时间。我们很快注意到,新的管道往往无法提供与旧管道相同的结果。原因之一是。CSV 文件与亚马逊 S3 中创建的模式不匹配。粗略地说,这些文件通常有不同的列名或者数据格式错误。

Google DoubleClick 的传统活动管理工具

还有一次,我的公司想从利基营销管理工具迁移到 Google DoubleClick。因为我们的主要客户希望他的旧报告是一对一的,所以应该从 DoubleClick 中提取数据,写入 SQL 数据库,然后消化到 Microsoft PowerBI 中。

陷阱很快就暴露出来了。与前一种情况一样。CSV 文件包含错误的列名。在谷歌分析中,它们有时会在没有警告的情况下被更改。自从下载了。CSV 文件自动运行,不一致的数据被插入到数据库中,随后破坏了 KPI 仪表板。此外,没有遵循分类维度的命名约定。

新数据也是每天都有。这些差距被自动传输到 PowerBI 可视化中,它们的错误让很多人感到非常沮丧。

SAP 至 Salesforce

我的下一次迁移有一个巨大的范围:该公司希望从 SAP 迁移一个 ERP、一个 CRM 和一个分析工具,SAP 宣布其一些模块退休,转到其竞争对手 Salesforce。Salesforce 并不专注于 ERP 市场。它提供单个软件包,可以帮助您组装预订和发票的工作流程。不过,这需要大量的定制。

因此,来自新 ERP 的数据与来自 SAP 环境的数据非常不同。此外,Salesforce 分析扩展有相当多的细节。在迁移过程中,SAP 数据被直接插入到 Salesforce Einstein Analytics 中。作为两个系统之间的桥梁,SQL 数据库存储两者之间的数据。

的。从 SAP 弹出的 CSV 文件未能添加到数据库中。最重要的是,Einstein Analytics 数据管道交付的结果与我们在 SAP 分析工具中看到的结果有所不同。KPI 就像高度聚合的总收入一样,完全不一样!

即席检查数据一致性

每一个差异都让我去钻研数据。我开发了一些可靠的方法。

向下的方法

您从 KPI 开始,这些 KPI 通常是较小单位值的高度聚合。例如,您会发现不同平台的总收入是不同的。您可以进一步比较每个客户或给定时间段的收入。

可能只有特定客户的金额会有偏差。你继续深入,选择下一层,例如,一个合同。然后是账单。迟早,你会发现差异,现在可以寻找原因。您应该找到一个错误的数据条目。然后你去找出数据条目是什么时候被添加到你的系统中的。查看一堆数据,比如. CSV 文件。可能,它已损坏,与数据结构不匹配,或者有数据格式问题。

向上的方法

根据报告的类型,有时您可以直接分配错误数据条目到达的时间段。或涵盖显示不正确总收入的合同期限的时间段。然后,您可以跳到最低的汇总级别,或者跳到根本没有汇总的级别。例如,您获取每个合同或账单,从每个系统中导出它们,并通过匹配它们的 id 来比较它们。

元数据级别

我不喜欢比较 KPI。这意味着理解他们的业务逻辑。这种逻辑经常会在我不知道的情况下改变。比较元数据似乎是一种更安全的方式,但并不总是足够的。

众所周知,元数据是关于数据的数据。我之前所说的模式。您检查传入的数据是否具有相同的结构。这包括但不限于:

  • 列名
  • 对于某些工具:列顺序!
  • 数据格式,尤其是日期
  • 分类维度的名称

如果您有关于三个营销活动的数据,突然,一个. CSV 有了第四个活动,而您没有处理规则,那么您的数据管道可能会混乱。

数据不一致的其他原因

如果最小的数据单元——合同、账单、预订——在不同的平台上具有不同的值,这意味着您将错误的数据加载到一个或两个数据管道中。

从这个水平开始,偏差只会越来越大,总的结果会越来越大。

在许多情况下,这些最小的单元与管道内的一些附加数据相匹配,如客户、行业等。这允许在流程的后期对数据进行分组和聚合。这些匹配经常失败:客户更改了公司名称,CRM 的名称不正确,名称和 ID 不匹配,等等。

匹配规则中的异常也令人头疼。如果你忘记把旧系统的所有异常都复制到新系统中,你就会有偏差。只有当您开始比较聚合数据时,它们才变得可见。

持续检查数据的一致性

基本上,所有方法都适用于持续监控。你只需要将它们自动化。

您可以监控一个平台,可能是新平台,或者两个都监控。这取决于您对遗留平台的信任或您使用的方法。

从技术角度来看,这是通过以下方式实现的。我提取了两个平台的数据,并把它们进行了对比。我花了有限的一段时间,主要是最近的一段时间。一些计算也需要以前时期的数据。在一些特殊情况下,用户可以调整过去期间的数据条目,比如为当前达到折扣启用值的合同添加折扣。这就是为什么我定期对去年的数据进行一致性检查。

那么,这实际上意味着什么呢?

您可以在其中一个分析扩展中运行检查。或者,您可以从两个系统中导出数据,并在第三个工具中比较元数据。两种方法我都尝试过,但最终都是基于 Python 的管道。

这两个报告的提取也可以自动化。不过,这取决于工具。

比较数据

我下载了两个 CSV。旧平台和新平台上的文件。它们有不同的结构,但是应该有一个键,比如事务 ID。我有一个 R 或 Python 脚本,它处理来自两个系统的数据,获取键,并将其他数据作为键的属性进行比较。

下面是两个(当然是虚构的)导出的截图:

遗留平台样本原始数据:电子商务交易

目标平台样本原始数据:电子商务交易

该脚本将来自两个系统的数据标准化,重命名列或维度,或者使用附加数据将不同的命名放在一起。

例如,交易 313200 在旧系统中的价值为 40,00 美元,在新系统中的价值为 40 美元。它是匹配的。Python 脚本找到了两种格式的共同点,并对实际值进行了比较。

我比较了交易的每一个属性,不仅包括总和,还包括字符串列:

检查单个事务的属性

作为最后一个例子,我附上了总收入比较。

您可能已经注意到,相同的交易在不同的平台上有不同的客户 ID。我转换包含它们的名称的列,并将它们用作键。然后,我对交易值求和,得到每个客户的收入,并计算增量。

比较每个客户的总收入(不同平台之间的差异)

比较元数据

您可以用日期-时间来标记数据的时间戳,以指示它被弹出或被消化的时间。然后,检查最近一段时间(如昨天)添加到数据库的新数据量,以排除此阶段的异常和错误。

您计算在某一天(比如昨天)打上时间戳的行数。

检查元数据:过去 24 小时内添加到两个系统的行数

检查分类变量也是如此。您可以创建一个数据可视化来显示您的维度值,甚至检查是否添加了任何新值。

得到通知

另一个好的做法是创建一个警报,在出现问题时向您发出警告。例如,如果新行的数量小于零。

在小部件上设置通知

定义通知触发器:如果最近没有添加新行

一会儿之后

对于这篇文章,我以稍微简化的形式重新创建了我以前的工作程序。我不能发布完全相同的数据和方法,因为我既没有访问它们的权利,也没有为自己的利益使用它们的权利。我创建了我的真实方法的抽象,使它们匿名和通用。所有特定于公司的信息都被小心翼翼地删除了。除了日常工作之外,我还主动要求定期进行数据一致性检查,并制定方法。

我使用了 sales force Einstein Analytics trail head 操场来构建上面的数据可视化。不涉及数据管道。数据处理直接发生在数据可视化界面中。

下面是我用来构建表的 SAQL 查询:

属性比较:

legacy = load "System_1_Legacy";
legacy = filter legacy by date(Processed_Year, Processed_Month, Processed_Day) in ["1 day ago" .. "1 day ago"]; 
legacy = foreach legacy generate Processed, count() as Count_Rows;
legacy = group legacy by Processed;
legacy = foreach legacy generate Processed as Last_Insert_Date, sum(Count_Rows) as Count_Rows_Legacy;target = load "System_2_Target";
target = filter target by date(System_Timestamp_Year, System_Timestamp_Month, System_Timestamp_Day) in ["1 day ago" .. "1 day ago"]; 
target = foreach target generate System_Timestamp, count() as Count_Rows;
target = group target by System_Timestamp;
target = foreach target generate System_Timestamp as Last_Insert_Date, sum(Count_Rows) as Count_Rows_Target;result = cogroup legacy by Last_Insert_Date full, target by Last_Insert_Date;
result = foreach result generate legacy.Last_Insert_Date as Legacy_Last_Insert_Date, target.Last_Insert_Date as Target_Last_Insert_Date, 
    coalesce(sum(legacy.Count_Rows_Legacy), 0) as Count_Rows_Legacy,
    coalesce(sum(target.Count_Rows_Target), 0) as Count_Rows_Target,
    coalesce(sum(legacy.Count_Rows_Legacy), 0) - coalesce(sum(target.Count_Rows_Target), 0) as Delta_Count_Rows;

总收入比较:

legacy = load "System_1_Legacy";
target = load "System_2_Target";
legacy = filter legacy by date(Processed_Year, Processed_Month, Processed_Day) in ["1 day ago" .. "1 day ago"]; 
target = filter target by date(System_Timestamp_Year, System_Timestamp_Month, System_Timestamp_Day) in ["1 day ago" .. "1 day ago"];legacy = foreach legacy generate Surname + ", " + Name as Customer_Name, Transaction_Value;
result = cogroup legacy by Customer_Name full, target by Name;
result = foreach result generate legacy.Customer_Name as Customer_Name, 
coalesce(sum(legacy.Transaction_Value), 0) - coalesce(sum(target.Total_sum), 0) as Delta;

行数/元数据比较:

legacy = load "System_1_Legacy";
target = load "System_2_Target";
legacy = filter legacy by date(Processed_Year, Processed_Month, Processed_Day) in ["1 day ago" .. "1 day ago"]; 
target = filter target by date(System_Timestamp_Year, System_Timestamp_Month, System_Timestamp_Day) in ["1 day ago" .. "1 day ago"]; 
legacy = foreach legacy generate Transaction_ID, 
                                Surname + ", " + Name as Customer_Name, 
                                Transaction_Currency,
                                Transaction_Timestamp,
                                Processed,
                                Transaction_Value;
result = cogroup legacy by (Transaction_ID, 
                            Customer_Name, 
                            Transaction_Currency,
                            Transaction_Timestamp,
                            Processed) full, 
                target by (Order_ID, 
                            Name, Currency,
                            Ordered_at,
                            System_Timestamp);
result = foreach result generate legacy.Transaction_ID as legacy_ID, target.Order_ID as target_ID,
(case when coalesce(sum(legacy.Transaction_Value), 0) == coalesce(sum(target.Total_sum), 0) then 0 else 1 end) as Transaction_Value_Check,
(case when legacy.Customer_Name == target.Name then 0 else 1 end) as Customer_Name_Check,
(case when legacy.Transaction_Currency == target.Currency then 0 else 1 end) as Transaction_Currency_Check,
(case when legacy.Transaction_Timestamp == target.Ordered_at then 0 else 1 end) as Transaction_Timestamp_Check,
(case when legacy.Processed == target.System_Timestamp then 0 else 1 end) as Processed_Check;

测试愉快!

用 BERT 和 ULMFiT 检查语法。

原文:https://towardsdatascience.com/checking-grammar-with-bert-and-ulmfit-1f59c718fe75?source=collection_archive---------18-----------------------

让我们来看看迁移学习的两个重量级人物在检查语法方面的表现。

绿色变色龙Unsplash 上的照片

迁移学习对于所有 NLP 研究人员来说是一个游戏改变者,所以在开始之前,让我们快速回顾一下什么是迁移学习。

迁移学习(Transfer learning)是一种机器学习方法,其中为一项任务开发的模型被重新用作第二项任务的模型的起点。

简单地说,它将来自一个领域和任务的先验知识运用到不同的领域和任务中。幸运的是,我们有各种这样的模型,它们具有关于语言及其语义的先验知识,所以我们将只使用那些(有知识的)模型,并看看它们如何执行我们手头的任务(这里检查语法)。

但是我们许多人在各种 NLP 任务中面临的一个主要问题是缺乏良好的硬件(GPU 和 TPU),这是 NLP 任务的一个必要条件,因为我们要处理高维密集向量。在本文中,我们将看到如何克服这一点,使用 Google Colab 来训练模型,并使用一台 CPU 机器来测试和使用我们的语法检查器。

让我们见见竞争者

一方面,我们有 fast.ai 的杰瑞米·霍华德和 NUI Galway Insight Center 的 Sebastian Ruder 提出的 ULMFiT。ULMFiT 使用以下新技术实现了最先进的结果:

  • 区别微调
  • 倾斜三角形学习率,以及
  • 逐步解冻

该方法包括将在 Wikitext 103 数据集上训练的预训练语言模型(LM)微调到新的数据集,以使其不会忘记之前学习的内容。

为了与 Fast.ai 的 ULMFIT 竞争,我们有谷歌的 BERT (来自变压器的双向编码器表示),它为大多数 NLP 任务提供了最先进的结果。BERT 的关键技术创新是将 Transformer(一种流行的注意力模型)的双向训练应用于语言建模。这与以前从左到右或者结合从左到右和从右到左训练来查看文本序列的努力形成对比。

在本文中,我们不会深入讨论每个模型的细节,而是看看它们在检查语法方面的表现。

那么数据在哪里呢?

我们将使用语言可接受性语料库(CoLA) 数据集进行单句分类。它是一组被标记为语法正确或不正确的句子。它于 2018 年 5 月首次发布,是“GLUE Benchmark”中包括的测试之一,BERT 等模型正在进行竞争。

让我们看一下我们的数据:

数据集的一小部分。(0 ->错,1->对)。

让我们开始战斗吧

我们将使用 Google Colab 来微调预训练的模型,因为我们可以轻松地使用 Colab 免费提供给我们的 GPU,这将大大减少训练时间。

伯特

对于伯特,我们将使用拥抱脸的 PyTorch 实现,因为它非常简单和直观。以下是我们大致遵循的步骤:

  1. 加载数据集并解析它。
  2. 将句子编码成伯特可以理解的格式。
  3. 训练(微调),它涉及到这些步骤 :
  • 打开我们的数据输入和标签
  • 将数据加载到 GPU 上进行加速
  • 清除上一步中计算的渐变。
  • 正向传递(通过网络输入数据)
  • 反向传递(反向传播)
  • 告诉网络使用 optimizer.step()更新参数
  • 跟踪用于监控进度的变量
  • 我们将指定BertForSequenceClassification作为最后一层,因为它是一个分类任务

4.将微调后的模型保存到我们的本地磁盘或驱动器。

5.下载保存的模型,并在我们的本地机器上做一些语法检查。

这里的笔记本包含了全部代码。

乌尔菲特

Fast.ai 提供了一个简单得多的接口来实现 ULMFIT。以下是涉及的步骤:

  1. 加载数据集并解析它。
  2. 使用我们的数据集建立一个语言模型。
  3. 只使用语言模型的编码器来构建分类器。
  4. 微调分类器(这里是语法检查器)。
  5. 保存微调后的模型。
  6. 下载模型在我们的本地设置中玩。

这里是包含上述代码的笔记本

那么谁是赢家呢?

为了可视化结果,让我们用 HTML 和 CSS 构建一个带有简单 UI 的小 flask 应用程序。这里是 Flask 应用程序的 Github repo ,在这里你可以很容易地下载你自己的模型并使用这个应用程序。

让我们从一些句子开始:

下面是一个简单的陈述。

伯特和乌尔菲特都预测正确。

干得好,伯特,你不适合,你需要更多的训练。

太好了,你们俩都在这里。

这是一个棘手的问题,但乌尔菲特可能有优势。

玩了一天后,伯特似乎是这场战斗的明显赢家。尽管我们可以进一步微调超参数以改善结果。

评估模型的更好方法是通过使用马修相关系数的预测,因为这是更广泛的 NLP 社区用来评估可乐性能的指标。按照这个标准,+1 是最好的分数,而-1 是最差的分数。通过这种方式,我们可以看到我们在这项特定任务中相对于最先进模型的表现有多好。

对于我们的车型,BERT 的 MCC 得分为 0.55 优于 ULMFiT 的 0.4042

结论

在这场战斗中,BERT 可能在理解语言语义方面比 fast.ai 的 ULMFiT 有优势,但我们可以进一步优化我们的模型,以获得更好的结果。我们也可以尝试其他迁移学习模式,如:脸书的 RoBERTa,XLNET,ALBERT 等。用于检查语法。

参考资料:

  1. Fast.ai 文档https://docs.fast.ai/
  2. 拥抱脸变形金刚https://huggingface.co/transformers/index.html
  3. Chris mcCormick 的博客文章http://mccormickml . com/2019/11/11/Bert-research-EP-1-key-concepts-and-sources/

Keras 中的检查点深度学习模型

原文:https://towardsdatascience.com/checkpointing-deep-learning-models-in-keras-a652570b8de6?source=collection_archive---------4-----------------------

了解如何使用检查点保存深度学习模型,以及如何重新加载它们

保存和加载深度学习模型的不同方法正在使用

在本文中,您将了解如何对使用 Keras 构建的深度学习模型进行检查点检查,然后将模型架构和训练好的权重恢复到新模型,或者从您停止的地方恢复训练

检查点的使用

  • 允许我们使用预训练的模型进行推理,而不必重新训练模型
  • 从我们停止的地方继续训练过程,以防训练中断或用于微调模型

在训练因任何原因中断的情况下,它可以自动保存您的模型。

使用检查点保存和加载模型和权重的步骤

  • 创建模型
  • 指定我们要保存检查点文件的路径
  • 创建回调函数来保存模型
  • 在培训期间应用回调函数
  • 根据测试数据评估模型
  • 使用 l oad_weights()从最近的检查点恢复重量,将预训练的重量加载到新型号上

创建具有损失函数、指标和优化器的基础模型架构

我们为时尚 MNIST 数据集创建了多类分类模型

**# Define the model architecture 
def create_model():
    model = tf.keras.Sequential()
    # Must define the input shape in the first layer of the neural network
    model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=2, padding='same', activation='relu', input_shape=(28,28,1))) 
    model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
    model.add(tf.keras.layers.Dropout(0.3))
    model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=2, padding='same', activation='relu'))
    model.add(tf.keras.layers.MaxPooling2D(pool_size=2))
    model.add(tf.keras.layers.Dropout(0.3))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(256, activation='relu'))
    model.add(tf.keras.layers.Dropout(0.5))
    model.add(tf.keras.layers.Dense(10, activation='softmax'))

    #Compiling the model
    model.compile(loss='sparse_categorical_crossentropy',
             optimizer='adam',
             metrics=['accuracy'])

    return model**#create the model
**model_ckpt= create_model()**

指定存储检查点文件的路径

**checkpoint_path = "train_ckpt/cp.ckpt"**

创建回调函数保存模型。

在训练的不同阶段应用回调函数,以给出内部训练状态的视图。

我们使用 模型检查点 创建一个回调函数来保存模型权重。

如果我们将save _ weight _ only设置为 True,那么将只保存重量。模型架构、损失和优化器将不会被保存。

我们还可以指定是否要在每个时期或每隔 n 个时期保存模型。

# Create a callback that saves the model's weights
**cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,save_best_only=True, save_weights_only=True, verbose=1)**

模型检查点回调类具有以下参数:

  • 文件路径:指定我们想要保存模型的路径或文件名
  • 监控:我们想要监控的指标,比如损失或准确性
  • 详细度 : 0 表示调试模式,1 表示信息
  • save_weights_only :如果设置为 True,则只保存模型权重,否则保存整个模型,包括模型架构、权重、损失函数和优化器。
  • save_best_only :如果设置为 True,则根据我们监控的数量,仅保存最佳模型。如果我们正在监控精度并且 save_best_only 被设置为 True,那么模型将在我们每次获得比先前精度更高的精度时被保存。
  • 模式:有三个选项- 自动、最小或最大如果我们正在监控精度,则将其设置为最大值,如果我们正在监控损耗,则将其设置为最小值。如果我们将模式设置为自动,则方向会根据监控的数量自动推断
  • save_freq 或 period : 设置为‘epoch’或一个数字。当它设置为 epoch 时,模型在每个 epoch 后被保存。当我们指定一个数字,比如说 5,那么模型在每五个时期后被保存,如下面的代码所示
# Create a callback that saves the model's weights every 5 epochs
**cp_callback = tf.keras.callbacks.ModelCheckpoint(
    filepath=checkpoint_path, 
    verbose=1, 
    save_weights_only=True,
    save_freq=5)**

在培训过程中应用回调

# Train the model with the new callback
# Pass callback to training
**model_ckpt.fit(train_images, 
          train_labels,  
          batch_size=64,
          epochs=10,
          validation_data=(test_images,test_labels),
          callbacks=[cp_callback])**

我们可以看到,如果 val_loss 没有改善,那么权重就没有保存。每当丢失减少时,这些权重就会保存到检查点文件中

在测试图像上评估模型

**loss,acc = model_ckpt.evaluate(test_images,  test_labels, verbose=2)**

检查点文件

检查点文件以二进制格式将训练好的权重存储到检查点格式化文件的集合中

tensor flowsave()保存三种文件:检查点文件、索引文件、数据文件。它将图形结构变量值分开存储。

检查点文件:包含索引文件以及一个或多个数据文件的前缀

索引文件:指示哪些权重存储在哪个分片。当我在一台机器上训练该模型时,我们看到CP . ckpt . data-00000-of-00002CP . ckpt . data-00001-of-00002

数据文件:保存所有变量的值,无结构。可以有一个或多个数据文件

检查点文件

加载预训练的重量

加载预训练重量的原因

  • 从我们停止的地方继续或
  • 中断后恢复或
  • 加载预训练的重量进行推断

我们创建一个新的模型来加载预训练的权重。

当加载具有预训练权重的新模型时,新模型应该具有与原始模型相同的架构。

# Create a basic model instance
**model_ckpt2 = create_model()**

我们使用load _ weights()将预训练的权重加载到我们的新模型中。

**model_ckpt2.load_weights(checkpoint_path)**

我们可以使用新模型对测试图像进行推断

**loss,acc = model_ckpt2.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))**

未经训练的模型将随机执行(大约 10%的准确度)

从我们停止的地方继续训练

**model_ckpt2.fit(train_images, 
          train_labels,  
          batch_size=64,
          epochs=10,
          validation_data=(test_images,test_labels),
          callbacks=[cp_callback])**

我们看到现在精确度已经改变了

loss,acc = model_ckpt2.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))

从最新的检查点加载权重

latest _ check point()查找最新保存的检查点文件的文件名

#get the latest checkpoint file
**checkpoint_dir = os.path.dirname(checkpoint_path)
latest = tf.train.latest_checkpoint(checkpoint_dir)**

我们创建一个新的模型,从最新的检查点加载权重并进行推理

Create a new model instance
**model_latest_checkpoint = create_model()**# Load the previously saved weights
**model_latest_checkpoint.load_weights(latest)**# Re-evaluate the model
**loss, acc = model_latest_checkpoint.evaluate(test_images,  test_labels, verbose=2)
print("Restored model, accuracy: {:5.2f}%".format(100*acc))**

在文件名中包含纪元编号

# Include the epoch in the file name (uses `str.format`)
**checkpoint_path = "training2/cp-{epoch:04d}.ckpt"**

使用时尚 MNIST 保存模型和重新加载模型的代码

结论:

我们现在了解了如何使用模型检查点类、创建不同的检查点文件来创建回调函数,以及如何恢复预训练的权重

参考文献:

https://www.tensorflow.org/tutorials/keras/save_and_load

创建自定义对象检测模型的简单方法

原文:https://towardsdatascience.com/chess-rolls-or-basketball-lets-create-a-custom-object-detection-model-ef53028eac7d?source=collection_archive---------11-----------------------

数据科学工具包第二部分

介绍

OLO 是我最喜欢的计算机视觉算法之一,很长一段时间以来,我一直计划专门为这个奇迹写一篇博文。然而,我决定我不想让它成为另一篇详细解释 YOLO 如何在幕后工作的文章。至少有一些媒体上的出版物很好地涵盖了事物的理论方面。除此之外,如果你想拓宽你对这个架构的理解,直接从源头获取你的信息并阅读最初的论文也是一个很好的主意。

基于 YouTube-8M 数据集,检测在篮球场上走动的球员

代替理论,这次我将向你展示如何快速地,以相对较低的努力,并且不需要强大的机器,创建定制的模型,能够检测你选择的任何物体。如果你需要在工作中快速测试你的想法,或者只是在家里愉快地建立你的小宠物项目,这是一个很好的方法。去年我有机会做了几个这样的实验,本文中出现的所有可视化都是这些项目的成果。

注意:这一次我们将主要使用开源库和工具,因此我们网站上的编码量将是最小的。然而,为了鼓励你和 YOLO 一起玩,并给你一个项目的起点,我还提供了脚本,允许你下载我预先训练的模型以及所有的配置文件和测试数据集。像往常一样,你会在我的 GitHub 上找到它。

YOLO

一个 你们都不知道 YOLO 是什么——但出于好奇决定点击封面图片——别担心, 哪儿也别去!我现在会简单解释一下我在说什么。

YOLO——或者你只看一次——是一种实时对象检测算法,它是首批平衡所提供预测的质量和速度的算法之一。这种类型中最强大的模型是建立在卷积神经网络之上的,这次也不例外。通过“对象检测模型”,我们的意思是,我们不仅可以使用它来指示给定照片中存在什么对象,还可以指示它们的位置和数量。这种模型在机器人和汽车工业中广泛使用,因此干涉的速度至关重要。自 2015 年以来,这种算法已经有了三次迭代,以及为 TinyYOLO 等移动设备设计的变体。移动版本的精度有限,但它的计算要求也更低,允许它运行更快。

资料组

和深度学习中的惯例一样,创建模型的第一步是准备数据集。监督学习是关于查看带标签的例子,并在数据中找到不明显的模式。我必须承认,创建数据集是一项相当乏味的任务。这就是为什么我准备了一个脚本,可以让你下载我的国际象棋数据集,看看 YOLO 是如何处理这个例子的。

但是那些想要建立自己的数据集的人面临一个挑战。为了实现这个目标,我们需要收集一组图像并创建匹配的标签文件。图片应该包含我们想要识别的物体。还建议数据集群体中所有对象类的分布相似。如你所见,在我的第一个项目——篮球探测器中,我使用了游戏视频中的帧。

篮球数据集中的图像示例

您的标签文件应该与图像具有相同的名称,但显然具有不同的扩展名,并且应该位于一个并行目录中。最佳数据结构如下所示。除了imageslabels目录,我们还必须准备class_names.txt文件,它定义了我们计划检测的对象类的名称。这个文件的每一行都代表一个类,应该包含一个单词或多个单词,不带空格。

project
 └──dataset
    ├── class_names.txt
    ├── images
    │   ├── image_1.png
    │   ├── image_2.png
    │   └── image_3.png
    │       ...
    └── labels
        ├── image_1.txt
        ├── image_2.txt
        └── image_3.txt
            ...

标记

不幸的是,YOLO 需要一种特定的标签格式,大多数免费标签工具都不支持这种格式。为了消除从 VOC XML、VGG JSON 或其他广泛使用的格式解析标签的需要,我们将利用 makesense.ai 。这是我在 GitHub 上开发的一个免费开源项目。该编辑器不仅支持直接导出到 YOLO 格式,而且直观,不需要安装,因为它在浏览器中工作。此外,它支持多种功能,旨在加快您的贴标工作。用 MakeSense 看看 AI 支持的标注过程。

使用 makesense.ai 的人工智能支持的贴标过程

一旦工作完成,我们可以下载一个.zip,包含.txt文件。每个这样的文件对应于一个单独的标签图像,并描述了照片中可见的对象。如果我们打开其中一个文件,我们会发现,每一行都是class_idx x_center y_center width height格式。其中class_idx代表从class_names.txt文件中分配的标签的索引(从 0 开始计数)。其余参数描述围绕单个对象的边界框。它们可以取 0 到 1 之间的值(相对于图像尺寸)。幸运的是,大多数时候我们不需要考虑这些细节,因为编辑器会为我们处理好一切。YOLO 格式的标签示例如下所示。

4 0.360558 0.439186 0.068327 0.250741
7 0.697519 0.701205 0.078643 0.228243
3 0.198589 0.683692 0.076613 0.263441

环境设置

Y OLO 最初是在一个名为 Darknet 的深度学习小众框架中编写的。从那以后,出现了许多其他实现,其中大部分使用了两个非常流行的 Python 平台——Keras 和 PyTorch。在所有可用的解决方案中,有一个是我特别喜欢的。它提供了一个用于训练和检测的高级 API,但也有丰富的有用功能。使用它时,我们所有的工作都归结为准备一个数据集和创建几个配置文件,然后责任就转移到了库上。

project
 ├── dataset
 └── yolov3

环境设置也很简单,因为它归结为运行几个命令,您可能会在下面找到(假设您已经在您的计算机上安装了 PythonGit )。最好从project目录执行命令,以实现上面所示的结构。值得一提的是,该环境也可以通过 Docker 创建(这对 Windows 用户尤其有用)。你可以在这里找到关于这个主题的更多说明。

# Clone framework
git clone [https://github.com/ultralytics/yolov3.git](https://github.com/ultralytics/yolov3.git)
# Enter framework catalogue [Linux/MacOS]
cd ./yolov3
# Setup Python environment
pip install -U -r requirements.txt

配置

正如我在上一段中提到的,我们现在需要做的就是创建几个配置文件。它们定义了我们的训练和测试集的位置、对象类的名称,并提供了所用神经网络架构的指南。

用于标注象棋数据集的参考照片

首先,我们需要将数据集分成训练集和测试集。我们在两个.txt文件的帮助下完成这项工作。它们中的每一个都包含从我们的数据集中指向特定图像的路径。为了加快我们的工作,我准备了一个 Python 脚本,它会自动为我们创建这些文件。您需要做的只是指出数据集的位置,并定义训练集和测试集之间的百分比分割。下面显示了train.txt / test.txt文件的一个片段。

./dataset/images/image_1.png
./dataset/images/image_2.png
./dataset/images/image_3.png
 ...

.data是我们需要提供的最终文件。让我们以我的下一个项目——象棋探测器为例来讨论它的内容。在这种情况下,我有 12 个唯一的对象类需要识别。接下来,我们给出定义哪些照片属于训练集和测试集的文件的位置,最后给出前面讨论的带有标签名称的文件的位置。为了一切正常工作,应将文件chess.datachess_train.txtchess_test.txtchess.names移动到project/yolov3/data目录。

classes=12
train=./data/chess_train.txt
valid=./data/chess_test.txt
names=./data/chess.names

培养

现在我们准备好开始训练了。正如我前面提到的,我们使用的库有一个高级 API,所以终端中的一个命令和几个参数就足以启动这个过程。然而,在这背后,有几件重要的事情正在发生,大大增加了我们获得最终成功的机会。

python3 train.py
   --data ./data/project.data
   --cfg ./cfg/project.cfg
   --weights ./weights/yolov3.pt

首先,我们可以应用迁移学习——我们不必从头开始训练。我们可以使用在不同数据集上训练的模型的权重,这导致我们自己的网络的学习时间更短。我们的模型可以使用基本形状的知识,并专注于将这些信息与我们想要识别的新类型的对象联系起来。其次,该库执行数据扩充,因此它基于我们提供的照片生成新的示例。正因为如此,即使我们只有一个很小的数据集——几百张图片,我们也可以训练我们的模型。我们使用的库也为我们提供了作为增强结果而创建的图像样本。下面你可以看到在我的篮球探测器的训练过程中创建的例子。

在训练集上执行的数据扩充的可视化

侦查

终于,快乐的时刻到来了!我们致力于创建模型的工作得到了回报,因为我们现在可以用它在任何照片中找到我们想要的物体。同样,这是一个非常简单的任务,我们可以在终端中用一个简单的命令来完成。执行之后,我们将在输出目录中找到我们预测的结果。值得一提的是,我们还可以对来自网络摄像头的视频进行现场预测,这在我们希望通过展示演示给大家留下深刻印象时特别有用。

python3 detect.py
   --data ./data/project.data
   --cfg ./cfg/project.cfg
   --weights ./weights/best.py
   --source ./data/sample

使用 TinyYOLO 的国际象棋检测

结论

如果你设法来到这里,祝贺你。非常感谢你花时间阅读这篇文章。如果你喜欢这篇文章,考虑把它分享给你的朋友,或者两个或五个朋友。我希望我设法证明了训练你自己的定制 YOLO 模型并不困难,并且我的提示将在你未来的实验中有所帮助。

本文是“数据科学工具包”系列的另一部分,如果您还没有机会,请阅读其他文章。此外,如果你喜欢我目前的工作,请在 TwitterMedium 上关注我,并在 GitHubKaggle 上查看我正在进行的其他项目。保持好奇!

胸部 CT 扫描 5 分钟机器学习

原文:https://towardsdatascience.com/chest-ct-scan-machine-learning-in-5-minutes-ae7613192fdc?source=collection_archive---------30-----------------------

临床目标、数据表示、任务、模型

作者图片

这篇文章提供了胸部 CT 扫描机器学习的概述,由临床目标,数据表示,任务和模型组织。

胸部 CT 扫描是一种灰度三维医学图像,描绘了胸部,包括心脏和肺。CT 扫描用于诊断和监测许多不同的疾病,包括癌症、骨折和感染。

临床目标

临床目标是指作为研究重点的医学异常。下图显示了一些异常情况,显示为通过 CT 容积的 2D 轴向切片:

图片作者。子图片来自:毛玻璃放射科助理、肺炎卡尔帕纳班萨尔、结节肺部编年史、蜂窝肺Radiopaedia.org、肺气肿TES.com、肺不张研究门

很多 CT 机器学习的论文都聚焦于肺结节

最近的其他工作关注了肺炎、肺气肿、肺癌、气胸和气胸,前者是肺部感染,后者是肺气肿,前者是吸烟导致的一种肺部损伤,后者是肺癌,后者是气胸。

我一直专注于多种异常预测,其中模型同时预测 83 种不同的异常发现

数据

在机器学习模型中,有几种不同的方法来表示 CT 数据,如下图所示:

作者图片

3D 表示包括大约 1000×512×512 像素的整个 CT 体积,以及可以大(例如整个体积的一半或四分之一)或小(例如 32×32×32 像素)的 3D 补片。

2.5D 表示使用不同的垂直平面。

  • 轴面像腰带一样水平,冠状面像头带或旧式耳机一样垂直,矢状面像弓箭手面前的弓箭的平面一样垂直。
  • 如果我们取一个轴向切片、一个矢状切片和一个冠状切片,并将它们堆叠成一个 3 通道图像,那么我们就有一个 2.5D 切片表示。
  • 如果这是用小的小块来完成的,例如 32×32 像素,那么我们有一个 2.5D 的小块表示。

最后,还使用了 2D 表示法。这可以是一个完整的切片(例如 512 x 512),也可以是一个 2D 面片(例如 16 x 16,32 x 32,48 x 48)。这些 2D 切片或贴片通常来自轴向视图。

任务

胸部 CT 机器学习有很多不同的任务。

下图说明了一些任务:

图片作者。子图片来自颜等 2018 深度病变江等 2019

二元分类包括给 CT 表现分配 1 或 0,表示异常的存在(1)或不存在(0)。

多级分类用于互斥的类别,如间质性肺病的不同临床亚型。在这种情况下,模型将 0 分配给除 1 类别之外的所有类别。

多标签分类用于非互斥类别,如肺不张(肺组织萎陷)、心脏肥大(心脏增大)和肿块。CT 扫描可能有一些、全部或没有这些发现,并且模型确定存在哪些(如果有的话)。

目标检测包括预测感兴趣的异常周围的边界框的坐标。

分割包括标记每个像素,这在概念上就像“描绘异常的轮廓并给它们着色”

训练这些模型需要不同的标签。需要异常的“存在或不存在”标签来训练分类模型,例如[肺不张=0,心脏肥大= 1,质量= 0]。需要包围盒标签来训练对象检测模型。训练分割模型需要分割掩模(轮廓中跟踪和填充的)。如果这些标签是从自由文本放射学报告中自动提取的(例如,36,316 CT 的 RAD-ChestCT 数据集),则只有“存在或不存在”标签可扩展到数万次 CT 扫描。获得分割掩模是最耗时的,因为它们必须在每个切片上手动绘制;因此,分割研究通常使用 100-1000 次 CT 扫描。

型号

卷积神经网络是在 CT 数据上使用的最流行的机器学习模型。关于 CNN 的 5 分钟介绍,见本文。

  • 3D CNNs 用于整个 CT 体积或 3D 补片
  • 2D CNN 用于 2.5D 表示(3 个通道,轴向/冠状/矢状),与 2D CNN 可以将 3 通道 RGB 图像作为输入(3 个通道,红/绿/蓝)的方式相同。
  • 2D CNN 用于 2D 切片或 2D 补丁。

一些 CNN 结合了 2D 和 3D 卷积。CNN 也可以被“预训练”,这通常是指首先在像 ImageNet 这样的自然图像数据集上训练 CNN,然后在 CT 数据上精炼 CNN 的权重。

这里是一个架构示例,其中预训练的 2D CNN (ResNet18)应用于 3 个相邻切片的组,然后进行 3D 卷积:

作者图片

间质性肺病分类举例

下表包括几个关注间质性肺病的研究实例,按临床目标、数据、任务和模型组织。

  • 临床目标:这些论文都集中在间质性肺病。不同的研究使用的确切类别不同。一些研究侧重于临床分组,如特发性肺纤维化或特发性非特异性间质性肺炎(如王等人 2019 年和沃尔什等人 2018 年)。其他研究侧重于网状或蜂窝状等肺部模式(如 Anthimopoulos 等人 2016 年和高等人 2016 年)。
  • 数据:数据集由 100–1,200 个 CT 组成,因为所有这些研究都依赖于片、切片或像素的手动标记,这非常耗时。进行碎片、切片或像素级分类的好处在于,除了诊断信息之外,它还提供了定位信息。
  • 任务:任务大多是多类分类,其中每个片或片被分配给多个可能的类中的一个类。
  • 模型:一些研究使用定制的 CNN 架构,等人 2019 和高等人 2018,而其他研究采用现有的 CNN 架构,如 ResNetAlexNet

补充阅读

原载于 2020 年 8 月 4 日 http://glassboxmedicine.com**T21

基于卷积神经网络的胸部 X 线肺炎检测

原文:https://towardsdatascience.com/chest-x-rays-pneumonia-detection-using-convolutional-neural-network-63d6ec2d1dee?source=collection_archive---------13-----------------------

面向初学者的基本 Tensorflow 和 Keras 实现

对于初学者来说,卷积神经网络(CNN)可能看起来有些吓人。然而,该项目将概述如何使用 Tensorflow 和 Keras 从头构建一个模型来检测肺炎。

迷你项目的内容如下:

  • 模型结构
  • 模特培训
  • 模型评估
  • 最终模型预测

什么是肺炎?

肺炎是一种由病毒或细菌感染引起的肺部炎症,病情从轻微到严重不等。这种炎症使患者无法呼吸足够的氧气进入血液。当感染使肺部的气囊(肺泡)充满液体或脓液,可能影响一侧或两侧肺部时,就会发生这种情况。如果你的医生认为你可能患有肺炎,将进行胸部 x 光检查,以发现患者肺部的感染及其扩散程度。

资料组

该实验利用了来自 Kaggle 知识库的名为胸部 x 光图像(肺炎)的数据。点击查看数据集。数据集由正常肺和肺炎肺两类组成,如下图所示。

履行

在我们开始构建卷积神经网络之前,以下是必要的库和依赖项。

模型开发

所以让我们直接进入代码。我们将要开发的模型由几个部分组成,它们是:

  • tf.keras.layers.Conv2D() :卷积层,通过隔离图像特征来提高图像识别
  • TF . keras . layers . maxpooling2d():减少图像中的信息同时保持特征的层
  • TF . keras . layers . flatten():将结果展平为一维数组
  • TF . keras . layers . dense():添加密集连接层

将构建一个五层卷积网络,其中 Conv2D()和 MaxPooling2D()作为一层堆叠在一起。然后,最终卷积层的输出将变平,并适合完全连接的神经元。

此外,在模型适合训练之前,有必要按如下方式配置规格:

  • 丢失:肺炎检测在最后一步使用乙状结肠激活,其结果为 0 或 1(正常或肺炎)。因此,二元交叉熵是最合适的损失函数
  • 优化器:将使用学习率为 0.001 的 RMSprop (均方根传播)
  • 度量:准确度是获得每个历元上的预测准确度的测量度量

下面是 model.summary() 的输出。

我们建立的模型概述如下:

作者插图

模特培训

在模型适合训练之前,我们将设置数据生成器从源文件夹中读取图像,而不是逐个标记图像。在基本概念中,imagedata generator根据图像所在的目录对图像进行标注。这个生成器指向数据的子目录。下面的代码可以描述如下:

  • 通过使用重新缩放参数,执行灰度归一化,以便 CNN 更快收敛。标准化将图像像素从[0…255]转换为[0…1]
  • 创建两个生成器,即 train_generatoreval_generator 。其中 train_generator 指向训练数据的子目录,eval_generator 指向评估数据的子目录
  • 然后,将模型训练 10 个时期,每个时期 10 步

此外,以下是在训练和验证数据集之间的模型训练之后的 10 个时期内的模型准确度和损失率的分析:

模型评估

一旦模型被完全训练,测试数据集将被用于确保最终模型的无偏预测。此模型评估步骤对于衡量训练模型预测未知数据的能力非常有用。

训练后的模型准确率达到 81.25%,如下图所示:

最终预测

现在模型已经准备好进行预测,下面的代码允许用户输入一个图像来确定 x 光图像是否被诊断为肺炎。完整的代码可以在 GitHub 上找到。

输出:

结论

在开发用于肺炎预测的 CNN 模型的整个过程中,我们从零开始建立了一个模型,该模型由 5 层组成,随后是一个完全连接的神经网络。然后,使用单独的看不见的数据来评估训练的模型,以避免偏差预测。结果,测试数据集的准确率达到 81.25%,表明该模型是不错的。这个迷你项目允许初学者获得如何建立一个模型来解决现实世界问题的概述。

毫无疑问,通过执行数据扩充或实施迁移学习概念,可以更好地改进预测模型,从而为模型提供改进空间。因此,这将被添加到未来的故事中作为进一步的增强。

参考

** [## 胸部 x 光图像(肺炎)

5,863 张图片,2 个类别

www.kaggle.com](https://www.kaggle.com/paultimothymooney/chest-xray-pneumonia) [## Keras 文档:图像数据预处理

从目录中的图像文件生成 tf.data.Dataset。如果您的目录结构是:然后调用…

keras.io](https://keras.io/api/preprocessing/image/) [## 深度学习用于从 X 射线图像中检测肺炎

从 X 射线图像中自动检测肺炎

towardsdatascience.com](/deep-learning-for-detecting-pneumonia-from-x-ray-images-fc9a3d9fdba8)**

Python 中独立性的卡方检验以及 IBM HR 分析数据集的示例

原文:https://towardsdatascience.com/chi-square-test-for-independence-in-python-with-examples-from-the-ibm-hr-analytics-dataset-97b9ec9bb80a?source=collection_archive---------5-----------------------

活动发起人Unsplash 上的照片

假设您正在研究一个数据集,并且想要检查两个分类变量是否相互依赖。

动机可能是更好地理解结果变量和预测因子之间的关系,识别相关预测因子等。

在这种情况下,卡方检验可以成为有效的统计工具。

在这篇文章中,我将讨论如何用 Python(从头开始和使用 SciPy)进行这个测试,并用一个流行的 HR 分析数据集 IBM 员工流失和绩效数据集——做例子。

古玩目录

  1. 什么是卡方检验?
  2. 我们要检验的分类变量是什么?
  3. 如何从头开始进行这项测试?
  4. 这样做有捷径吗?
  5. 我们还能做什么?
  6. 有哪些局限性?

概观

卡方检验是一种统计假设检验,用于检验统计量在零假设下的卡方分布,特别是独立性卡方检验通常用于检验两个分类变量之间的独立性【1】。

与该测试相关的关键假设是:1 .从人群中随机抽取的样本。2.在任何变量中,每个主题不能属于一个以上的组。

为了更好地说明这个测试,我选择了来自 Kaggle ( 链接)的 IBM HR 数据集,其中包括一个关于减员、工作满意度、绩效等员工 HR 信息的样本。人们经常用它来揭示员工流失和其他因素之间的关系。

注意,这是由 IBM 数据科学家创建的虚构数据集[2]。

要查看完整的 Python 代码,请查看我的 Kaggle 内核

事不宜迟,让我们进入细节!

探测

让我们首先检查雇员的数量和属性的数量:

data.shape
--------------------------------------------------------------------
(1470, 35)

员工 1470 人,属性 35 个。

接下来,我们可以检查这些属性是什么,并查看是否有任何与它们相关联的缺失值:

data.isna().any()
--------------------------------------------------------------------
Age                         False
Attrition                   False
BusinessTravel              False
DailyRate                   False
Department                  False
DistanceFromHome            False
Education                   False
EducationField              False
EmployeeCount               False
EmployeeNumber              False
EnvironmentSatisfaction     False
Gender                      False
HourlyRate                  False
JobInvolvement              False
JobLevel                    False
JobRole                     False
JobSatisfaction             False
MaritalStatus               False
MonthlyIncome               False
MonthlyRate                 False
NumCompaniesWorked          False
Over18                      False
OverTime                    False
PercentSalaryHike           False
PerformanceRating           False
RelationshipSatisfaction    False
StandardHours               False
StockOptionLevel            False
TotalWorkingYears           False
TrainingTimesLastYear       False
WorkLifeBalance             False
YearsAtCompany              False
YearsInCurrentRole          False
YearsSinceLastPromotion     False
YearsWithCurrManager        False
dtype: bool

识别分类变量

假设我们想检验“流失”和“工作满意度”之间是否有关系。

两类“损耗”的计数:

data['Attrition'].value_counts()
--------------------------------------------------------------------
No     1233
Yes     237
Name: Attrition, dtype: int64

按频率排序的四类“工作满意度”的计数:

data['JobSatisfaction'].value_counts()
--------------------------------------------------------------------
4    459
3    442
1    289
2    280
Name: JobSatisfaction, dtype: int64

请注意,对于“工作满意度”,1 表示“低”,2 表示“中”,3 表示“高”,4 表示“非常高”。

原假设和替代假设

对于我们这里的独立性卡方检验,零假设是在‘流失’和‘工作满意度’之间没有显著的关系。

另一个假设是,在“流失”和“工作满意度”之间有显著的关系。

列联表

为了计算卡方检验统计量,我们需要构建一个列联表。

我们可以使用 pandas 的“交叉表”功能来实现:

pd.crosstab(data.Attrition, data.JobSatisfaction, margins=True)

表中的数字代表频率。例如,“工作满意度”中的“2”和“流失”中的“是”都显示为“46 ”,这意味着在 1470 名员工中,有 46 名员工将他们的工作满意度评为“中等”,他们确实离开了公司。

卡方统计

卡方统计量(X)的计算公式如下所示:

X =总和[(观察值-预期值)/预期值]

术语'观察到的是指我们在列联表中看到的数字,术语'期望的是指零假设为真时的期望数字。

在零假设下,“流失”和“工作满意度”之间没有显著的关系,这意味着流失的百分比在工作满意度的四个类别中应该是一致的。例如,“4”和“流失”的预期频率应该是将工作满意度评为“非常高”的员工人数(总流失/员工总数),即 459237/1470,或大约 74。

让我们计算所有预期的数字,并将它们存储在一个名为“exp”的列表中:

row_sum = ct.iloc[0:2,4].values
exp = []
for j in range(2):
    for val in ct.iloc[2,0:4].values:
        exp.append(val * row_sum[j] / ct.loc['All', 'All'])
print(exp)
--------------------------------------------------------------------
[242.4061224489796,
 234.85714285714286,
 370.7387755102041,
 384.99795918367346,
 46.593877551020405,
 45.142857142857146,
 71.26122448979592,
 74.00204081632653]

注意最后一项(74)验证了我们的计算是正确的。

现在我们可以计算 X:

((obs - exp)**2/exp).sum()
--------------------------------------------------------------------
17.505077010348

自由度

除了 X 之外,我们还需要一个参数,即自由度,其计算方法为(第一个变量中的类别数-1)(第二个变量中的类别数-1),在本例中为(2–1)(4–1),即 3。

(len(row_sum)-1)*(len(ct.iloc[2,0:4].values)-1)
--------------------------------------------------------------------
3

释义

对于 X 和自由度,我们可以使用卡方表/计算器来确定其对应的 p 值,并在给定 alpha 的指定显著性水平的情况下,推断是否存在显著关系。

换句话说,给定自由度,我们知道在零假设下,“观察到的”应该接近“预期的”,这意味着 X 应该相当小。当 X 大于某个阈值时,我们知道 p 值(假设存在零假设,则出现如此大的 X 的概率)极低,我们会拒绝零假设。

在 Python 中,我们可以如下计算 p 值:

1 - stats.chi2.cdf(chi_sq_stats, dof)
--------------------------------------------------------------------
0.000556300451038716

假设显著性水平为 0.05。我们可以得出结论,在“流失”和“工作满意度”之间有着重要的关系。

使用 SciPy

在 Python 中有一个执行这个测试的捷径,它利用了 SciPy 库(文档)。

obs = np.array([ct.iloc[0][0:4].values,
                  ct.iloc[1][0:4].values])
stats.chi2_contingency(obs)[0:3]
--------------------------------------------------------------------
(17.505077010348, 0.0005563004510387556, 3)

请注意,这三个术语分别是 X 统计量、p 值和自由度。这些结果与我们之前手工计算的结果一致。

‘减员’和‘教育’

员工是否离职与工作满意度有关,这多少有些直观。现在让我们看另一个例子,在这个例子中,我们检验“流失”和“教育”之间是否有显著的关系:

ct = pd.crosstab(data.Attrition, data.Education, margins=True)
obs = np.array([ct.iloc[0][0:5].values,
                  ct.iloc[1][0:5].values])
stats.chi2_contingency(obs)[0:3]
--------------------------------------------------------------------
(3.0739613982367193, 0.5455253376565949, 4)

p 值超过 0.5,因此在 0.05 的显著性水平上,我们无法拒绝“流失”和“教育”之间没有关系。

按部门分解分析

我们还可以检查是否存在按部门细分的重要关系。例如,我们知道“自然减员”和“工作生活平衡”之间有很大的关系,但我们想检验这是否与部门无关。首先,让我们看看有哪些部门以及每个部门的员工人数:

data['Department'].value_counts()
--------------------------------------------------------------------
Research & Development    961
Sales                     446
Human Resources            63
Name: Department, dtype: int64

为了确保卡方检验有足够的样本,我们在分析中将只关注 R&D 和销售。

alpha = 0.05
for i in dep_counts.index[0:2]:
    sub_data = data[data.Department == i]
    ct = pd.crosstab(sub_data.Attrition, sub_data.WorkLifeBalance, margins=True)
    obs = np.array([ct.iloc[0][0:4].values,ct.iloc[1][0:4].values])
    print("For " + i + ": ")
    print(ct)
    print('With an alpha value of {}:'.format(alpha))
    if stats.chi2_contingency(obs)[1] <= alpha:
        print("Dependent relationship between Attrition and Work Life Balance")
    else:
        print("Independent relationship between Attrition and Work Life Balance")
    print("")
--------------------------------------------------------------------
For Research & Development: 
WorkLifeBalance   1    2    3   4  All
Attrition                             
No               41  203  507  77  828
Yes              19   32   68  14  133
All              60  235  575  91  961
With an alpha value of 0.05:
Dependent relationship between Attrition and Work Life Balance

For Sales: 
WorkLifeBalance   1    2    3   4  All
Attrition                             
No               10   78  226  40  354
Yes               6   24   50  12   92
All              16  102  276  52  446
With an alpha value of 0.05:
Independent relationship between Attrition and Work Life Balance

从这些输出中,我们可以看到在 R&D 部门中有一个重要的关系,但在销售部门中没有。

警告和限制

进行此分析时有一些注意事项,以及此测试的一些限制:

  1. 为了得出有意义的结论,每个场景中的样本数量需要足够大,但现实中可能并非如此。
  2. 重要的关系并不意味着而不是意味着因果关系。
  3. 卡方检验本身并不能提供除“显著关系与否”之外的额外见解。例如,测试没有告知随着工作满意度的增加,离开公司的员工比例趋于减少。

摘要

让我们快速回顾一下。

我们对独立性进行了卡方检验,以检查 IBM HR 分析数据集中变量之间的关系。我们讨论了用 Python 实现这一点的两种方法,一种是从头开始,另一种是使用 SciPy。最后,我们表明,当一个重要的关系存在,我们也可以分层,并检查它是否是真实的每一个水平。

我希望你喜欢这篇博文,并请分享你的想法:)

查看我的另一篇关于通过 Streamlit 和 PyTorch 构建图像分类的文章:

[## 使用 PyTorch 和 Streamlit 创建影像分类 Web 应用程序

用 50 行代码搭建一个简单的图像分类 app!

towardsdatascience.com](/create-an-image-classification-web-app-using-pytorch-and-streamlit-f043ddf00c24)

参考

[1]https://en.wikipedia.org/wiki/Chi-squared_test
【2】https://www . ka ggle . com/pavansubhasht/IBM-HR-analytics-attraction-dataset

手工卡方独立性检验

原文:https://towardsdatascience.com/chi-square-test-of-independence-by-hand-e87c0d36e7cd?source=collection_archive---------11-----------------------

或者如何测试两个定性变量之间的关联

戴维·潘宁顿的照片

介绍

C 独立性的卡方检验检验两个定性变量是否独立,即两个分类变量之间是否存在关系。换句话说,该测试用于确定两个定性变量之一的值是否依赖于另一个定性变量的值。

如果测试显示两个变量之间没有关联(即变量是独立的),这意味着知道一个变量的值不会给出另一个变量的值的信息。相反,如果测试显示变量之间的关系(即变量是相关的),这意味着知道一个变量的值就提供了关于另一个变量的值的信息。

本文重点介绍如何手工执行独立性的卡方检验,以及如何用一个具体的例子来解释结果。要了解如何在 R 中进行这个测试,请阅读文章“R 中独立性的卡方测试”。

假设

独立性的卡方检验是一种假设检验,因此它有一个零假设(H0)和一个替代假设(H1):

  • H0:变量是独立的,两个分类变量之间没有关系。知道一个变量的值无助于预测另一个变量的值
  • H1:变量是相关的,两个分类变量之间有关系。知道一个变量的值有助于预测另一个变量的值

测试是如何进行的?

独立性卡方检验的工作原理是,如果两个分类变量之间没有关系,则将观察到的频率(即样本中观察到的频率)与预期频率(即零假设为真时的预期频率)进行比较。

如果观察频率和预期频率之间的差异很小,我们不能拒绝独立性的零假设,因此我们不能拒绝两个变量不相关的事实。另一方面,如果观察频率和预期频率之间的差异很大,我们可以拒绝独立性的零假设,因此我们可以得出两个变量相关的结论

小差异和大差异之间的阈值是来自卡方分布的值(因此称为测试)。该值称为临界值,取决于显著性水平α(通常设置为等于 5%)和自由度。这个临界值可以在卡方分布的统计表中找到。关于这个临界值和自由度的更多信息将在本文后面介绍。

例子

以我们的例子为例,我们想确定吸烟和成为职业运动员之间是否有统计学上的显著联系。吸烟只能是“是”或“不是”,做职业运动员只能是“是”或“不是”。感兴趣的两个变量是定性变量,因此我们需要使用独立性的卡方检验,并且已经收集了 28 个人的数据。

注意,为了简单起见,我们选择了二元变量(二元变量=具有两个水平的定性变量),但是独立性的卡方检验也可以在具有两个以上水平的定性变量上进行。例如,如果变量吸烟有三个水平:(I)不吸烟者,(ii)中度吸烟者和(iii)重度吸烟者,测试的步骤和结果的解释与两个水平的测试相似。

观察到的频率

我们的数据汇总在下表中,报告了每个亚组的人数、按行、按列的总数以及总计:

预期频率

请记住,对于独立性的卡方检验,我们需要确定如果两个变量之间没有关联,观察到的计数是否与我们预期的计数显著不同。我们有观察到的计数(见上表),所以我们现在需要计算变量独立情况下的预期计数。使用以下公式逐一计算每个子组的这些预期频率:

obs 在哪?符合观察结果。给定我们上面的观察频率表,下面是为每个亚组计算的预期频率表:

请注意,只有当所有组中的预期频率等于或大于 5 时,才应进行独立性卡方检验。我们的例子满足了这个假设,因为预期频率的最小数量是 5。

检验统计量

我们有观察到的和预期的频率。我们现在需要比较这些频率,以确定它们是否有显著差异。观察频率和预期频率之间的差异称为检验统计量(或 t-stat ),用χ2 表示,计算如下:

其中 O 代表观察频率,E 代表预期频率。我们使用观察频率和预期频率之间的差值的平方来确保负差值不会被正差值所补偿。该公式看起来比实际更复杂,所以让我们用例子来说明它。我们首先根据以下公式逐一计算每个子组中的差异:

然后我们将它们相加,得到检验统计量:

临界值

单独的检验统计不足以得出两个变量之间的独立性或依赖性的结论。如前所述,这个测试统计量(在某种意义上是观察到的频率和预期的频率之间的差异)必须与临界值进行比较,以确定差异是大还是小。如果不从临界值的角度来看,就无法判断一个检验统计量是大还是小。

如果测试统计值高于临界值,这意味着观察到观察频率和预期频率之间的差异的可能性不大。另一方面,如果检验统计低于临界值,则意味着观察到这种差异的概率是可能的。如果有可能观察到这种差异,我们不能拒绝这两个变量是独立的假设,否则我们可以得出结论,变量之间存在关系。

临界值可在卡方分布的统计表中找到,并取决于显著性水平(表示为αα)和自由度(表示为 dfdf)。显著性水平通常设置为等于 5%。独立性卡方检验的自由度如下:

df =(行数 1) ⋅(列数 1)

在我们的例子中,自由度因此是 df =(21)⋅(21)= 1,因为列联表中有两行和两列(总数不作为一行或一列计算)。

我们现在有了在卡方表中找到临界值的所有必要信息(α = 0.05,df = 1)。为了找到临界值,我们需要看看下图中 df = 1 的行和χ^2_0.050(因为α = 0.05)的列。临界值是 3.84146。 1

卡方表——α= 5%和 df = 1 时的临界值

结论和解释

既然我们已经有了检验统计量和临界值,我们可以比较它们来检查变量独立性的零假设是否被拒绝。在我们的例子中,

测试统计= 15.56 >临界值= 3.84146

像任何统计检验一样,当检验统计量大于临界值时,我们可以在指定的显著性水平上拒绝零假设。

在我们的案例中,我们因此可以在 5%的显著性水平上拒绝两个分类变量之间独立性的零假设。

这意味着吸烟习惯与是否是运动员之间有很大关系。知道一个变量的值有助于预测另一个变量的值。

感谢阅读。我希望这篇文章能帮助您手工执行独立性卡方检验并解释其结果。如果你想了解如何在 R 中做这个测试,请阅读文章“R 中独立性的卡方测试”。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

相关文章:

原载于 2020 年 1 月 27 日 https://statsandr.com

R 中独立性的卡方检验

原文:https://towardsdatascience.com/chi-square-test-of-independence-in-r-c109947ca73a?source=collection_archive---------15-----------------------

如何检验两个定性变量之间的独立性

乔治·托马塞蒂拍摄的照片

介绍

他的文章解释了如何在 R 中进行独立性卡方检验,以及如何解释其结果。要了解更多关于测试如何工作以及如何手工操作的信息,我邀请您阅读文章“手工卡方独立性测试”。

简要回顾一下那篇文章中所说的内容,卡方独立性检验测试两个分类变量之间是否存在关系。无效假设和替代假设是:

  • H0:变量是独立的,两个分类变量之间没有关系。知道一个变量的值无助于预测另一个变量的值
  • H1:变量是相关的,两个分类变量之间有关系。知道一个变量的值有助于预测另一个变量的值

独立性卡方检验的工作原理是,如果两个分类变量之间没有关系,则将观察到的频率(即样本中观察到的频率)与预期频率(即零假设为真时的预期频率)进行比较。

数据

对于我们的示例,让我们重用文章“R中的描述性统计”中介绍的数据集。这个数据集是众所周知的稍微增强的iris数据集。因为只有一个分类变量,而卡方检验需要两个分类变量,所以我们添加变量size,如果花瓣的长度小于所有花的中值,则对应于small,否则对应于big:

dat <- irisdat$size <- ifelse(dat$Sepal.Length < median(dat$Sepal.Length),
  "small", "big"
)

我们现在用table()函数创建两个变量Speciessize列联表:

table(dat$Species, dat$size)##             
##              big small
##   setosa       1    49
##   versicolor  29    21
##   virginica   47     3

列联表给出了每个亚组中观察到的病例数。例如,只有一朵大刚毛藻花,而数据集中有 49 朵小刚毛藻花。

绘制一个条形图来直观地表示数据也是一个很好的做法:

library(ggplot2)ggplot(dat) +
  aes(x = Species, fill = size) +
  geom_bar() +
  scale_fill_hue() +
  theme_minimal()

如果您更喜欢用比例来形象化它(因此所有条形的高度都是 1 或 100%):

ggplot(dat) +
  aes(x = Species, fill = size) +
  geom_bar(position = "fill")

如果在 x 轴上绘制的变量的每个级别中有不同数量的观察值,则第二个条形图特别有用,因为它允许在相同的基础上比较两个变量。

参见文章“R 中的Graphics with gg plot 2”了解如何在{ggplot2}中创建这种条形图。

R 中独立性的卡方检验

对于这个例子,我们将在 R 中测试变量Speciessize之间是否有关系。为此,使用chisq.test()功能:

test <- chisq.test(table(dat$Species, dat$size))
test## 
##  Pearson's Chi-squared test
## 
## data:  table(dat$Species, dat$size)
## X-squared = 86.035, df = 2, p-value < 2.2e-16

您需要的一切都会出现在这个输出中:

  • 测试的标题,
  • 使用了哪些变量,
  • 测试统计,
  • 自由度和
  • 测试的 p 值。

您还可以使用以下方法检索χ2 检验统计和 p 值:

test$statistic # test statistic## X-squared 
##  86.03451test$p.value # p-value## [1] 2.078944e-19

如果你需要找到期望的频率,使用test$expected

如果出现诸如“卡方近似可能不正确”的警告,这意味着最小预期频率低于 5。要避免此问题,您可以:

  • 收集一些水平(尤其是那些具有少量观察值的水平)以增加子组中的观察值,或者
  • 使用费希尔精确检验

费希尔的精确检验不需要假设最少 5 个预期计数。由于功能fisher.test(),它可以在 R 中应用。该检验在假设和结果解释方面类似于卡方检验。在专门讨论这种测试的文章中了解更多关于这种测试的信息。

供您参考,还有另外三种方法来执行 R 中独立性的卡方检验:

  1. 具有summary()功能
  2. 使用{vcd}包中的assocstats()功能
  3. 使用{summarytools}包中的ctable()功能
# second method:
summary(table(dat$Species, dat$size))## Number of cases in table: 150 
## Number of factors: 2 
## Test for independence of all factors:
##  Chisq = 86.03, df = 2, p-value = 2.079e-19# third method:
library(vcd)
assocstats(table(dat$Species, dat$size))##                      X^2 df P(> X^2)
## Likelihood Ratio 107.308  2        0
## Pearson           86.035  2        0
## 
## Phi-Coefficient   : NA 
## Contingency Coeff.: 0.604 
## Cramer's V        : 0.757library(summarytools)
library(dplyr)

# fourth method:
dat %$%
  ctable(Species, size,
    prop = "r", chisq = TRUE, headings = FALSE
  ) %>%
  print(
    method = "render",
    style = "rmarkdown",
    footnote = NA
  )

如你所见,所有四种方法给出了相同的结果。

如果不同方法的数据没有相同的p-值,请确保在chisq.test()函数中添加correct = FALSE参数,以防止应用 Yate 的连续性校正,该校正在此方法中默认应用。 1

结论和解释

从输出和test$p.value我们看到 p 值小于 5%的显著性水平。像任何其他统计检验一样,如果 p 值小于显著性水平,我们可以拒绝零假设。

在我们的上下文中,拒绝独立性卡方检验的零假设意味着物种和大小之间存在显著的关系。因此,知道一个变量的值有助于预测另一个变量的值。

绘图和统计检验相结合

我最近从{vcd}包中发现了mosaic()功能。该函数的优势在于它结合了镶嵌图(可视化列联表)和独立性卡方检验的结果:

library(vcd)mosaic(~ Species + size,
       direction = c("v", "h"),
       data = dat,
       shade = TRUE)

如您所见,镶嵌图类似于上面的柱状图,但是卡方检验的 p 值也显示在右下角。

此外,如果变量是独立的,这个彩色镶嵌图显示了观察频率与预期频率的偏差。红色情况表示观察频率比预期频率小,而蓝色情况表示观察频率比预期频率大。

另一种选择是{ggstatsplot}封装中的ggbarstats()功能:

# load packages
library(ggstatsplot)
library(ggplot2)# plot
ggbarstats(
  data = dat,
  x = size,
  y = Species
) +
  labs(caption = NULL) # remove caption

从剧情来看,似乎大花更有可能属于virginica种,小花更倾向于属于setosa种。因此,预计物种和大小是相互依赖的。

这一点得到了图表副标题中显示的统计结果的证实。有几个结果,但在这种情况下,我们可以关注显示在p =之后的 p 值。

和前面的测试一样,我们拒绝零假设,我们得出结论,物种和大小是相关的(p 值< 0.001)。

感谢阅读。我希望这篇文章有助于您执行 R 中独立性的卡方检验并解释其结果。如果你想了解如何手工做这个测试以及它是如何工作的,请阅读文章“手工卡方独立性测试”。

和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。

  1. 感谢 Herivelto 指出这一点。 ↩︎

相关文章:

原载于 2020 年 1 月 27 日 https://statsandr.com

特征选择的卡方检验及其 Python 实现

原文:https://towardsdatascience.com/chi-squared-test-for-feature-selection-with-implementation-in-python-65b4ae7696db?source=collection_archive---------5-----------------------

一个统计测试,用于识别两个变量之间的关联/关系及其在 Python 中的实现。

图片提供:全菲尼克斯,[Pinterest 邮报]。于 2020 年 2 月 13 日从 https://in.pinterest.com/pin/641059328193274870/检索

简介:

机器学习中有各种技术来确定我们的输入特征是否与要预测的结果相关。我们可以使用这些技术找出并删除对模型结果没有贡献的不重要的特性。在某种程度上,我们只选择那些真正重要的特征,因此这些技术被称为特征选择方法。卡方检验可用于特征选择。让我们深入细节。

特征选择方法:

确定特征重要性的方法有很多,主要分为两组:

  1. 过滤器特征选择方法
  2. 包装器特征选择方法

我们将只看到第一个,因为我们的卡方检验属于这一类。

简而言之,滤波器特征选择方法是那些使用一些统计技术(如卡方检验)考虑输入和目标变量的数据类型来评估它们之间关系的方法。

有许多其他的统计测量可用于基于过滤器的特征选择。因此,统计测量的选择高度依赖于特征和目标变量数据类型。

数据类型可以是数字的,也可以是分类的。

何时使用卡方检验:

当要测试的特征的数据类型和目标变量都是分类的(即我们有一个分类问题)时,我们可以使用卡方检验。

卡方检验解释道:

皮尔逊卡方检验,或简称卡方检验,是以数学家 卡尔·皮尔逊 命名的。它也被称为“拟合优度”统计量。

让我们看看如何进行这个测试,以及 8 个简单步骤中的一个例子。

例如,让我们考虑一个只有两列的非常简单的数据集。我们将发现性别是否与对运动的兴趣相关/依赖/联系在一起。

╔════════╦══════════╗
║ Gender ║ Interest ║
╠════════╬══════════╣
║ Male   ║ Cricket  ║
║ Female ║ Tennis   ║
║ Male   ║ Cricket  ║
║ Male   ║ Football ║
║ ....   ║ ....     ║
╚════════╩══════════╝

步骤 1:定义假设

假设检验是一种统计方法,它评估两个陈述(假设)并确定哪个陈述是正确的。在假设检验中,最初的陈述被称为零假设,表示为 H0 ,通常与第一个陈述互补的第二个陈述被称为替代假设,表示为 H1。

对于我们的例子,假设是:
H0: 特征性别兴趣独立(也就是说它们没有关联)。
H1: 性别兴趣不是独立的(也就是说它们是关联的)。

第二步:选择一个重要级别

基本上,由α (alpha)表示的显著性水平是我们希望对我们的结果有多确定的度量。

或者简单地说,显著性水平用于确定是否应该拒绝零假设。对于要拒绝的零假设,p 值**(稍后解释)应小于显著性水平。

较低的α值通常是优选的,可以在 0.01 至 0.10 的范围内。

我们选择 α = 0.05

步骤 3:创建列联表

以行和列显示一个变量和另一个变量的频率分布的表格,用于研究两个变量之间的相关性,称为列联表(也称为交叉制表或交叉表)。看到下表后你会更清楚:

*╔══════════════╦═════════╦══════════╦════════╦═══════════╗
║              ║ Cricket ║ Football ║ Tennis ║ Row Total ║
╠══════════════╬═════════╬══════════╬════════╬═══════════╣
║ Male         ║      20 ║       30 ║     15 ║        65 ║
║ Female       ║      20 ║       15 ║     30 ║        65 ║
║ Column Total ║      40 ║       45 ║     45 ║       130 ║
╚══════════════╩═════════╩══════════╩════════╩═══════════╝*

我们可以看到,在数据集中的 130 名候选人中,分别有 20 名、30 名和 15 名男性对板球、足球和网球感兴趣。同样,分别有 20、15 和 30 名女性对板球、足球和网球感兴趣。

表中的值称为观察值。

步骤 4:计算预期频率

我们计算每个单元的预期频率计数。计算预期频率的公式为:

*E = (row total * column total)/grand total*

第一个细胞(即雄性蟋蟀)的预期频率为:

*E₁ = (65 * 40)/130 = **20***

我们计算其余单元的预期频率,并得到下表,其中括号 '[]' 中的值表示预期频率:

*╔══════════════╦═════════╦════════════╦═══════════╦═══════════╗
║              ║ Cricket ║  Football  ║  Tennis   ║ Row Total ║
╠══════════════╬═════════╬════════════╬═══════════╬═══════════╣
║ Male         ║ 20 [20] ║  30 [22.5] ║ 15 [22.5] ║        65 ║
║ Female       ║ 20 [20] ║  15 [22.5] ║ 30 [22.5] ║        65 ║
║ Column Total ║ 40      ║ 45         ║ 45        ║       130 ║
╚══════════════╩═════════╩════════════╩═══════════╩═══════════╝*

步骤 5:计算卡方值或卡方统计

计算卡方值或χ的公式为:

其中χ不是我们所知道的英语 aphabet 而是第 22 个希腊字母 Chi
如图所示,χ是所有小区的观测频率和预期频率之间的平方差除以预期频率的总和。计算结果如下所示:

***Χ² = ((20-20)^2/20) + ((30-22.5)^2/22.5) + ((15-22.5)^2/22.5) + ((20-20)^2/20) + ((15-22.5)^2/22.5) + ((30-22.5)^2/22.5)****Χ² = 0 + 2.5 + 2.5 + 0 + 2.5 + 2.5****Χ² = 10***

步骤 6:计算自由度

自由度可以计算如下:

*df = (total_rows - 1) * (total_cols - 1)*

列联表中有 2 行3 列,因此我们的自由度是 2。

第七步:寻找 p 值

我们可以看到像这样的卡方分布表,这个使用卡方和自由度值找到 p 值。

如果您打开了到表的链接,选择左边的自由度值(2),沿着它的行找到最接近卡方值(10)的数字,然后检查第一行中的相应数字,得到 p 值 0.005

也有一些网站像这个一样为你计算 p 值。
这里我们得到的 p 值为. 0067,我们可以使用其中任何一个,让我们继续使用从表中得到的那个。

步骤 8: 决定是拒绝还是保留我们的零假设

简而言之,如果我们的 p 值小于显著性值,我们拒绝零假设,如果我们的 p 值大于显著性值,我们不拒绝它

由于 0.005 小于我们的显著性值 0.05,我们拒绝零假设,这意味着性别和感兴趣的运动之间存在关联。

用 python 实现

*# required imports
from scipy.stats import chi2_contingency# we create contingency table same as above
table = [[20, 30, 15], [20,  15,  30]]# Get chi-square value , p-value, degrees of freedom, expected frequencies using the function **chi2_contingency**
stat, p, dof, expected = chi2_contingency(table)# select significance value
alpha = 0.05# Determine whether to reject or keep your null hypothesis
print('significance=%.3f, p=%.3f' % (alpha, p))
if p <= alpha:
    print('Variables are associated (reject H0)')
else:
    print('Variables are not associated(fail to reject H0)')*

为了简单起见,我创建了一个列联表。要从数据帧列中创建列联表,可以使用 pandas 中的交叉表函数。

摘要

我们已经看到了如何进行卡方检验来检查两个分类变量之间是否存在某种关系。

用很少几行代码我们就可以使用 Python 的 scipy 库实现这个测试。

希望你喜欢。建议总是受欢迎的。

参考资料:

* [## 机器学习的卡方检验简介

应用机器学习中的一个常见问题是确定输入特征是否与输出相关

machinelearningmastery.com](https://machinelearningmastery.com/chi-squared-test-for-machine-learning/) [## 卡方检验

术语“卡方检验”,也写作,指的是某些类型的统计假设检验是有效的…

en.wikipedia.org](https://en.wikipedia.org/wiki/Chi-squared_test)*

时尚外观,带 Chiclet 切片器的 Power BI

原文:https://towardsdatascience.com/chic-look-in-power-bi-with-chiclet-slicer-ad726af94a14?source=collection_archive---------30-----------------------

使用新的切片选项增强您的功耗 BI 报告

Cottonbro 在 Pexels.com 拍摄的照片

在 Power BI 报告创建中使用自定义视觉效果,为您提供了扩展内置视觉功能的绝佳机会。Appstore 中有数百种自定义视觉效果,我建议你在想用非标准视觉效果丰富你的报告时查看它们。

这是 Power BI 的主要优势之一——您可以从数百种视觉效果中进行选择,以一种吸引人的方式讲述您的数据故事。

Chiclet 切片机

最近,我遇到了一个基于姓氏对客户进行切片的特定请求。它们是按字母顺序排序的,但是要求只查看姓氏以 r 开头的客户。

第一步是从市场上导入 Chiclet Slicer visual。单击可视化窗格下的三个点,然后选择从 AppSource 导入。

在搜索字段中输入 Chiclet,看到它后,单击添加。

现在,您已经准备好在您的报告中使用 Chiclet Slicer 了。下一步是只提取客户姓氏的第一个字母。我将使用 Adventure Works 2017 数据库进行演示。

由于我想查看客户的全名,我将首先在 DimCustomer 表中创建一个新列,并将客户的姓和名连接起来:

*Full Name = DimCustomer[LastName] & " " & DimCustomer[FirstName]*

下一步是从该列中提取第一个字母,最简单的方法是使用 LEFT 函数:

*Cust Lastname 1st = LEFT(DimCustomer[LastName],1)*

数字 1 告诉函数只在文本左侧保留一个字符,并删除其他所有字符。

一旦我这样做了,我就可以在报表上拖动 Chiclet Slicer,并将我新创建的列 Cust Lastname 1st 作为切片的类别:

现在,我可以只选择那些姓氏以特定字母开头的客户,所有其他可视化结果也将被相应地过滤。

你也可以将“首字母技巧”用于其他类别,如产品、国家等。

用图像增强切片器

Chiclet slicer 还为您提供了一个很好的功能,可以将图像用作切片器。为了证明这一点,我将使用 Adventure Works 2017 数据库中作为地区存在的特定国家的国旗。

我使用维基百科的网址,但是你可以自由选择你想要的任何来源。您可以在 DimGeography 表中创建一个附加列,并为每个国家插入一个 web URL。但是,在这种情况下,您的数据模型将变得更大,因为您不能忘记计算列是数据模型的一部分,因此会占用内存空间。

为了避免这种情况,我使用 DimGeography 和 web URL 中的国家/地区代码将数据规范化到一个单独的表中。权力匕很聪明的认出了这两张表的关系:

现在,非常重要的一步是正确标记图像的 URL,以便 Power BI 可以将其作为图像处理。您可以通过单击列标志 URL 并将此列归类为图像 URL(列工具选项卡下的数据类别下拉菜单)来实现。

现在,是时候将 Chiclet Slicer 再次拖到我们的报告中了。将国家/地区代码作为一个类别,将标志 URL 作为图像。

然后,在格式窗格下,您可以尝试各种属性的不同定制。我已经将图像分割值设置为 80,这样类别和图像都可见,但是您也可以通过将该值放大到 100 来选择仅在您喜欢时查看图像。

正如我所说的,尝试不同的数字,直到你得到最适合你的报告的外观和感觉。

结论

Chiclet Slicer 是您的另一个有趣的工具,它通过扩展标准的可视化,为您提供了增强报表的可能性。但是,要小心,不要过度使用。最重要的是找到正确的平衡并在一些有意义的特定场景中使用它。

感谢阅读!

订阅这里获取更多有见地的数据文章!

机器学习儿童指南

原文:https://towardsdatascience.com/childrens-guide-to-machine-learning-b90171f86cef?source=collection_archive---------21-----------------------

向未来的领导者介绍当今最重要的技术之一。

来源:https://undraw.co

(本文旨在让小学生也能轻松理解机器学习的基础知识。反过来,这将使每个人都可以访问它。如果你觉得有哪个部分没有达到你的目的,请在评论中告诉我,我会努力改进这个部分)

成年人喜欢用很多复杂的词来说一些事情。这可能是因为他们想展示他们令人印象深刻的词汇。在像计算机科学这样有很多专业术语的技术领域,情况变得更糟。这些技术词汇应该有助于区分相似的想法。但最常见的是,它使简单的想法变得复杂。在这篇文章中,我会尽量不使用这些复杂的词汇。这是为了让你能清楚地理解想法,而不是死记硬背大词。所以让我们从一点历史开始。

让我们从头开始。

你可能已经看到你周围都是电脑。从智能手表到手机、平板电脑和笔记本电脑,它们都是不同形式的计算机。今天这些有用的小玩意一直是“哑机器”。他们擅长服从命令,就像一只听话的小狗(或者像小猫一样古怪的人)😀).如果你告诉它向右刷,它就向右刷。如果你告诉它向左滑动,它就向左滑动。如果你告诉它打开 Instagram,当有人点击 Instagram 图标时,它就会打开它。你明白了。它自己想不出任何东西。

尽管这些机器很笨,但在过去的 50 年里,我们已经让计算机做了很多事情。从添加数字和播放歌曲到在国际象棋中击败大师。但是对于这些事情中的每一件,必须有人告诉计算机该做什么以及具体怎么做。

所以计算机能为我们做的事情是有限的。计算机只能做我们可以展示给它们如何做的事情(一步一步地)。正如你所猜测的,这种魔力很快就失去了它的魅力。总有一些事情:

  • 连人类都不知道怎么做(更别说向计算机解释了)
  • 以及一些我们不知道如何告诉计算机做什么的任务。(我们无法用机器能理解的语言解释清楚)

(告诉计算机做什么和怎么做的一个大词是 编程。但是我们不会用这些大词,因为我们还不想成为成年人。)

今天有什么故事?

在很长一段时间里,如果没有人告诉计算机如何做某件事,它们什么也做不了。直到最近还是如此。一些非常聪明的人找到了一种教计算机自学的方法。(大人对此用的另一个大词是 【机器学习】 但是嘶。谁需要那个)。想象你在一个没有老师的教室里。在那里,你和你所有的同学在没有任何老师的情况下自学。很奇怪吧?想象一下计算机自己学习是多么奇怪。令人惊讶的是,计算机非常擅长自己学习。它甚至能学会人们教不了它的复杂东西。

(他们不断尝试教计算机,直到慢慢地,即使是愚蠢的计算机也开始学习

“自学”是什么意思😮?

我们教计算机的方法是给它看许多问答的例子。专家们喜欢将整套例子称为数据集。这些例子包含一个样题( x )**及其正确答案( y )。一个例子可以包含例如“一张猫的图片”和它的回答“猫”。

这很像学校里一些好老师在考试前做的小测验。这个小测验样本有助于你对考试内容有所准备。你可能不会在考试中得到完全相同的问题,但它有助于你准备类似类型的问题。

我们向计算机展示问题和答案的例子,而不告诉它如何找到正确的答案。利用这些例子,计算机试图找出一种方法来猜测正确答案。它学会做出正确的猜测,即使它在我们展示的例子中没有看到这个特定的问题。计算机寻找它以前见过的类似问题,并使用以前见过的正确答案进行猜测。这就是计算机所做的一切——根据之前看到的例子进行猜测。

懂数学的人有一种奇怪的癖好,喜欢用无意义的字母来称呼事物。学生们最害怕的字母是 X。来自世界任何角落的每个学生都花了无数个小时来尝试“寻找 X”。字体这个数学领域叫做代数,尽管它看起来很奇怪,但却非常有用。在用字母、数字甚至类似外星人的符号漂亮地表达非常复杂的想法时,它是有用的。)

“猜你说,就这样?”是也不是。

计算机所做的只是根据它所知道的类似问题进行猜测。(猜测的一种花哨说法叫做)。嗯,不是随便猜的。它试图学习根据一些有趣的数学知识做出尽可能好的猜测(我们现在还不需要进入这个领域)。重申一下,机器学习中的学习是关于如何做出最好的猜测。最可能的猜测是最接近正确答案的一个。**

“那它怎么猜对呢?”

最初,计算机做出非常糟糕的猜测(从随机猜测开始)。然后,它将自己的猜测与我们在示例中提供的正确答案进行比较。我们要求计算机减少猜测中的错误。然后,它继续徒劳地减少错误。当它试图减少自己的错误时,它会自我纠正,从而慢慢接近正确的猜测。

计算机正在修正自身错误的过程被专家称为梯度下降。现在不用记名字了。这可能是将来另一个有趣帖子的主题。现在,只要记住计算机通过查看正确答案的例子来慢慢纠正自己。

“如果机器在自我修正,我们人类会怎么做?”

机器学习不是由计算机自己完成的。人类在机器学习中有非常重要的作用。人类扮演着教练或调解人的角色,控制着整个游戏:

  • 人类提供了计算机用来学习的例子。
  • 人类告诉计算机如何发现他们的错误。

基本上,机器所做的唯一事情就是根据例子进行猜测,并尽最大能力纠正猜测。其他一切都由人类提供的信息和代码指导。

包扎

这是对什么是机器学习的一个非常快速的介绍,没有进入油腻的细节。以下是这篇文章主要观点的快速总结:

  • 机器学习允许计算机执行任务,而无需你告诉计算机如何去做。
  • 机器学习就是计算机查看大量示例,并试图找出如何做出最佳猜测。
  • 机器学习如何做出最佳猜测的方法是自我纠正错误的猜测。这是通过查看示例中的正确答案来完成的。
  • 人类通过提供正确的示例集、检测错误的方法等来运行整个游戏。

如果你明白这一点,你就比大多数人更了解机器学习是如何工作的。欢迎在评论区留下您的反馈和疑问。

穿蟒蛇皮的中国邮递员

原文:https://towardsdatascience.com/chinese-postman-in-python-8b1187a3e5a?source=collection_archive---------15-----------------------

详细的实现和解释,特别强调使用递归生成奇数顶点对的独特方法

梅森 B.Unsplash 上拍摄的照片

今天,我将解释并实现流行的“中国邮递员”算法。

为了方便读者,本文分为以下几个部分,建议按顺序浏览所有部分。

动机

中国邮递员问题最早是由中国数学家关美子在 20 世纪 60 年代初研究的。他提出了这样一个问题,如果一个邮递员(在他的情况下是一个中国邮递员,因此得名:D)希望以尽可能短的距离走遍一个城市的所有街道,投递信件并返回他的邮局。

由于我们生活在互联网时代,电子邮件和即时通讯已经取代了传统的信件,我将修改这个问题,以适应这一代人😃

杰克·吉塞尔Unsplash 上的照片

让我们想象一下,你正在一个古老而美丽的城市里度过一个美妙的假期。鉴于目前的情况,我们必须想象这一点,并等到新冠肺炎疫情吹走来尝试这一点。

你想游览这座城市,并成为一名热情的游客,比如说一名摄影师;从您的酒店出发,您希望游览这个城市的每条街道至少一次,然后回到您的酒店。(街头摄影是你的爱好:D)

但是,你要背一个大背包,摄像器材,口粮等。这给你能走多远设置了一个物理限制。而且,你没有世界上所有的时间去蜿蜒曲折,整天不停地游荡,一条一条地寻找所有的街道。(虽然听起来很可爱!)

你想知道完成这次旅行的最小可能距离是多少,以及如何做到这一点?

嗯,读完这篇文章后,你将能够实现一个 python 程序,如果你以图表的形式输入城市地图,它将返回你游览所需的最小距离!

算法、前提条件和假设

就图论而言,问题是简单地找出图中欧拉回路的路径距离。然而,一个图只能有一个欧拉回路(或也称为欧拉圈),如果它的所有顶点的度数都是偶数。

因此,如果我们有一个所有顶点都是偶数的图,那么图中的欧拉回路将恰好穿过每条边一次。

这涵盖了我们算法的一种情况:如果我们的图有所有偶数顶点,我们只需要返回该图中所有边的权重之和。

但是现在这个世界并不完美,不是吗?找到一个所有顶点都是偶数的城市的图是不太可能的。事实上,人们甚至在他们的考试题中找不到这样的图表,更不用说古代城市了(我也是:D 的学生)

那么,如果一个图有一些奇数个顶点,会发生什么呢?这就是中国邮递员算法的优势所在。

  1. 我们找到了图中所有的奇数顶点。

2.确定所有可能的奇数顶点对。

3.对于每一对,我们找到连接奇数顶点和最短可能路径的边。

4.从以上组合中,我们选择总长度最短的一个。

5.我们通过考虑新增加的最短额外边来计算中国邮递员的最小距离。

在我深入每一个步骤之前,我将详细阐述我将详细解释的算法的哪些部分,以及哪些部分是先决条件。

先决条件:

  1. 我们将使用 Dijkstra 算法来计算配对之间的最短可能路径。我将在 python 中实现这一点;然而,我不会解释算法本身的细节。
  2. python 数据结构和语法的基础知识,如列表、集合、循环等。
  3. 熟悉递归的概念。
  4. 熟悉图论的基本概念。
  5. 愿意学习!😄

详细步骤:

  1. 生成奇数顶点配对:这是通过使用递归的算法来完成的,这是我在第一次解决这个问题时想到的。
  2. 从所有组合中选择合适的一个。
  3. 所有的计算导致一个中国邮差旅行的最后最小距离。

假设:

  1. 我在实现这个算法时考虑了一个连通的、无向的、加权的图,其权重为正。
  2. 由于问题陈述通常被解释为寻找路线的最小距离,我认为无向和正加权图的假设是合理的。

所以现在我们配备了一个算法来获得游览古城的最小距离。我将通过 python 代码块演示每一步,完整的代码将附在最后。请注意,我所做的实现可能不是社区中最有效的,但是,它们反映了一个普通学生编写这个算法:D 所需的思想和方法

实施

该算法的实现遵循以下步骤:

一、将输入定义为图形

二。将 Dijkstra 算法实现为一个函数

三世。用函数寻找奇数次顶点

四。用递归生成所有奇数顶点对

五、借助 Dijkstra 函数选择最佳配对

六。实现函数以获得所有边的和

七。将所有代码块组合在一起

八。给定中国邮递员距离作为图形输入的输出

I .将输入定义为图形

我们将一个无向的正加权图作为我们的输入。我们将以列表的形式存储它,如代码块所示。

注意:我们可以在运行时获取用户输入的图形,但是由于逐个输入值会很麻烦,所以我们使用预定义的图形来简化我们的工作😄

如代码块所示,我们将两个图作为输入。

图形输入:列表列表

将 Dijkstra 算法实现为一个函数

该算法的目标是在图中给定的两个节点之间找到最短的可能路线,从而也找到距离。它属于贪婪算法的范畴,试图通过寻找最近的邻居和自我调整来找到最佳路径。Dijkstra 的唯一主要缺点是当权重为负时它会失败,此时我们使用贝尔曼福特或其他算法来寻找最短路径。

代码块显示了对于一组给定的图的源和目的顶点,实现该算法所采用的方法。要了解有关该算法实现的更多详细信息,请参见参考资料。

迪杰斯特拉算法 作为函数

寻找奇数次顶点

对奇数顶点执行这些步骤的决定取决于我们的图中是否存在奇数顶点这一事实。如果不是,我们可以吃颗定心丸&只返回所有边的权重之和😎否则我们需要叫中国邮递员来支援👊

由于我们的输入图是加权的和无向的,找到每个顶点的度数并不困难。我们只需要计算图中每个节点的非零条目的数量。

为此,我们运行一个简单的嵌套 for 循环,并计算每个顶点的度数。一旦我们有了每个顶点的度数,我们使用列表理解来找到奇数个顶点,并将顶点编号存储在另一个名为 odds 的列表中,这是我们将来需要的。

记住,根据握手定理,输入图中奇数顶点的数量总是偶数。

在一个列表中得到图的所有奇数顶点

IV 生成所有奇数顶点对

这一步通常被认为是该算法中最难实现的部分,需要大量的思考和努力。当我第一次自己解决这个问题时,我花了几乎 3-4 个小时来想出一个算法来生成这些配对!然而,结果是非常令人满意和值得的🔥我鼓励你也这样做,并且考虑一下这一步。如果你有逻辑地思考和进行,你也许能解决这个问题。

这个算法是我做的,但它可能不是独一无二或原创的,从某种意义上说,有人可能遵循相同的思维过程,并提出了类似的算法。然而,我非常自豪自己有这样的想法,这也是我写这篇文章的原因之一,为了社区的利益,分享我的方法:)

直觉和逻辑

我们的任务是得到所有可能的配对,包括所有奇数顶点。例如,如果奇数顶点是:A,B,C & D,可能的配对是:-

(A,B)和(C,D)

(A,C)和(B,D)

(A,D)和(B,C)

这看起来很简单,但是随着奇数顶点数量的增加,这种组合的数量会呈指数增长。例如,对于 10 个奇数顶点,有 945 种可能的组合!

因此,要解决这个问题,我们必须理性地对待它。如果我们观察这些对是如何被少量顶点组合的,我们可以推广到任意数量的顶点。

参考下面给出的图表。我已经写下了 6 个奇数顶点的所有唯一对:A,B,C,D,E & F。

图 1 作者的图片:这代表了我们如何将所有唯一的顶点对分组

每列包含从 A、B、C、D、E & F 开始的对。现在,任何对的组合都必须包括所有奇数顶点,从 A 到 f。因此,如果我们考虑第一种可能的组合:

  • 我们可以结合 AB,
  • 那么既然 B 被取->就去 C 列
  • 拿 CD
  • 那么既然 D 取了->去 E 列
  • 拿 EF 来说

所以我们得到了第一个可能的组合:(A,B) & (C,D) & (E,F)

图 2 作者的图片:这是我们如何得到第一个组合的

对于第二种可能的组合:

  • 因为 E 列没有剩余的线对,我们回到 C 列
  • 现在我们拿 CE
  • 现在既然 D 没有被取->去 D
  • 因为 E 已经被取了,取 DF

所以我们得到了第二种可能的组合:(A,B) & (C,E) & (D,F)

图 3 作者图片:这是我们如何得到第二个组合

我们观察到这里出现了一种模式。如果我们能够以某种方式跟踪我们已经使用过的顶点,那么通过递归,我们可以很容易地得到所有可能的配对组合。请参考下图。在这里,我已经形象化了我们如何通过像树一样递归的每个分支得到所有的组合。我们看到,对于 6 个奇数顶点,我们将得到总共 15 个组合。

图 4 作者图片:递归树获取所有组合

递归代码

我们首先需要一个函数,它可以按照图 1 所示的顺序给出所有唯一的对。我们定义了一个函数“gen_pairs”,它使用一个简单的嵌套循环来获取所有唯一的对。因为我们希望这些对按照以每个字母开始的列进行分组,所以我们制作了一个 list-> ' pairs ',其中每一列都是一个列表。如代码块中所示,该函数获取包含所有奇数顶点的赔率列表,并返回对。

生成所有唯一对:如图- 1 所示

现在我们来看看递归函数。为了构造递归函数,我们总是需要考虑两种情况

基本情况,我们返回一些输出,或者停止递归

我们执行一些计算并再次调用函数的一般情况

我们需要两个列表作为递归函数的输入:

  1. ' done ':这将跟踪我们在组合中已经获得的顶点
  2. ' final ':这将存储我们想要生成的所有组合
  3. 注意:这些需要从一个递归调用传递到另一个递归调用,不能被覆盖。为了解决这个问题,我使用 slice 操作符在没有引用的情况下复制了它们。Example - val = done[:]

递归将在我们之前生成的“pairs”列表中完成,每次都将通过切分 list -> pairs[1:]来调用该函数

只有当我们最终得到一个组合时,递归才会停止。但是由于组合的结束对可以来自任何列,我们通过匹配组合列表的长度是否等于“顶点数/ 2”来检查这个条件。出现这种情况的原因是,因为我们将有 2 对,所以对的总数将是“顶点数”/2。因此,我们预定义了一个变量“l”,其值为:(len(pairs) + 1)//2

(注意:我们使用 pairs 列表来检查这个条件,因为逻辑是相同的。请随意使用“赔率”来获得此条件)

如代码块中所示,代码是简短的和甜蜜的:D。这种情况下只需检查字母对中的任何字母是否在我们的完成列表中,如果它们不在,那么我们将该字母对视为组合。

递归函数:生成所有奇数对

我还附上了这段代码的调试版本,这是我最初在制作这个函数时使用的。如果您想了解函数在每次递归调用时是如何工作的,那么建议删除我的一些注释并运行它。

递归代码 调试版本 :带注释我原来用来测试代码的

借助 Dijkstra 的帮助选择最佳配对

首先,如果你已经走到这一步,那么我对你的努力表示赞赏,我也有一些好消息要告诉你。所有繁重的工作都完成了!🎊

我们现在寻求配对,其中配对之间的总距离最小。例如,如果我们有奇数个顶点:A,B,C & D

  • 我们取每一个可能的配对,并计算该配对中每一对之间的总距离,加上该配对的总距离。这听起来很难理解,但是很容易理解和实现
  • 举个例子,我们来看配对:(AB) & (CD):

使用 Dijkstra 的,让我们说 A & B 之间的最小距离是:20

使用 Dijkstra 的,让我们说 C & D 之间的最小距离是:10

那么这个配对的总距离是:20 + 10 = 30

  • 我们对(AC)和(BD)以及(AD)和(BC)重复这个过程
  • 我们从所有 3 个配对中选择距离最小的配对作为我们的最佳配对

下图也说明了这一点。(所有值都是随机考虑的,以演示该过程)

图 5 作者图片:如何使用 Dijkstra 选择最佳配对

这在下面的代码块中实现。我们将所有的距离存储在一个列表中,并获取其中的最小值作为完成中国邮递员距离所需的额外距离

选择与 Dijkstra 的最佳配对

VI 函数获得所有边的和

下面的代码块使用简单的嵌套循环来获得所有边的权重之和。我们将需要这个来获得输入图的权重和,这将加上由最小奇数配对计算的额外距离。

获取所有边总和的函数

VII 组合所有代码块

恭喜你!你坚持到了最后😃剩下的就是在一个函数中调用&使用我们写的所有函数。请记住,我们需要考虑输入图的两种情况:

如果所有顶点都是偶数:我们返回中国邮递员距离作为所有权重的和

如果有奇数个顶点:我们计算奇数对,从最优顶点得到最小距离,并把它加到所有权重的和上

第八卷最后的中国邮递员距离

下面的代码块具有最终编译的函数,当使用图形调用该函数时,将返回遍历图形所有边至少一次所需的最小距离,并返回到起始顶点。

最终编译函数

为什么会这样

现在,你将成功地从上面的代码中找到中国邮递员的距离。然而,有些疑问可能会萦绕在你的脑海中,比如这在❔实际上是如何运作的

下图是一个简单的图,所有的顶点都是偶数。图中的欧拉回路沿着箭头方向,从 A -> B -> C -> D -> A。我们看到,为了能够访问所有边至少一次,并返回到起始顶点,我们需要经过的最小距离与所有边的权重之和相同。

图 6 作者图片:所有顶点都是偶数的图

现在考虑下图所示的图表的附加内容。现在我们有两个奇数顶点。因为这里唯一可用的配对是 AD,所以我们得到它们之间的最小距离作为最小配对距离。

图 7 作者图片:修改后的奇数顶点图

现在,为了形象化我们是如何完成旅程的,让我们沿着所选配对广告之间的最短距离添加一条新边

图 8 作者图片:应用中国邮递员,我们添加一条新的边得到欧拉回路

我们看到这条边会使图中所有的顶点都是偶数。现在,如果我们在这里考虑欧拉回路,我们会看到,我们需要穿越这个新的边缘,回到我们的出发点。因此,中国邮递员的总最小距离是原始图的所有权重之和,加上添加的边的权重。这正是我们的代码所做的,不需要显式地添加边。

所以上面的图传达了中国邮递员算法背后的光辉!

现在你可以访问世界上的任何一个城市,把它的地图做成图表,输入到你的代码中,就可以得到“中国邮差之旅”😄 所需的最短距离

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

最终代码和参考文献

附上实现中国邮递员算法的完整代码。如果你还想要最小距离的路径,那么你可以看看 Fleury 的算法,它可以用来在修改后的图形中显示欧拉回路。

作者写的实现中国邮递员的完整代码

我非常感谢我的大学图论教授 Surabhi Narayan 博士,他教会了我这些概念,激发了我对:D 这个领域的兴趣

我希望您喜欢这篇文章,并且现在已经准备好自己实现这个算法了!

下面是一些参考资料,可以阅读更多关于中国邮递员算法和 Dijkstra 算法的内容。

1.https://www . geeks forgeeks . org/Chinese-postman-route-inspection-set-1-introduction/

2.https://en.wikipedia.org/wiki/Route_inspection_problem

3.【https://www.youtube.com/watch?v=XB4MIexjvY0

4.https://www . geeks forgeeks . org/dijkstras-shortest-path-algorithm-greedy-algo-7/

马特·拉格兰在 Unsplash 上拍摄的照片

Pytorch 挑战中国十二生肖分类

原文:https://towardsdatascience.com/chinese-zodiac-sign-classification-challenge-with-pytorch-d89a8897d00b?source=collection_archive---------13-----------------------

在贝塔斯曼 AI Udacity 奖学金(Bertelsmann AI Udacity Scholarship)中,学者们不仅要完成 AI uda city 课程,而且还要相互挑战,以应用他们在课程期间收集和实践的技能和知识。这些挑战之一是中国十二生肖分类挑战。在,你知道,中国农历新年的时候。

来源

中国的十二生肖被分为十二个年度周期,每一年都由一种特定的动物来标识。

我认为这将是一个有趣的挑战,所以我一头扎了进去。

对于那些想尝试这个挑战的人,你可以在这里得到数据

设置环境

最重要的是。使用 GPU 会使任务更容易,所以我尝试使用 Google Colab 和 Kaggle Notebook 来构建这个模型。但是因为我喜欢能够编辑(添加、更改、移动或删除)我的数据,我更喜欢使用 Google Colab,因为数据存储在我的 Google Drive 中。

来源

加载并检查数据

我们有 12 类图像,我们希望我们的 Pytorch 模型进行分类。将数据分为三组是一个好主意——训练数据,用于训练我们的模型;验证和测试数据,用于确保我们的模型不会过度拟合。

我们先来看看这些数据的分布情况。

十二生肖图像分布

好的,所以对于每个训练,我们有 600 个训练图像(一个是goat的缩写),54 个验证图像(一个是goat的额外图像,这可能是因为一个图像放错了位置),以及 54-55 个测试图像。

我觉得不错。

让我们来看看这些图片的样本。

样本图像

我也觉得不错。我们还可以看到,我们正在纳入绘图图像以及(因为龙并不存在)。

使用 Pytorch 创建模型

Pytorch(以及其他机器学习/深度学习框架)的一个好处是,它为我们提供了简化的样板代码。其中之一是加载列车值测试数据。

现在来建立模型。

我将使用预训练的 Resnet34 模型来转移它的学习,以构建这个分类模型。我还尝试了其他预训练的模型,如 Resnet101 和 VGG 19 与 BatchNorm,但 Resnet34 给我一个相当好的性能,所以我要用它。Resnet34 要求输入图像的宽度和高度为 224。

全模型架构如下。

这里我不会用什么很复杂的东西。只有两个额外的 FC 层,每个层有 512 个神经元,一个输出层有 12 个神经元(当然,每个十二星座类一个)。

训练模型

现在是第一个令人兴奋的部分,训练模型。

我们只需要迭代训练数据加载器,同时(a)对模型进行向前和向后传递,以及(b)测量模型的当前/运行性能。我选择每 100 个小批量做点(b)。

我选择在 7-15 个时期内训练模型。你会在下面的图表中看到原因。

训练和验证损失和精确度(Resnet50 try 1)

在每 100 次迷你批次传递中,该模型在训练数据集上肯定会随着时间而改进。但是当我们查看验证数据集的性能时,它似乎并没有提高太多(虽然随着时间的推移,准确性似乎提高了一点点,但我认为这还不够)。

但是当我们看一看具有不同架构的其他模型时,同样的事情发生了。

训练和验证损失和精确度(Resnet50 try 2)

培训和验证损失和准确性(VGG 协议 19 和批次标准)

第二个模型是 Resnet50,除了我把学习率从 0.001 改为 0.003 之外,与第一个模型基本相同。三是使用 VGG 19,批量常模,学习率 0.001。

三个不同的模型+参数讲述了相同的故事——在多个历元之后,验证的准确性性能并没有像训练一样显著提高(特别是对于最后两个模型)。

我们并不太关心模型的损失,因为这是对模型表现的“自信”程度的衡量,我们更关注准确性。

测试模型

让我们看看模型实际上是好的,还是满足测试数据集。

  • ResNet (lr 0.001) —损失:0.355 acc: 90.5%
  • ResNet (lr 0.003) —损失:0.385 acc: 90.6%
  • VGG 19 批次标准—损失:0.586 acc: 90.8%

从精确度来看,它们基本相同。对于损失,具有 0.001 lr 的 ResNet 至高无上。这些数字与我们的训练和验证几乎相同,所以我们可以说我们的模型没有过度拟合(或者至少我们在它与我们的小纪元发生之前停止了它),并且在分类中国十二生肖方面工作得相当好。

我很好奇,哪张图片的问题最大。

混淆矩阵

喜欢混乱矩阵中的数字。

我们可以看到,模型很少会弄错一个goat,如果弄错了,也总是带着ox(喇叭)。

被模特误认为是公牛的山羊图像

我们还可以看到,这个模型在区分dragon和其他星座时有一点困难。最显著的是oxes (角)和snake(身体)。

最后的话

在贝塔斯曼 AI Udacity 奖学金期间参加中国十二生肖分类挑战赛非常棒,令人耳目一新。它推动并激励我做我热爱的事情——在人工智能/机器学习/深度学习领域进行实验和建设。

更多的挑战会到来,我已经等不及了。

你可以在我的 Github 页面查看我的笔记本。请回顾并关注:)

选择智能数据而非大数据来拯救您的企业

原文:https://towardsdatascience.com/choose-smart-data-over-big-data-to-save-your-business-a334c6302618?source=collection_archive---------62-----------------------

从数据工程师的角度来看

肖恩·斯特拉顿在 Unsplash 上拍摄的照片

为什么您的数据需要智能?

大数据并不神奇。你不能指望把所有的东西都扔进一个罐子里,然后希望出来的东西能让你的业务增长。在处理数据时,口头禅“越多越好”是一个错误的信条。尽管有最先进的算法,你喂它垃圾,它最终给你垃圾。选择不适当的数据策略会让您的公司损失一大笔钱,甚至会让整个运营破产。

Artem Maltsev 在 Unsplash 上拍摄的照片

每隔一段时间,大数据就被当做一个科技流行语。我见过一些公司声称他们正在使用大数据来改变世界,而他们甚至不能改变他们的 MySQL 数据库的 root 权限。我夸大了数据库的部分,但我正试图说明我的观点。

大数据以五个 v 而闻名:量、速、变、准、值。最终的 V 偶尔会被低估和忽略,但事实上它是所有数据系统中最关键的元素。从长远来看,数据的价值不在于它的数量或速度,而在于它决定了其他方面的方法。万一你的数据没有给你的企业带来任何价值,你还会费心去收集它吗?

您为拥有数百 TB 的数据而自豪,但您却让这些数据扎根于数据中心的机架中。您坚持雇佣最熟练的数据团队,但是您让他们做的只是清理和重命名 JSON 文件。那种违反直觉的一点也不环保的方法会阻碍你成为一个数据驱动的企业。

我的数据比你的数据大

心满意足地说“我的数据比你的数据大”可能会让你觉得自己和其他大数据大师是一个档次的,但这里有另一种说法供你磨练: “我的数据比你的数据聪明”。

这是我在互联网上遇到的关于智能数据的两种不同定义

“智能数据是经过格式化的数字信息,在发送到下游分析平台进行进一步的数据整合和分析之前,可以在收集点对其进行处理。”—WhatIs.com

“智能数据”是指实际上有意义的信息。这就是看到一长串每周销售额的数字与识别一段时间内销售额的高峰和低谷之间的区别。— 连线

前者甚至声明智能数据确实来自智能设备,嗯?作为一名数据工程师,这与我对智能数据的看法相去甚远。后者似乎更适合我,但感觉还是不对。我用自己的话给出了一个新的定义

智能数据是数据的一部分,其价值可直接用于满足特定的业务需求或实现预定义的结果。智能数据完全符合技术规范,应该在数据结构中没有任何冗余信息的情况下使用。

简单来说,智能数据并不是大数据的一个独立实体,而是从未经处理的数据中,提取出一条条有价值的信息。智能数据是您在 PowerPoint 演示文稿中放入的内容,是您在决策过程中投射的内容。

尽管听起来令人惊讶,智能数据并没有排在最后,但它应该出现在流程的初始设计中。它决定了你如何收集数据,你构建数据架构的方式,你想雇佣哪些人来完成这项工作。 用结果来决定收益是一种精益的方法,使结果最大化,成本最小化。

两位数据创始人的故事

这个想法

让我们介绍一下约翰和杰克,两位年轻热情的企业家。他们都是从数据世界开始创业的。他们希望利用现成的大数据和机器学习工具来改变电子商务市场的面貌。他们倾向于收集购物平台上用户事件的每个数据点,以构建一个典型的购物者之旅。然而,约翰和杰克采取不同的步骤来理解这个想法。

奥斯汀·迪斯特尔Unsplash 上拍摄的照片

行动

John 将赌注压在了现成的分析工具上。他在网站、移动应用程序上集成了一个代码片段,并立即开始查看数据。由于他无法控制如何将数据作为输入形成管道,他将分析工具提供给他的任何东西输入到数据基础设施中。管道的其余部分由过度优化的学习模型组成,John 希望这些模型能够提供最佳结果。他为在他的数据管道中摄取数百千兆字节而自豪。

这是约翰输入数据的一个例子

来源: 谷歌分析

前数据工程师杰克从另一个角度出发。他渴望完全控制数据结构。当他的同伴已经从他们的训练模型中得到结果时,杰克仍然在努力把他自己的跟踪模块组合在一起。他正在焦急地等待,但这将使他对自己拥有的输入数据有一个适当的认识。Jack 可以有一个紧凑的数据格式来支持他的开箱即用的机器学习模型。

与 John 的数据相比,Jack 的示例数据更加简洁和精确

余波

让我们快速计算一下。在 John 的数据点中,有 3 个空值、1 个重复字段、4 条不必要的信息,总共有 8 列可以删除。假设在 John 的数据存储中,他用 16 个字节存储整数,用 32 个字节存储长整数,用 256 个字节存储字符串,总计:

16 * 3 + 256 * 3 + 32 = **848 bytes** on each data pointFor a data point every second, that number would be**72 MB** a day = **2 GB** permonth = **765 GB/**year.

在 John 的 Hadoop 数据中心内,一年内有 765 GB 的数据处于闲置和非生产状态。这将花费约翰数千美元来维护冗余的 Hadoop 节点。他的现金很快就花光了,他想不出为什么他的机器学习模型不能处理这么大的数据。当 John 在数据库中积累了数百 TB 的数据时,他不知道该如何处理。他无法控制他的数据。

另一方面,Jack 在他的数据管道中保持少量的摄入。他有适量的数据来填充他的训练模型,这可以给他带来积极的结果。Jack 在数据存储方面节省了大量资金,并重新投资于为其应用程序构建更好的算法。当谈到数据结构时,Jack 掌握了主动权,他为自己的小而聪明的数据感到自豪。

克拉克·蒂布斯在 Unsplash 上拍摄的照片

结论

现实生活中没有绝对的约翰和杰克,而是介于两者之间。企业正在通过优化算法和超调模型来努力实现投资回报最大化。他们不断将大数据输入到他们的流程中,相信最终会学到一些有用的东西。

如果没有有价值的信息,大数据只不过是无用的数字片段,仅仅是您业务的负担。冗余、不必要、重复的数据是万恶之源。在一个混乱的数据时代,智能数据将是我们的救星,它不会排在最后,而是排在首位。

我叫 Nam Nguyen,我写关于大数据的文章。享受你的阅读?请在 Medium 和 Twitter 上关注我,了解更多更新。

[## 如何构建可扩展的大数据分析管道

大规模建立端到端系统

towardsdatascience.com](/how-to-build-a-scalable-big-data-analytics-pipeline-7de18f8be848) [## 大数据工程师的一天

为巴黎的一家广告技术巨头工作

towardsdatascience.com](/a-day-in-the-life-of-a-big-data-engineer-a286e4a5ae29)

为您的应用选择最佳的 Python Web 抓取库

原文:https://towardsdatascience.com/choose-the-best-python-web-scraping-library-for-your-application-91a68bc81c4f?source=collection_archive---------1-----------------------

前 5 个库的概述以及何时使用它们。

法扎德·纳兹菲Unsplash 上拍摄的照片

生活在当今世界,我们被周围不同的数据所包围。在我们的项目中收集和使用这些数据的能力是每个数据科学家必备的技能。

关于如何使用特定的 Python 库来获取在线数据,网上有很多教程。然而,您很少能找到为您的特定应用程序选择最佳库的教程。

Python 提供了各种可以用来抓取 web 的库,如 Scrapy、Beautiful Soup、Requests、Urllib 和 Selenium。考虑到 Python 有多受欢迎,我很确定会有更多的库存在,并且很快会有更多的库发布。

在这篇文章中,我将涵盖我刚刚提到的 5 个库,将对它们中的每一个进行概述,例如,代码以及它们中的每一个的最佳应用和案例。

对于本文的其余部分,我将使用包含书籍的这个沙盒网站来解释每个库的具体方面。

1.Scrapy

Scrapy 是目前最流行的 Python web 废弃库之一。它是一个开源框架。这意味着它甚至不是一个图书馆;它是一个相当完整的工具,你可以用它系统地在网络上抓取和爬行。

Scrapy 最初被设计用来构建可以自己爬网的网络蜘蛛。它可以用于监控和挖掘数据,以及自动化和系统化的测试。

与其他抓取网页的 Python 方法相比,它的 CPU 和内存效率也很高。使用 Scrapy 的缺点是,安装它并在你的设备上正常工作可能有点麻烦。

概述和安装

要开始使用 Scrapy,您需要确保您运行的是 Python 3 或更高版本。要安装 Scrapy,你可以简单地在终端中写下下面的命令。

pip install scrapy

Scrapy 成功安装后,您可以通过键入以下命令来运行 Scrapy shell:

scrapy shell

当您运行此命令时,您会看到类似这样的内容:

作者截图

您可以使用 Scrapy shell 运行简单的命令,例如,您可以使用fetch函数获取网站的 HTML 内容。所以,假设我想获取这个图书网站;我可以在 shell 中简单地实现它。

fetch("[http://books.toscrape.com/](http://books.toscrape.com/)")

现在,您可以使用view函数在默认浏览器中打开这个 HTML 文件。或者你可以直接打印出页面的 HTML 源代码。

view(response)
print(response.text)

当然,你不会仅仅为了在浏览器中打开一个网站而吓到它。您可能希望从 HTML 文本中获得一些特定的信息。这是使用 CSS 选择器完成的。

在开始之前,您需要检查要获取的网页的结构,以便使用正确的 CSS 选择器。

何时使用 Scarpy?

使用 Scrapy 的最佳情况是当你想做大规模的网络抓取或者自动化多个测试的时候。Scrapy 的结构非常好,它允许更好的灵活性和对特定应用程序的适应性。此外,Scrapy 项目的组织方式使得维护和扩展更加容易。

我建议你避免使用 Scrapy,如果你有一个小项目,或者你想抓取一个或几个网页。在这种情况下,Scarpy 会使事情变得过于复杂,而不会带来额外的好处。

2.要求

Requests 是你可以使用的最简单的 HTTP 库。 Requests 允许用户向 HTTP 服务器发送请求,并以 HTML 或 JSON 响应的形式获得响应。它还允许用户向服务器发送 POST 请求来修改或添加一些内容。

请求展示了使用设计良好的高级抽象 API 所能获得的真正力量。

概述和安装

请求通常包含在 Python 的内置库中。但是,如果由于某种原因您不能立即导入它,您可以使用 pip 轻松安装它。

pip install requests

您可以使用请求来获取和清理组织良好的 API 响应。例如,假设我想在 OMDB 的数据库中查找一部电影。请求允许我向 API 发送一个电影名称,清理响应,并在不到 10 行的代码中打印出来——如果我们省略注释的话😄。

何时使用请求?

Requests 是您开始网络抓取时的理想选择,并且您有一个 API tp 联系人。它很简单,不需要太多的练习就能掌握使用。请求也不需要你手动添加查询字符串到你的 URL。最后,它有一个写得非常好的文档,并支持整个 restful API 及其所有方法(PUT、GET、DELETE 和 POST)。

如果您尝试或期望的网页包含 JavaScrip 内容,请避免使用请求。则响应可能无法解析正确的信息。

3.Urllib

Urllib 是一个 Python 库,允许开发者打开并解析来自 HTTP 或 FTP 协议的信息。Urllib 提供了一些处理和打开 URL 的功能,即:

  • urllib.request: 打开并读取 URL。
  • urllib.error: 捕获 urllib.request 引发的异常。
  • urllib.parse: 解析 URL。
  • urllib.robotparser: 解析 robots.txt 文件。

概述和安装

好消息是,您不需要安装 Urllib,因为它是内置 Python 库的一部分。然而,在一些罕见的情况下,您可能在 Python 包中找不到 Urllib。如果是这种情况,只需使用 pip 安装即可。

pip install urllib

可以使用 Urllib 来探索和解析网站;然而,它不会给你提供太多的功能。

何时使用 Urllib?

Urllib 比请求稍微复杂一点;然而,如果你想更好地控制你的请求,那么 Urllib 是一个不错的选择。

4.美味的汤

美汤是一个 Python 库,用来从 XML 和 HTML 文件中提取信息。美汤被认为是一个解析器库。解析器帮助程序员从 HTML 文件中获取数据。如果解析器不存在,我们可能会使用正则表达式从文本中匹配和获取模式,这不是一种有效或可维护的方法。

幸运的是,我们不需要这样做,因为我们有解析器!

Beautiful Soup 的优势之一是它能够检测页面编码,从而从 HTML 文本中获得更准确的信息。美丽的汤的另一个优点是它的简单和容易。

概述和安装

安装美丽的汤是非常简单和直接的。您所要做的就是在终端中键入以下内容。

pip install beautifulsoup4

就是这样!你可以开始刮了。

现在,Beautiful Soup 是我们刚刚提到的一个解析器,这意味着我们需要首先获取 HTML,然后使用 Beautiful Soup 从其中提取我们需要的信息。我们可以使用 UrllibRequests 从网页中获取 HTML 文本,然后使用 Beautiful Soup 来清理它。

回到之前的网页,我们可以使用请求获取网页的 HTML 源代码,然后使用 Beautiful Soup 获取页面中< a >内的所有链接。我们只需要几行代码就可以做到。

什么时候用美人汤?

如果你刚开始学习 webs scarping 或 Python,Beautiful Soup 是最好的选择。此外,如果您将要抓取的文档不是结构化的,那么 Beautiful Soup 将是您的最佳选择。

如果你正在建立一个大项目,美丽的汤将不会是明智的选择。漂亮的汤项目不灵活,随着项目规模的增大,很难维护。

5.硒

Selenium 是一个开源的基于网络的工具。Selenium 是一个网络驱动程序,这意味着你可以用它打开网页,点击一个按钮,然后得到结果。它是一个主要用 Java 编写的自动化测试的强大工具。

尽管 Selenium 很强大,但它是一个初学者友好的工具,不需要很高的学习曲线。它还允许代码模仿人类行为,这在自动化测试中是必须的。

概述和安装

要安装 Selenium,只需在终端中使用 pip 命令。

pip install selenium

如果您想获得 Selenium 的全部功能——您很可能会这样做——您需要安装一个 Selenium WebDriver,以真实用户的身份在本地或远程设备上驱动浏览器。

您可以使用 Selenium 自动登录 Twitter——或者脸书或任何网站,真的。

什么时候用硒?

如果您是 web 抓取游戏的新手,但是您需要一个可扩展且灵活的强大工具,Selenium 是最佳选择。此外,如果您想浏览几页,这是一个很好的选择,但是您需要的信息在 JavaScript 中。

为您的项目使用正确的库可以节省您大量的时间和精力,这对项目的成功至关重要。

作为一名数据科学家,您可能会遇到所有这些库,在您的旅程中可能会遇到更多,在我看来,这是了解每个库的优缺点的唯一方法。这样做,你将会发展出一种第六感来引导你在未来的项目中选择和使用最好的库。

选择数据库技术

原文:https://towardsdatascience.com/choosing-a-database-technology-d7f5a61d1e98?source=collection_archive---------18-----------------------

路线图和流程概述

奥利弗·鲁斯在 Unsplash 上拍摄的照片

选择数据库是数据架构师最近享受的一种奢侈。在过去,最常见的是,这是一个先前做出的决定,是一个需要接受的决定。责任、存储过程代码和太脆弱的数据管道带来了巨大的负担,每个人都不敢重新设计它们,因为害怕会损坏。数据库通常在应用程序之间共享,或者在许多情况下,功能是单个应用程序的模块。

现在,在多应用程序和多数据库的世界中,在一些作者称之为多语言持久性的世界中,情况有所不同。

大多数云提供商都有自己的技术,他们试图根据用例将用户引导到正确的数据库。

下面是我关于如何在数据库世界中做出技术选择的路线图。在某些情况下,您还可以扩展该方法来涵盖一般的技术选择。

这样的选择究竟是如何做出的?

根据我的经验,现实生活中做出这种决定的大致比例如下:

如何选择一个数据库?

  • 技术原因:30%
  • 用例适合度:30%
  • 成本/总拥有成本/更换成本或实施成本:10%
  • 利益相关者驱动(或者叫做“谁和谁打高尔夫?”): 30%.决策是由利益相关者的网络效应、与供应商的关系驱动的因素、销售人员、上级组织联系、共同投资者、交换交易和其他商业活动决定的。

选择和入围的过程

选择过程,从一个长名单开始,缩小到一个短名单

从候选人名单开始——一个“长名单”

  • 作为一名顾问,您将从自己的经验、团队成员的经验、客户 IT 团队推荐的名字以及对 Gartner、Forrester、Bloor Research 和其他公司报告的研究中收集一份清单。
  • 分析产品文献、特性和局限性
  • 看看“民间讨论”发生的来源——论坛、stackoverflow、slashdot、reddit(!),github 问题,bug 报告
  • 寻找独立的测试和排名( Jepsendb-engines 和类似的来源)

定义一个合格标准。不符合资格标准将会取消选择。

作为数据库选择基础的能力和特征

技术能力、特性和非功能性需求

  • NFRs 或“完整性”要求,如可扩展性、容量、可恢复性、耐用性。
  • 上面给出了一些选择参数,以及与该参数相关的一些候选参数
  • 数据大小— MBs、GBs、TBs、PBs — SQLite、MySQL、PostgreSQL、Oracle、Teradata、AWS 红移
  • 大量并发用户—使用缓存、Redis、DynamoDB
  • 快速响应时间要求— ElasticSearch,MemSQL
  • 计算量大(矩阵计算、Python/R 集成)— SQL Server 与 R、存储过程
  • 文档数据(JSON)、地理数据(GIS)、时间数据、多媒体数据—适合数据存储格式的数据库— MongoDB、PostGIS、TICK stack
  • 点查询或批量数据查询— Redis、键值存储、雪花、Google Cloud SQL
  • 平衡的读写,主要是读,主要是写,事务和分析处理— OLTP(在线事务处理),OLAP(在线分析处理),HTAP(混合事务和分析处理)
  • 大量数据的快速接收、涓滴流、计划作业、数据湖(Cassandra、Kafka、Spark、Presto)
  • 微服务 v/s 整体架构、ACID 要求、最终一致性要求

用例及适用性

  • 现有的编程语言投资(Java,。NET)、市场上托管服务的可用性或技能可用性,以了解和管理技术的复杂性、云可用性、法律或地理或合同限制
  • 在数据存储和处理以及数据库(如 Oracle 数据库云服务器或 Teradata)方面的现有投资
  • 由云提供商提供的数据库,确保与云生态系统的良好集成,统一或相似的 API,以及相同的 DevOps 工具。
  • 成本/总体拥有成本或实施/迁移成本

候选名单

从候选名单中剔除不符合资格标准的候选人后剩下的名单。

产生了最终的竞争者

接下来,一个非常详细的需求列表(包括技术、成本、用例以及适用性)和评分标准被制定出来。通常这是在以下格式的电子表格中完成的。

评分和加权要求

它总是有助于记录为什么分配一个特定的分数,或者为什么分配或调整一个权重。我可以向您保证,这样一个带注释的文档将在组织中被多次引用,因为注释和指定的分数一样有价值。

与客户的最终讨论总是在电子表格的基础上进行,客户及其技术、业务和 IT 团队可以对权重进行权衡和调整。

在这个过程的最后,通常会有 1-2 名候选人脱颖而出。

根据我的经验,在入围过程中,或者在前 2-3 名的选择之后,需要一个结构化的 PoC,以确保文档中的声明是真实的,并且可以解决提到的限制。

混合数据库架构的案例

每个数据库都有一些核心特性,以及一些为了“打勾”而添加的特性。这里的危险是,随着时间的推移,这些“其他”功能会被放弃,因为它们没有得到应有的关注。

数据库也不能孤立地考虑,而是要放在为请求服务的能力、应用程序架构和整个数据流的业务用例的整体环境中考虑。

出于上述原因,为了获得最佳性能,有时使用专门的数据处理组件比使用一个数据库来处理所有请求更有意义。

在这里,您可以看到 SAS Grid 等技术、SciDB 等专用数据处理平台或 Intersystems Cache shine。

在某些方面,Hadoop 堆栈(文件存储、Hive 元数据存储、HBase、Impala)或各种 Spark 组件(GraphX、Spark SQL、Spark streaming、Mlib)也是一种混合 DB 架构。

共享数据库的使用和集成需求

通用数据库仍然满足大多数需求。然而,正在发生变化的是数据库使用的共享模式。

以前,销售和营销、交易、财务和会计以及服务应用程序都将数据存储在同一个数据存储中(可能是相同的模式,也可能是不同的模式)。考虑到数据量小、许可成本高、DBA 预算有限,这是有意义的。它确实提供了单一存储位置、更少的模式差异和更低的复杂性的优势。

现在,每个应用程序都有单独的数据存储和数据库。数据鸿沟增加了。随着这种分离,集成需求增加了。公共数据和主数据的维护也有所增加。分析层现在使用来自所有这些不同数据源的数据。API 提供了应用程序之间的集成。企业应用程序集成(EAI)和提取-转换-加载或提取-加载-转换(ETL/ELT)的双重性,以及两者的重叠角色增加了,两者混合使用,导致了更大的复杂性,有时会导致更多的成本和开销。

结论

作为数据架构师,做出正确的技术选择非常重要。平衡适用性需求、降低运营和集成的复杂性和成本的需求,以及防止堆栈失控和激增的需求。使用正确的数据库和数据存储的案例应该只针对正确的应用程序和用例。

参考

m .福勒(2011 年 11 月 16 日)。bliki:多语种持久性。从https://martinfowler.com/bliki/PolyglotPersistence.html取回

在您喜欢的工具和实际完成工作的工具之间进行选择。

原文:https://towardsdatascience.com/choosing-between-the-tools-you-love-and-the-tools-that-actually-get-the-work-done-ff0da99bc00b?source=collection_archive---------44-----------------------

作为一名数据科学家、人工智能或机器学习工程师,你应该知道何时在使用你情有独钟的工具和实际上更容易更快完成工作的工具之间划清界限。

布雷特·乔丹在 Unsplash 上的照片

最终这是你做出的选择,做出这个选择有多难并不重要。重要的是你做了。
――卡桑德拉·克莱尔

作为不断编写代码的人,我们对某些工具和技术情有独钟,我们倾向于一直使用它们,即使它们在某些情况下不是最好或最可取的工具。然后,我们有责任知道何时在使用正确和适当的工具、技术或方法与使用我们喜欢的工具之间划清界限。

什么时候知道用什么

对于你作为数据科学家、人工智能或 ML 工程师承担的任何项目,一定要知道问题需要你构建什么样的解决方案。如果您对问题陈述理解得足够好,您会发现构建和实现您的解决方案相对更容易。在构建你的数据科学、AI 或 ML 解决方案时,一定要一步一步来。如果您的目标是构建能够经受时间考验的解决方案,那么使用系统的或逐步的方法来构建解决方案是非常必要的。确保遵循数据科学或 ML 项目的道德和普遍接受的工作流程。在工作流程的每个阶段,对解决手头问题的可能方法进行研究或案例分析,并查找可供您使用的工具和技术。完成这些事情后,权衡使用每种可用工具或技术的利弊,并根据自己的判断,选择有助于您更轻松、更快速地实现目标的工具或技术。如果有许多可用的选项可供选择,那么可以归结为选择一个拥有良好社区和围绕它构建的内容的人来帮助和指导您使用该工具或技术,以便您可以有效地利用该工具或技术。

选择是丰富的,难得的是正确的决定!
――穆罕默德·穆拉特·伊尔丹

为什么你不应该保留收藏夹

作为一名数据科学家、人工智能或人工智能工程师,你必须保持开放的心态,以便能够高效地工作。在工具和技术方面保持偏好只会限制你,让你意识不到可供选择的大量选项会帮助你更容易、更快、更有效地完成工作。如果你一直想在这个领域保持相关性,教会自己学习、忘却和再学习可能是你能教会自己的最重要的事情。你必须抛弃过去对你有用的工具、技术或方法,选择更新更有效的。在数据科学家、人工智能或人工智能工程师的生活中,时间是一个非常重要的因素,因此,在从事任何项目时,你应该始终坚持使用节省时间的工具、技术或方法。

乔恩·泰森在 Unsplash 上的照片

在正确的时间做出正确的决定,会让你的生活像鲜花一样绽放;否则,它将被视为荆棘。第一个你会享受,另一个你要承受。
――埃桑·塞加尔

我希望我已经能够告诉你为什么选择那些对你来说确实有效的选项来使你的工作更容易和更快是明智的,而不是选择那些你在多年的工作中已经形成的软肋。你有什么想法?在这个故事的回应部分分享你的观点和看法。

感谢您抽出时间阅读这个故事。我希望你学到了新的东西,这对你有所帮助。可以直接在 Twitter 或者 LinkedIn 联系我。最美好的祝愿!

非常感谢 安娜·阿依库 为我校对并纠正了我写这篇文章时犯的许多错误。

用动态规划快速选择

原文:https://towardsdatascience.com/choosing-fast-with-dynamic-programming-b6916da543f4?source=collection_archive---------25-----------------------

用真实世界的例子和 Python 代码简单解释背包问题。

马丁·范·登·霍维尔在 Unsplash 上的照片

终于到了,你要搬到三藩市成为一名著名的数据科学家了!你将在一家大公司工作,很快就会出名!但是,首先。你将住在一个小公寓里,比你现在在山谷里的房子要小得多。所以你必须决定带走哪些东西。因为你是一个数据科学家,你会以一种聪明而有效的方式来决定这件事。让我们找到最优解!

问题描述

目前你的房子是 100 平方米。你的东西所占的面积是 50 平方米。你的新公寓有 40 平方米,你希望你的东西最多占 20 平方米,因为你喜欢在地板上有一些自由空间。你以一种方式列出你的物品,你给它们分配它们占据的区域和它们给你的生活增加的价值。你的目标是最大化这 20 平方米的价值。

项目

你开始列出你的物品。你可以指定面积(以平方分米为单位)以及物品给你的生活带来的价值(从 0 到 100)。您最终得到了下面这本包含 29 个条目的字典:

好吧!例如,床占 4 平方米(= 400 平方分米),它给你的生活增加的价值是 100,游戏桌占 1.5 平方米,增加的价值是 30。

价值最大化

你如何最大限度地利用这本词典?您可以尝试所有可能的组合,并计算每个组合的总值。通过为 20 平方米的最大面积选择最大值,您将获得最佳解决方案。一个问题,这 29 个项目给了 2 个⁹选择项目的可能组合!超过 5.36 亿了!那需要一些时间!

你想想其他的选择。如果你从给你的生活增加最大价值的物品开始,然后是第二高价值的物品,以此类推,直到 20 平方米都满了,会怎么样?这又简单又快捷!但是它会给出最优解吗?你怀疑。如何快速解决问题,获得最佳解?

注:上面提到的算法分别叫做 蛮力 贪婪

动态规划

幸运的是,一个朋友告诉你一个更聪明的处理问题的方法。他解释说,你可以用递归的方式把问题分成更小更简单的子问题。如果您将结果存储在记忆表中,您可以快速找到最佳解决方案,因为您可以重复使用这些结果。这样你就用记忆空间换取了时间。所以你从这个方法开始,叫做动态编程。事实上,一个小时后你就解决了这个问题,并且知道了你要把哪些东西带到新家去。

动态编程步骤

你需要完成四个步骤来获得你的 SF 公寓的最佳库存清单:

第一步。用条目及其包含的区域/值创建一个字典。
这是前面提到的带有条目的 stuffdict(见第一个代码块)。

第二步。从字典中创建面积和值列表。
你使用 stuffdict 创建两个带有面积和值的列表。

第三步。使用这些列表建立记忆表。
有了面积列表、数值列表、最大面积和项目数,就可以建立记忆表。

第四步。获取包含在记忆表最后一行中的项目。 记忆表的最后一行包含最优解。有可能存在多个最优解。例如,当您有两个具有相同面积和价值的项目时,或者当一些项目加起来与另一个项目的面积和价值相同时。

让我们更深入地研究这些步骤,并检查代码。

第一步。用条目及其包含的区域/值创建一个字典。 这是包含项目、区域和值的字典:

第二步。从字典中创建面积和值列表。
使用 stuffdict 创建两个包含面积和值的列表。为此,您可以使用下面的函数。输入是步骤 1 中的 stuffdict,它返回两个列表:一个包含区域,另一个包含值。

第三步。使用这些列表建立记忆表。 现在你将创建记忆表来寻找最优解。您需要步骤二中的面积和值列表,总面积 A 和项目总数 n 。表格有 n+1 行和 A+1 列。从第一行开始,零个条目,然后计算每个单元格的值。您将以自下而上的方式逐行执行此操作。数值表 V 看起来是这样的:

用代码创建表:

在第二和第三行,表被创建。创建完成后,您将填充表格的每个单元格。第六和第七行显示了基本情况:当面积或项目数为零时,值为零。第八行和第九行的意思是,当当前项的面积小于或等于单元格的面积时,根据以下公式计算单元格的值:

选择当前项目的值加上前一行的值和当前区域减去当前项目的区域之间的最大值(1),以及前一行的值加上当前单元格的区域(2)。第 10 行和第 11 行的意思是:如果单元格的面积小于当前项目的面积,则您将单元格的值设置为等于具有相同面积的前一行的值。

第四步。获取包含在记忆表最后一行中的项目。

你可以使用以下代码找到你的完美家具组合:

此代码返回:

['bike_stand', 'garbage_can', 'standing_lamp', 'chest_of_drawers', 'plant_3', 'plant_2', 'diner_table_with_chairs', 'bookshelf', 'armchair', 'table', 'desk', 'bed', 'couch_s']

现在你知道你需要带什么了吧!我们搬到旧金山去吧!

注意:注意,这段代码也返回重复项(面积和值对相同的项)!在这个例子中,情况并非如此。

结论

希望这篇文章能帮助你快速有效地找到最佳解决方案。您可以将面积值对替换为想要优化的其他参数,如权重和值或时间和改进。重要的一点是,通过存储更小的子问题的解,你可以更快地找到最优解,这种技术被称为动态规划。

额外收获:记忆表的热图

下面的热图很好地展示了记忆表。在 x 轴上,您可以看到可用的面积(2000 平方分米)。y 轴显示项目列表。您从一个空列表开始,然后开始添加项目。这些颜色代表某个区域内可用项目的总价值。你可以看到当你继续前进时,这个值会变得越来越高。

使用记忆表和 stuffdict 构建该热图的代码:

别忘了 订阅 如果你想在我发表新文章时收到电子邮件。

选择绩效指标

原文:https://towardsdatascience.com/choosing-performance-metrics-61b40819eae1?source=collection_archive---------11-----------------------

准确性、敏感性与特异性、精确性与回忆性以及 F1 分数

分类 _ 报告来自 scikit-learn。

准确度、召回率、精确度、F1 分数--如何选择衡量模型性能的指标?一旦你选择了,你想要宏观平均值吗?加权平均?对于这些指标中的每一个,我将更仔细地研究它是什么以及它的最佳用例是什么。我还将介绍如何从 scikit-learn 的[classification_report](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.classification_report.html)中读取输出表,如上图所示。

准确(性)

我从准确性开始,因为我认为,从它的名字来看,我们觉得我们对它有一个直观的理解,而没有见过任何数学公式。“我们想要一个更准确的模型。”一直都是,我们甚至还没有严格意义上的定义。我确实从项目的准确性开始(现在仍然如此),因为它感觉熟悉而不专业。

从理论上讲,准确性就是预测正确的百分比,用 0 (0%的预测正确)到 1 (100%的预测正确)之间的小数表示。

作者图片

因为预测 TP(真阳性)、FP(假阳性)、TN(真阴性)和 FN(假阴性)对后面的指标很重要,所以让我们继续讨论它们与准确性的关系。

对于二元分类问题。作者图片

举一个例子,如果我们试图将图像分为两类,狗和非狗,我们的模型将只预测 1)图像是狗,在这种情况下它可能是正确的,并且图像确实是狗(TP),或者不正确的,并且图像不是狗,尽管模型认为它是(FP);或者 2)模型可以预测图像不是狗,在这种情况下,它可以再次是正确的,并且图像确实不是狗(TN),或者是不正确的,并且图像实际上是狗,尽管模型认为它不是(FN)。

从上面看,我们可以看出,无论我们使用哪种准确性定义,我们只是将模型正确的预测数除以其预测总数。

对于你遇到的大多数普通的、不复杂的数据集来说,准确性确实是一种“金发姑娘”。只要类别或多或少是平衡的(在前面的例子中,狗和非狗图像的数量相等),准确性在融合特异性和敏感性、召回率和精确度方面做得很好。特异性灵敏度在这个例子中本身就是相当具体的词语,回忆精度也是如此,接下来我们要谈到它们。

敏感性(回忆)和特异性

就像准确性一样,我认为我们已经对特异性和敏感性有了相当直观的理解,或者至少感觉我们有,但现实是它们在统计学领域有一些相当具体的定义。

TPR 代表真阳性率,FNR 代表假阴性率。作者图片

敏感度,剧透一下,和回忆是同一个东西,也被称为真阳性率(TPR) ,用通俗英语来说,就是所有被放入正确箱子的真阳性的分数;在前面的例子中,在实际上是的狗的图像中,模型得到了其中的多少部分,并且称之为狗?这个模型在捕捉“是”方面有多好?敏感度/回忆/TPR 就是这么回答的。

你会注意到一些有趣的事情:我们没有包括任何关于非狗的图片。事实上,如果你认真思考上面等式,你会意识到那些非狗或没有图像,以及模型预测或分类它们的成功或失败(TN 和 FP),根本不会影响灵敏度/回忆。事实上,再举一个早先的例子,一个对每一张图像都预测“是的,狗”的模型将具有完美的灵敏度/回忆/TPR。

这给了 sensitivity/recall/TPR 一个非常具体的用例,它可以归结为:当你所寻找的每一个实例都太珍贵而不能错过时,就使用它。例子包括检测恐怖袭击、检测疾病、检测欺诈等。在每一种情况下,一个以敏感度为中心的模型将捕捉所有真正的恐怖袭击,所有真正的心脏病病例,以及所有真正的欺诈性信用卡购买,同时警告它也将提取一些假阳性的实例:将有一些无辜的旅行者,一些健康的人,一些正常的目标购买被检测到。

特异性,也称为真阴性率(TNR),是敏感性的另一面。它关心敏感做的每一件事,但不关心“不”的情况(真的不是狗)。

TNR 为真阴性率,FPR 为假阳性率。作者图片

一个对每一张图像都称之为“不是狗”的模型将具有完美的特异性(因此,灵敏度为 0)。这与敏感性/回忆相反,通常两者之间的选择归结为你关注的是或否。在理想的世界中,你会得到一个在两方面都出色的模型,但有时我们被迫做出选择,特别是在医疗保健领域,特异性和敏感性之间的区别源于

召回率和精确度

回想一下我们已经讨论过——它是敏感性——和精确性,第三方面——万圣节快乐,各位——是这样的:在所有被模型认为是(狗)的东西中,有多少是正确的(真的是狗)?

作者图片

像灵敏度和特异性一样,在计算精度时,有一个模型性能的元素被忽略,但这一次是模型判断为“否”的所有东西被忽略。如果有 1000 张照片,500 张狗的照片,500 张非狗的照片,而模型只正确地分类了 5 只狗,并将其他所有照片都称为非狗,那将是完美的,精度为 1.0(即使分类器错过了 495 张狗的照片)。

那么,Precision 也有一个非常具体的用例。当你想对模型给你的“是”有信心时,就把注意力集中在它上面。当然,它会错过一些是,但它会做什么,如果模型有很好的精度,你可以放心。

F1 分数

简答, F1 评分是召回率和准确率的调和平均值,取 0 到 1 之间的值。

作者图片

当您用它们的 TP/FP/TN/FN 定义替换 recall 和 precision 时,F1 分数的定义如下:

作者图片

也许,你和我一样,从来没有听说过谐音的意思是这里有一个很好的视频用一个例子来解释它,但快速和肮脏的是,它最常见的用例是平均利率,我们熟悉的算术平均值并不足够。

如果你回到 F1 得分的第一个等式,你可以通过查看第二个定义,即分子中的召回率乘以精度,来判断如果召回率或精度为 0,那么 F1 得分也为 0。这使得它成为召回率和精确度之间的一个很好的折衷,这样你就不会遇到像我刚才给出的例子那样的极端情况。在最近的例子中,只有 5 张正确分类的狗的图片,精度是 1.0,但是回忆是 5/500 = 0.01,所以 F1 分数类似地被抑制在(大约)0.02。准确地说,是 0.51。

在这种情况下,精确度和 F1(分别为 0.51 和 0.02)都反映了较差的整体性能,但这是因为这是一个平衡的数据集。 在一个不平衡的数据集中,F1 分数而不是准确率会在查全率和查准率之间取得一个很差的平衡 。那是 F1 score 的用例。

一个例子:5 张狗的图片,995 张其他东西的图片(不平衡)。我们让一个分类器运行,它正确地将其中一张狗的图片分类,但称其他图片都不是狗。这意味着有 4 张错误分类的狗的图片。召回率是 0.2(相当差),精确度是 1.0(完美),但是精确度是 0.999,并没有反映出这个模型在捕捉这些狗的图片上做得有多差;F1 分数等于 0.33,反映了查全率和查准率之间的不均衡。

阅读分类报告

我的标记版本分类 _ 报告来自 scikit-learn。

第一次看到 scikit-learn 时,它对我来说非常难以理解,以至于我推迟了为项目选择指标,因为我无法找出它们在报告中的位置。我希望有人给了我上面的小抄。

我认为让它如此难以阅读的部分原因是它打印出了accuracy,然后是macro avgweighted avg,我的大脑认为是accuracy;但那是错的,他们属于precisionrecallf1-score。恰好有一个数字属于accuracy,我在上面用红色画了一个虚线框。

精确度、召回率和 F1 分数,每个都在上面自己的绿框中,都按类别细分,然后给出每个的宏观平均值和加权平均值。宏观平均数是我们习惯看到的通常平均数。把它们加起来,然后除以它们的数量。加权平均值考虑了计算中每个类别的数量,因此一个类别的数量越少,意味着它的精确度/召回率/F1 分数对每个类别的加权平均值的影响就越小。橙色框中的support表示每个职业有多少个:1 个class 0,1 个class 1,3 个class 2.

例如,阅读上面的图表可能是这样的:对于class 0class 1class 2,精度分别是 0.5、0 和 1。这意味着在模型归类为 0 类的事物中,只有 50%是真实的;在模型归类为 1 类的事物中,0%是真实的;在模型归类为第二类的事物中,100%都是真实的。宏观平均精度为 0.5,加权平均精度为 0.7。此模型的加权平均值较高,因为精度下降的地方是类 1,但它在此数据集中的代表性不足(仅 1/5),因此在加权平均值中所占比例较小。

何时使用什么(概述)

  • 使用精确度获得带有平衡数据集的模型性能的一般报告。
  • 当你寻找的每一个实例都太珍贵而不能错过时,使用特异性/回忆性/敏感性。示例包括医疗保健、欺诈检测和安全事务中的测试。你会得到一些假警报,但这是让真正的疾病/欺诈/危险逃脱的较小的罪恶。
  • 当你想确信你的模型是真的时,使用 precision 。您正在寻找的一些东西会跑掉,但您可以确信,当您的模型 pings 某个东西时,它确实是它所说的那样。想想申请人筛选。一些可行的申请人将会逃脱,但是当模型 pings 一个可行的申请人时,你可以对此有信心。
  • 使用 F1 分数作为召回率和精确度的平均值,尤其是在使用不平衡数据集时。如果召回率或精确度是 0,F1 分数将反映 an 也是 0。举例来说,我最近试图按情绪对推文进行分类,积极的、消极的或中性的,但数据集不平衡,中性的评论比积极或消极的评论多得多。只有 macro F1 score 很好地描述了整体模型性能(同等关注所有三个类)。

进一步阅读

选择正确的误差度量:MAPE 与斯马普

原文:https://towardsdatascience.com/choosing-the-correct-error-metric-mape-vs-smape-5328dec53fac?source=collection_archive---------2-----------------------

图片来自 Pixabay像素

两种流行的误差度量标准的利弊

MSE、RMSE、MAE、MAPE、sMAPE……仅举几例。有大量不同的错误度量标准,每一个都有其优点和缺点,并且应该比前一个覆盖更多的情况。那么,如何决定在我们的项目中使用哪种度量呢?

我认为回答这个问题的关键是了解最流行的度量标准的优点和局限性。这样,我们可以选择最适合手头任务的指标。这就是为什么在这篇文章中,我介绍了我最近使用的两个指标。

平均绝对百分比误差(MAPE)

平均绝对百分比误差是评估预测性能的最流行的度量之一。它由下面的公式给出。

其中 A_t 代表实际值,而 F_t 是预测值。在这种情况下,我们可以将 t 解释为进行一般回归问题(预测人的体重或房屋价格)时的观察值,或者时间序列分析时的时间指数。

该公式通常包括将该值乘以 100%,以百分比形式表示该数字。

优势

  • 以百分比表示,与尺度无关,可用于比较不同尺度的预测。但是我们应该记住,MAPE 的值可能超过 100%。
  • 易于向利益相关者解释。

缺点

  • 当实际值为零时,MAPE 会采用未定义的值,例如在需求预测中就可能出现这种情况。此外,当实际值非常接近零时,它采用极值。
  • MAPE 是不对称的,它对负误差(当预测高于实际时)的惩罚比对正误差的惩罚更重。这是因为预测值过低时,百分比误差不能超过 100%。而过高的预测没有上限。因此,MAPE 将倾向于低估而非高估的模型。
  • MAPE 假设变量的测量单位具有有意义的零值。因此,虽然预测需求和使用 MAPE 是有意义的,但当预测以摄氏度表示的温度(不仅仅是摄氏度)时就没有意义了,因为温度有一个任意的零点。
  • MAPE 不是处处可微的,这在将其用作优化准则时会导致问题。

有关在商业环境中使用 MAPE 的更多信息,请参见本文

对称平均绝对百分比误差

在讨论了 MAPE 之后,我们也来看看它的一个替代方案——对称 MAPE。它应该克服上面提到的不对称——预测高于实际的无限性。

sMAPE 有几个不同的版本。另一种流行且普遍接受的方法是在分母中的两个项上加上绝对值,以说明当实际值和预测值都等于 0 时 sMAPE 是不确定的。

优势

  • 用百分比表示。
  • 修复了原始 MAPE 的缺点-它同时具有下限(0%)和上限(200%)。

缺点

  • 当真实值和预测值都非常接近零时,不稳定。当这种情况发生时,我们会用一个非常接近于零的数来处理除法。
  • sMAPE 可以取负值,因此对“绝对百分比误差”的解释可能会产生误导。
  • 0%到 200%的范围解释起来并不直观,因此 sMAPE 公式中分母除以 2 的部分经常被忽略。
  • 每当实际值或预测值为 0 时,sMAPE 将自动达到上限值。
  • 与 MAPE 关于有意义的零值的假设相同。
  • 在修正无边界的不对称时,sMAPE 引入了另一种由公式的分母引起的微妙不对称。想象两种情况。在第一个例子中,A = 100,F = 120。sMAPE 为 18.2%。现在有一个非常类似的例子,A = 100,F = 80。这里我们得出了 22.2%的 sMAPE。

结论

在本文中,我描述了回归问题的两种流行的性能评估方法。虽然它修复了 MAPE 的一些缺点,但仍有一些问题和一些新的问题。您可以研究的一些其他指标有:

  • 平均绝对标度误差
  • 平均方向精度(MDA)
  • 准确率的对数(预测值与实际值之比)

一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。

如果您对本文感兴趣,您可能也会喜欢:

[## 我最喜欢的 10 个在线学习数据科学的资源

这些网站将帮助您跟上数据科学的最新趋势

towardsdatascience.com](/my-10-favorite-resources-for-learning-data-science-online-c645aa3d0afb) [## 有助于时间序列分析的 5 种绘图类型

以及如何使用 Python 快速创建它们!

towardsdatascience.com](/5-types-of-plots-that-will-help-you-with-time-series-analysis-b63747818705) [## Python 统计块中的新成员:pingouin

图书馆的快速参观,以及它是如何从老守卫中脱颖而出的

towardsdatascience.com](/the-new-kid-on-the-statistics-in-python-block-pingouin-6b353a1db57c)

选择正确的数据库

原文:https://towardsdatascience.com/choosing-the-right-database-in-a-system-design-interview-b8af9c6dc525?source=collection_archive---------5-----------------------

如何根据您的需求选择合适的存储解决方案

存储解决方案和数据库—如何选择最佳方案?Jan Antonin Kolar 在 Unsplash 上拍摄的照片

想象一下——你正在参加一个系统设计面试,需要选择一个数据库来存储,比如说,一个电子商务系统中与订单相关的数据。您的数据是结构化的,需要保持一致,但是您的查询模式与标准的关系数据库不匹配。你需要你的事务被隔离,原子的和所有的东西都是酸的…但是 OMG 它需要像 Cassandra 一样无限扩展!!那么,您如何决定选择哪种存储解决方案呢?好吧,让我们看看!

首先,我们在处理什么样的数据?是记录、文件系统还是音频/视频内容?我们打算对这些数据做什么样的处理?我们需要搜索什么或者运行复杂的分析算法吗?

有哪些不同类型的存储解决方案?

根据我们的要求以及我们使用或访问数据的方式,我们可能会寻找以下存储解决方案:

缓存解决方案 —如果我们正在设计一个像 Twitter 或脸书这样的读负载系统,我们可能会捕获大量数据,甚至是完整的时间线,以满足低延迟要求。这里的一些选项可能是 RedisMemcached

文件系统存储 —如果我们正在设计某种资产交付服务,其中我们可能需要存储图像或音频/视频文件,我们可能需要使用称为 blob 存储的东西。一个非常受欢迎的例子是亚马逊 S3。

文本搜索引擎 —如果我们正在设计一个像亚马逊一样的系统,并且需要实现一个搜索功能,该怎么办?关于搜索功能,我们也需要考虑错别字。假设用户想要搜索“衬衫”,但是却键入了“衬衫”。现在,如果我们不显示任何结果,这将是非常糟糕的用户体验。我们的系统需要足够智能,以显示“衬衫”或“短裤”的结果。这就是所谓的模糊搜索,这就是我们使用文本搜索引擎的地方,比如 Elasticsearch

数据仓库——我知道!我们一直在讨论数据和存储,怎么能不考虑大数据呢!有时,我们只需要将所有数据转储到一个存储中,然后我们可以在那里执行各种分析。这些系统更多地用于通常交易的离线报告。这就是我们最终使用像 Hadoop 这样的数据仓库解决方案的地方。

现在,您可能已经注意到,我们一直在谈论“存储解决方案”,而不是“数据库”。所以现在让我们来看看数据库

SQL?NoSQL?这是怎么回事?

作者图片

嗯,我们可以根据几个因素来决定使用哪种数据库,这些因素是——数据的结构、查询模式和规模。

我知道有点困惑!这就是为什么我会附上我在这篇文章中提到的视频。他们解释得很好,但我们也将在接下来的章节中讨论它,所以请继续阅读。

在系统设计面试中选择最佳数据库——CodeKarle

现在,规模结构,以及查询模式。没错。如果信息是结构化的,可以用表来表示,如果我们需要我们的事务是原子的、一致的、隔离的和持久的(ACID),我们就用关系数据库。最常用的是 MySQL。

现在,如果不需要 ACID 属性,那么您仍然可以使用关系数据库,或者您可以使用 NoSQL 替代方案。但是如果你的数据缺乏结构,它就不能用表格来表示,现在我们需要使用 NoSQL 数据库,比如 MongoDB、Cassandra、HBase、Couchbase、T19 等等。这就是查询模式成为决定性因素的地方。

psst:elastic search 是文档数据库的一个特例。

如果我们的数据中有各种各样的属性和各种各样的查询,我们使用一个文档数据库,比如 MongoDBCouchbase 。但是,如果我们必须在非常大的规模上工作,但是我们需要运行的查询类型很少,那么我们会选择像 CassandraHBase 这样的列式 DB 。甚至在列数据库之间,你可能知道,HBase 是建立在 Hadoop 之上的。因此,在设置 HBase 时,我们首先需要设置 Hadoop 和相关组件,然后在其上设置 HBase。这增加了设置系统的复杂性,所以我个人会选择 Cassandra,即使只是为了简单。性能方面两者给出相似的结果。

现在,像 Cassandra 这样的列数据库的问题是,它们主要通过划分和复制数据来工作。因此,如果您可以选择分区键,使所有查询都在 where 子句中使用公共分区键,那么 Cassandra 是一个不错的选择。

我看到了“codekarle”写的这篇关于如何选择最佳存储解决方案的文章,这篇文章很好地解释了什么时候使用列式数据库与文档数据库可能是有意义的,并举例说明了优步如何与系统的司机端和骑手端进行交互。让我用同样的场景来解释一下。

假设优步已经将与乘车相关的信息保存在一个 Cassandra 中,并将司机 id 作为分区键。现在,当我们运行一个查询来获取某一天特定驱动程序的所有数据时,它会根据分区键驱动程序 id 来获取数据。这是卡珊德拉解决方案的隔断部分。现在,如果我们试图通过客户 id 查询客户在某一天的乘车情况会怎样。现在,查询将被发送到所有分区,效率也随之降低!这就是解决方案的复制方面的用武之地。我们可以简单地复制整个数据,现在使用客户 id 作为分区键。现在,当基于客户 id 的查询到来时,它将被定向到使用客户 id 作为分区键的实例。这就是卡珊德拉可以无限扩展的原因。还记得 Cassandra 的查询模式吗?我们提到过,只有在查询种类有限的情况下,它才是有用的。这是因为我们只能复制数据这么多次。

让我们现实一点,一个数据库够吗?

现在,我们已经看到了各种存储解决方案,以及如何根据我们的需求和需要存储的信息类型在各种数据库之间进行选择。但这就够了吗?参考上述文章中的另一个例子,在某些情况下,单个 DB 不足以满足我们的需求。例如,在 Amazon 的例子中,订单数据需要遵循 ACID 属性,但是它需要像列数据库一样具有无限的可伸缩性。在这种情况下,我们将使用 MySQL + Cassandra 这样的数据库组合。现在,所有关于正在进行的订单的信息,需要遵循 ACID 属性,将存储在 MySQL 数据库中,一旦完成,我们可以将它们移动到 Cassandra,这可以用作永久存储。因此,只要我们需要 ACID 属性,数据就会保留在关系数据库中,然后转移到一个列数据库中,该列数据库可以根据数据的大小进行伸缩。问题解决了!

我希望这能帮助你在下一次系统设计面试中提出一个参考清单。认为我错过了一个重要的数据库/存储解决方案?请在评论中告诉我!

另外,这里有一个 youtube 链接指向我提到的解决方案。

为 AWS 上的深度学习选择合适的 GPU

原文:https://towardsdatascience.com/choosing-the-right-gpu-for-deep-learning-on-aws-d69c157d8c86?source=collection_archive---------2-----------------------

如何选择正确的亚马逊 EC2 GPU 实例进行深度学习训练和推理——从最佳性能到最具成本效益,以及介于两者之间的一切

最新更新:【2022 年 2 月 17 日。
-添加了
新的** G5 和 G5g 实例类型
-添加了新的部分:“对忙碌的数据科学家的重要建议”
-更新了所有现有的部分和图形以代表当前的产品组合
-添加了一个电子表格,其中包含 AWS 上所有 GPU 及其特性的详细列表**

作者插图

就在十年前,如果你想使用 GPU 来加速数据处理或科学模拟代码,你要么找一个电脑游戏玩家,要么联系你友好的邻居超级计算中心。今天,你可以登录你的 AWS 控制台,从一系列基于 GPU 的 Amazon EC2 实例中进行选择。

你问 AWS 上可以访问哪些 GPU?您可以启动具有不同 GPU 内存大小(8 GB、16 GB、24 GB、32 GB、40 GB)、NVIDIA GPU 代(Ampere、Turing、Volta、Maxwell、Kepler)不同功能(FP64、FP32、FP16、INT8、Sparsity、TensorCores、NVLink)、每个实例不同数量的 GPU(1、2、4、8、16)以及与不同 CPU(Intel、AMD、Graviton2)配对的 GPU 实例。您还可以选择具有不同 vCPUs(核心线程数)、系统内存和网络带宽的实例,并添加一系列存储选项(对象存储、网络文件系统、块存储等)。)—总而言之,你有选择。

我这篇博客的目标是为您提供指导,告诉您如何在 AWS 上为您的深度学习项目选择正确的 GPU 实例。我将讨论各种 EC2 GPU 实例的主要特性和优势,以及最适合每种实例类型和规模的工作负载。如果你是 AWS 新手,或者 GPU 新手,或者深度学习新手,我希望你能找到为项目做出正确选择所需的信息。

这篇博文涉及的主题:

  1. 给忙碌的数据科学家/ML 从业者的主要建议
  2. 为什么您应该选择正确的 GPU 实例 而不仅仅是正确的 GPU
  3. 深入探讨 GPU 实例类型:P4、P3、G5 (G5g)、G4、P2 和 G3
  4. AWS 上的其他机器学习加速器和实例
  5. 为 ML 使用 GPU 实例时的成本优化技巧
  6. 在 AWS 上使用什么软件和框架?
  7. HPC 使用案例应考虑哪些 GPU?
  8. 所有 AWS GPU 实例及其特性的完整且详细的电子表格

关键建议针对忙碌的数据科学家/ML 从业者

赶时间?只想要没有深潜的最终推荐?我掩护你。这里有 5 个 GPU 实例建议,应该适用于大多数深度学习用例。但是,我建议您回来阅读本文的其余部分,这样您可以做出更明智的决定。

1。AWS 上性能最高的多 GPU 实例

实例: p4d.24xlarge 何时使用:需要你能得到的所有性能的时候。将其用于大型模型和数据集的分布式培训。
你得到的: 8 个NVIDIA A100GPU,每个 GPU 40gb GPU 内存。基于最新的 NVIDIA Ampere 架构。包括用于快速多 GPU 培训的第三代 NVLink。

2.AWS 上性能最高的单 GPU 实例:

实例: 你得到的: 1 x NVIDIA V100 GPU 配 16gb GPU 内存。基于较老的 NVIDIA Volta 架构。性能最好的单 GPU 仍然是 P4 实例上的 NVIDIA A100,但你只能在 P4 获得 8 个 NVIDIA A100 GPUs。在接下来讨论的 G5 实例上,这种 GPU 比 NVIDIA A10G 有轻微的性能优势,但 G5 更具成本效益,并具有更多的 GPU 内存。

3.最佳性价比,AWS 上的单 GPU 实例

实例: g5.xlarge何时使用:当你想要高性能、比 P3 更低成本的更多 GPU 内存实例 你得到的: 1 x NVIDIA A10G GPU 拥有 24 GB 的 GPU 内存,基于最新的 Ampere 架构。NVIDIA A10G 可以被视为p4d.24xlarge上 A100 的低功耗近亲,因此当您需要更多计算时,可以轻松迁移和扩展。如果您有更多的预处理或后处理步骤,请考虑使用g5.(2/4/8/16)xlarge为具有更多 vCPUs 和更高系统内存的相同单 GPU 提供更大的尺寸。

4.最佳性价比,AWS 上的多 GPU 实例:

实例: p3.(8/16)xlarge
何时使用:性价比高的多 GPU 模型开发与训练。 你得到的: p3.8xlarge有 4 个英伟达 V100GPU,p3.16xlarge有 8 个英伟达 V100 GPUs,每个 GPU 上有 16 GB 的 GPU 内存,基于较旧的英伟达 Volta 架构。对于更大的模型、数据集和更快的性能,请考虑 P4 实例。

5.AWS 上的高性能 GPU 实例,价格适中

实例: g4dn.xlarge
何时使用:在模型开发和训练的成本上,性能低于其他选项。成本有效的模型推理部署。 你得到的: 1 x 英伟达 T4 GPU 配 16gb GPU 内存。基于上一代英伟达图灵架构。如果您有更多的预处理或后处理,请考虑使用g4dn.(2/4/8/16)xlarge来获得更多的 vCPUs 和更高的系统内存。

有了这些,你应该有足够的信息来开始你的项目。如果你仍然渴望了解更多,让我们深入研究每个实例类型、GPU 类型及其在 AWS 上的特性,并讨论何时以及为什么应该考虑它们。

为什么您应该选择正确的“GPU 实例”而不仅仅是正确的“GPU”

或者为什么您应该着眼于整个系统,而不仅仅是 GPU 的类型

GPU 是深度学习系统的主力,但最好的深度学习系统不仅仅是 GPU。您必须选择合适的计算能力(CPU、GPU)、存储、网络带宽和优化软件,以最大限度地利用所有可用资源。

一些深度学习模型需要更高的系统内存或更强大的 CPU 来进行数据预处理,其他模型可能在更少的 CPU 内核和更低的系统内存下运行良好。这就是为什么你会看到许多亚马逊 EC2 GPU 实例选项,有些具有相同的 GPU 类型,但不同的 CPU,存储和网络选项。如果你是 AWS 新手,或者是 AWS 深度学习新手,做出这个选择可能会感到不知所措。

让我们从 AWS 上的高级 EC2 GPU 实例命名开始。GPU 实例有两个系列——P 系列和 G 系列 EC2 实例,下图显示了各种实例代和实例大小。

用于深度学习的亚马逊 EC2 GPU 实例

历史上, P 实例类型代表更适合高性能计算(HPC)工作负载的 GPU,其特点是更高的性能(更高的瓦数、更多的 cuda 内核)和对科学计算中使用的双精度(FP64)的支持。 G 实例类型的 GPU 更适合图形和渲染,其特点是缺乏双精度和更低的性价比(更低的瓦数,更少的 cuda 内核)。

随着近年来 GPU 上的机器学习工作量快速增长,这一切都开始发生变化。今天,新一代的 PG 实例类型都适合机器学习。对于 HPC 工作负载和要求苛刻的机器学习培训工作负载,仍然推荐使用 P实例类型,对于机器学习推理部署和计算密集型程度较低的培训,我推荐使用 G 实例类型。在下一节讨论特定的 GPU 实例类型时,所有这些将变得更加清晰。

每个实例大小都有一定的 vCPU 计数、GPU 内存、系统内存、每个实例的 GPU 数和网络带宽。字母(P 3 ,G 5) 旁边的数字代表实例代。数字越大,实例类型越新。每个实例代可以有不同架构的 GPU,下面的时间线图像显示了 NVIDIA GPU 架构代、GPU 类型和相应的 EC2 实例代。

现在,让我们按照下面列出的顺序,按系列、代和规模来看一下这些实例。

我们将按照这里显示的顺序讨论每个 GPU 实例类型

亚马逊 EC2 P4:AWS 上性能最高的深度学习训练 GPU 实例类型。

P4 实例提供对基于 NVIDIA Ampere 架构的NVIDIA A100 GPU的访问。它只有一种尺寸——每个实例有多个 GPU,每个 GPU 有 8 个 A100 GPUs,每个 GPU 有 40 GB 的 GPU 内存,96 个 vCPU,以及 400 Gbps 的网络带宽,用于记录设置训练性能

P4 实例特征一目了然:

  • GPU 一代:英伟达安培
  • 支持的精度类型 : FP64、FP32、FP16、INT8、BF16、TF32、第三代张量核(混合精度)
  • GPU 内存:每颗 GPU 40 GB
  • GPU 互连 : NVLink 高带宽互连,第三代

基于 NVIDIA Ampere 的 NVIDIA A100 GPU 在 P4 实例上有什么新功能?

每一代新的 GPU 都比上一代更快,这里也不例外。NVIDIA A100 明显快于 NVIDIA V100(在稍后讨论的 P3 实例中发现),但也包括适合深度学习的更新精度类型,特别是 BF16 和 TF32。

深度学习训练通常在单精度或 FP32 中完成。FP32 IEEE 标准格式的选择早于深度学习,因此硬件和芯片制造商已经开始支持更好地用于深度学习的更新精度类型。这是一个很好的例子,说明硬件的发展是为了满足应用程序的需求,而开发人员必须改变应用程序才能在现有的硬件上工作。

NVIDIA A100 包括用于深度学习的特殊核心,称为张量核心,以运行混合精度训练,这是首次在 Volta 架构中引入的。而不是在单精度(FP32)下训练模型,你的深度学习框架可以使用张量核在半精度(FP16)下进行矩阵乘法,在单精度(FP32)下进行累加。这通常需要更新您的训练脚本,但可以带来更高的训练性能。每个框架对此的处理方式不同,所以请参考您的框架的官方指南( TensorFlowPyTorchMXNet )来了解混合精度的使用。

NVIDIA A100 GPU 支持两种新的精密格式——BF16 和 TensorFloat-32 (TF32)。TF32 的优势在于 NVIDIA A100 上的 TF32 张量核心可以从深度学习框架中读取 FP32 数据,并使用和产生标准的 FP32 输出,但在内部它使用了降低的内部精度。这意味着与混合精度训练不同,混合精度训练通常需要对训练脚本进行代码修改,像 TensorFlow 和 PyTorch 这样的框架可以支持 TF32 开箱即用。BF16 是 IEEE FP16 标准的替代产品,具有更高的动态范围,更适合处理梯度而不损失精度。TensorFlow 已经支持 BF16 有一段时间了,你现在可以在使用p4d.24xlarge实例时利用 NVIDIA A100 GPU 上的 BF16 precision。

P4 实例只有一种大小:p4d.24xlarge。让我们仔细看看。

p4d.24xlarge:云中最快的 GPU 实例

如果你需要云中绝对最快的训练 GPU 实例,那么只需看看p4d.24xlarge.就行了,这个头衔以前由p3dn.24xlarge拥有,它拥有 8 个基于 Volta 架构的 NVIDIA V100 GPU。

您可以访问 8 个配有 40 GB GPU 内存的 NVIDIA A100 GPUs,通过第三代 NVLink 互连,理论上,与我们将在下一节讨论的 P3 实例类型上可用的 NVIDIA V100 上的第二代 NVLink 相比,第三代 NVLink 的 GPU 间带宽增加了一倍。这使得p4d.24xlarge实例类型非常适合分布式数据并行训练,以及不适合单个 GPU 的大型模型的模型并行训练。该实例还允许您访问 96 个 vCPUs、1152 GB 系统内存(EC2 GPU 实例中最高的)和 400 Gbps 网络带宽(EC2 GPU 实例中最高的),这对于实现大规模分布式培训作业的近线性扩展非常重要。

在这个实例上运行nvidia-smi,可以看到 GPU 内存是 40 GB。这是目前 AWS 上每 GPU 最大的 GPU 内存。如果您的模型很大,或者您正在处理 3D 图像或其他大批量数据,那么这就是要考虑的实例。运行nvidia-smi topo -matrix,你会看到 NVLink 被用于 GPU 之间的通信。与 PCIe 相比,NVlink 提供了更高的 GPU 间带宽,这意味着多 GPU 和分布式培训作业将运行得更快。

Amazon EC2 G5:推理部署的最佳性价比单 GPU 实例和多 GPU 实例选项

G5 实例很有趣,因为在这种实例类型下有两种类型的 NVIDIA GPUs。这与 EC2 实例类型和 GPU 架构类型之间具有 1:1 关系的所有其他实例类型不同。

G5 实例类型有两个不同的子类别,具有不同的 CPU 和 GPU 类型

它们都有不同的实例大小,包括单个和多个 GPU 实例。

首先让我们看看 G5 实例类型,特别是g5.xlarge实例大小,我在开始时的关键要点/建议列表中讨论过。

G5 实例:AWS 上单 GPU 实例的最佳性价比

G5 实例功能一览:

  • GPU 一代 : NVIDIA Ampere
  • 支持的精度类型 : 支持的精度类型 : FP64、FP32、FP16、INT8、BF16、TF32、张量核第三代(混合精度)
  • GPU 内存 : 24 GB
  • GPU 互连 : PCIe

G5 给你带来了什么?

GPU 实例:g5.(2/4/8/16)xlarge为 AWS 上的单 GPU 实例提供了最佳的性价比。从g5.xlarge开始,作为您的单个 GPU 模型开发、原型制作和培训实例。您可以将大小增加到g5.(2/4/8/16).xlarge,以获得更多 vcpu 和系统内存,从而更好地处理依赖 CPU 能力的数据预处理和后处理。您可以访问单个和多个 GPU 实例大小(4 个 GPU、8 个 GPU)。NVIDIA A10G 的单 GPU 选项g5.(2/4/8/16)xlarge为训练和推理部署提供了最佳的性能/成本配置。

如果你看一下g5.xlarge实例的nvidia-smi的输出,你会看到热设计功率(TDP),这是 GPU 可以汲取的最大功率,是 300W。将此与上面 P4 部分显示的nvidia-smi的输出进行比较,后者显示的 TDP 为 400W。这使得在 G5 实例中的 NVIDIA A10G 是在 P4 实例类型上发现的 NVIDIA A100 的较低功率表亲。因为它也基于相同的 NVIDIA Ampere 架构,这意味着它包括 P4 实例类型支持的所有功能。

如果您的模型和数据规模增长,您需要进行分布式培训,或者如果您希望在更快的 GPU 上运行多个并行培训实验,这使得 G5 实例非常适合单 GPU 培训并将您的培训工作负载迁移到 P4。

g5.xlarge上 nvidia-smi 的输出

虽然您可以访问多 GPU 实例大小,但我不建议将它们用于多 GPU 分布式培训,因为没有 NVIDIA 高带宽 NVLink GPU 互连,通信将回退到速度明显较慢的 PCIe。G5 上的多 GPU 选项意味着在每个 GPU 上托管多个模型,用于推理部署用例。

G5g 实例:良好的性能和成本效益的 GPU 实例,如果你对 ARM CPU 没问题的话

G5g 实例功能一览:

  • GPU 一代:英伟达图灵
  • 支持的精度类型 : 支持的精度类型 : FP32,FP16,张量核(混合精度),INT8
  • GPU 内存 : 16GB
  • GPU 互连 : PCIe

你用 G5g 得到了什么?

与 G5 实例不同,G5g 实例提供了基于旧的 NVIDIA 图灵架构的 NVIDIA T4G GPUs。NVIDIA T4G GPU 最接近的表亲是亚马逊 EC2 G4 实例上可用的 NVIDIA T4 GPU,我将在下一节讨论。有趣的是,G5g 实例和 G4 实例的关键区别在于 CPU 的选择。

G5g 实例提供基于 ARM 的 AWS Graviton2 CPU,而
G4 实例提供基于 x86 的英特尔至强可扩展 CPU。
GPU(T4 和 T4g)在性能方面非常相似

我们在这两者之间的选择应该归结为您更喜欢的 CPU 架构。我个人倾向于今天的机器学习是 G4 实例而不是 G5g 实例,因为更多的开源框架被设计为在英特尔 CPU 上运行,而不是基于 ARM 的 CPU。

亚马逊 EC2 P3:AWS 上最高性能的单 GPU 实例和经济高效的多 GPU 实例选项

P3 实例提供对基于 NVIDIA Volta 架构的NVIDIA V100 GPU的访问,您可以为每个实例启动单个 GPU 或多个 GPU(4 个 GPU、8 个 GPU)。单个 GPU 实例p3.2xlarge就可以成为你深度学习训练的日常驱动。最强大的实例p3dn.24xlarge可让您访问 8 个 V100,配有 32 GB GPU 内存、96 个虚拟 CPU 和 100 Gbps 网络吞吐量,非常适合分布式培训。

P3 实例特征一目了然:

  • GPU 一代:英伟达 Volta
  • 支持的精度类型 : FP64、FP32、FP16、张量核(混合精度)
  • GPU 内存 : 16 GB 在p3.2xlarge, p3.8xlarge, p3.16xlarge,32 GB 在p3dn.24xlarge
  • GPU 互连 : NVLink 高带宽互连,第二代

NVIDIA V100 还包括张量核心来运行混合精度训练,但不提供 P4 实例上提供的 NVIDIA A100 中引入的 TF32 和 BF16 精度类型。然而,P3 实例有 4 种不同的大小,从单个 GPU 实例大小到 8 个 GPU 实例大小,使其成为灵活培训工作负载的理想选择。让我们来看看下面的每个实例大小p3.2xlargep3.8xlargep3.16xlargep3dn.24xlarge.

p3.2xlarge:单 GPU 训练的最佳 GPU 实例

如果你需要一个 GPU 并且性能是优先考虑的,这应该是你大多数深度学习培训工作的首选实例。G5 实例比 P3 的性能稍低,但更具成本效益。使用p3.2xlarge,您可以访问一个 NVIDIA V100 GPU,它具有 16 GB GPU 内存、8 个 vCPUs、61 GB 系统内存和高达 10 Gbps 的网络带宽。在撰写本文时,V100 是云中最快的 GPU,并且支持张量核,如果您的脚本可以利用混合精度训练,则可以进一步提高性能。

如果您启动一个 Amazon EC2 p3.2xlarge 实例并运行nvidia-smi命令,您可以看到实例上的 GPU 是支持 NVLink 的 V100-SXM2 版本(我们将在下一节讨论这一点)。在内存使用下,你会看到它有 16 GB 的 GPU 内存。如果您需要 16 GB 以上的 GPU 内存来处理大型模型或大数据量,那么您应该考虑p3dn.24xlarge(下面有更多详细信息)。

p3.8xlarge 和 p3.16xlarge:小规模多 GPU 训练和运行并行实验的理想 GPU 实例

如果你需要更多的 GPU 用于实验,更多的 vCPUs 用于数据预处理和数据扩充,或者更高的网络带宽,可以考虑p3.8xlarge (带 4 个 GPU)和p3.16xlarge (带 8 个 GPU)。每个 GPU 都是 16 GB 内存的 NVIDIA V100。它们还包括用于高带宽 GPU 间通信的 NVLink 互连,这将为多 GPU 培训提供便利。使用p3.8xlarge 您可以访问 32 个虚拟 CPU 和 244 GB 系统内存,使用p3.16xlarge 您可以访问 64 个虚拟 CPU 和 488 GB 系统内存。这个实例非常适合两个用例:

多 GPU 培训工作:如果你刚刚开始多 GPU 培训,4 个 GPU 在p3.8xlarge 上或者 8 个 GPU 在p3.16xlarge 上可以给你一个不错的加速。您还可以使用该实例为更大规模的多节点培训作业准备您的培训脚本,这通常需要您使用 Horovod 、 tf.distribute.Strategytorch.distributed库来修改您的培训脚本。参考我的使用 Horovod 进行分布式培训的分步指南:

博文:在 Amazon SageMaker 上使用 TensorFlow 和 Horovod 进行分布式培训的快速指南

并行实验:当您必须并行运行模型架构和超参数的变体以加快实验速度时,多 GPU 实例也会派上用场。使用p3.16xlarge ,您可以在多达 8 种型号上进行训练。与多 GPU 训练作业不同,由于每个 GPU 都独立运行训练,并且不会阻止其他 GPU 的使用,因此您可以在模型探索阶段提高工作效率。

p3dn.24xlarge: 高性能且经济高效的培训

这个实例之前拥有云头衔中最快的 GPU 实例,现在属于p4d.24xlarge。这并不使p3dn.24xlarge显得没精打采。它仍然是今天你能在云上找到的最快的实例类型之一,并且比 P4 实例更具成本效益。你可以访问 8 个 NVIDIA V100 GPUs,但与拥有 16 GB GPU 内存的p3.16xlarge不同,p3dn.24xlarge 上的 GPU 拥有 32 GB GPU 内存。这意味着你可以适应更大的模型和更大批量的训练。该实例允许您访问 96 个 vCPUs、768 GB 系统内存和 100 Gbps 网络带宽,这对于实现大规模分布式培训作业的近线性扩展非常重要。

在这个实例上运行 nvidia-smi,可以看到 GPU 内存是 32 GB。唯一一个拥有比这更多 GPU 内存的实例是p4d.24xlarge,它是一个拥有 40gb GPU 内存的 A100 GPU。如果您的模型很大,或者您正在处理 3D 图像或其他大批量数据,那么这就是要考虑的实例。运行nvidia-smi topo — matrix,你会看到 NVLink 被用于 GPU 之间的通信。与 PCIe 相比,NVlink 提供了更高的 GPU 间带宽,这意味着多 GPU 和分布式培训作业将运行得更快。

Amazon EC2 G4:用于训练的高性能单 GPU 实例和用于经济高效推理的多 GPU 选项

G4 实例提供对基于英伟达图灵架构的英伟达 T4 GPU 的访问。您可以为每个实例启动一个 GPU,也可以为每个实例启动多个 GPU(4 个 GPU,8 个 GPU)。在下面的时间线图中,你会看到 G4 instance 的正下方是 G5g instance,这两个实例都是基于采用 NVIDIA 图灵架构的 GPU。我们已经在前面的部分讨论了 G5g 实例类型,G4(英伟达 T4)和 G5g(英伟达 T4G)中的 GPU 在性能上非常相似。在这些情况下,您的选择将归结为 CPU 类型的选择。

G5g 实例提供基于 ARM 的 AWS Graviton2 CPU,而
G4 实例提供基于 x86 的英特尔至强可扩展 CPU。
GPU(T4 和 T4g)在性能方面非常相似

在 GPU 时间轴图中,您可以看到 NVIDIA Turing 架构是在 NVIDIA Volta 架构之后推出的,并为机器学习引入了几个新功能,如下一代张量核心和整数精度支持,这使它们成为经济高效的推理部署和图形的理想选择。

G4 实例特征一览:

  • GPU 一代:英伟达图灵
  • 支持的精度类型 : FP64、FP32、FP16、张量核(混合精度)、INT8、INT4、INT1
  • GPU 内存 : 16 GB
  • GPU 互连 : PCIe

G4 实例上的英伟达 T4 GPU 有什么新功能?

NVIDIA Turing 率先引入了对整数精度(INT8)数据类型的支持,这可以显著提高推理吞吐量。在训练期间,模型权重和梯度通常以单精度(FP32)存储。事实证明,要在训练好的模型上运行预测,实际上并不需要全精度,并且可以在半精度(FP16)或 8 位整数精度(INT8)中进行精度降低的计算。这样做可以提高吞吐量,而不会牺牲太多的准确性。准确性会有一些下降,下降的程度取决于具体到你的模型和训练的各种因素。总的来说,与其他 GPU 实例相比,G4 实例可以获得最佳的推理性能/成本。英伟达的支持矩阵显示了哪些神经网络层和 GPU 类型支持 INT8 等精度进行推理。

英伟达 T4(和英伟达 T4G)是 AWS 上任何 EC2 实例中功耗最低的 GPU。在这个实例上运行nvidia-smi,你可以看到g4dn.xlarge有一个 16gb GPU 内存的英伟达 T4 GPU。你还会注意到,与 NVIDIA A10G 的 300 瓦相比,功率上限为 70 瓦。

以下实例大小都可以让您访问单个 NVIDIA T4 GPU,并增加 vCPU、系统内存、存储和网络带宽的数量:g4dn.xlarge (4 个 vCPU,16 GB 系统内存)、g4dn.2xlarge (8 个 vCPU,32 GB 系统内存)、g4dn.4xlarge (16 个 vCPU,64 GB 系统内存)、g4dn.8xlarge (32 个 vCPU,128 GB 系统内存)、g4dn.16xlarge (64 个 vCPU,256 GB 系统内存)。您可以在产品详情部分的产品 G4 实例页面上找到差异的完整列表。

G4 实例大小还包括两种多 GPU 配置:g4dn.12xlarge4 个 GPU 和 g4dn.metal 个 GPU。但是,如果您的用例是多 GPU 或多节点/分布式训练,您应该考虑使用 P3 实例。在一个多 GPU g4dn.12xlarge实例上运行nvidia-smi topo --matrix,您将看到 GPU 并没有通过高带宽 NVLink GPU 互连进行连接。P3 多 GPU 实例包括高带宽 NVLink 互连,可以加速多 GPU 训练。

Amazon EC2 P2:对于 HPC 工作负载具有成本效益,不再推荐用于纯 ML 工作负载

P2 实例让你接触到基于英伟达开普勒架构的英伟达 K80 GPUs。开普勒架构已经有几代历史了(开普勒- >麦克斯韦- >帕斯卡- >、伏打- >图灵),因此它们不是最快的 GPU。它们确实有一些特定的功能,如全精度(FP64)支持,这使它们对于依赖额外精度的高性能计算(HPC)工作负载来说具有吸引力和成本效益。P2 实例有 3 种不同的大小:p2.xlarge (1 个 GPU)、p2.8xlarge (8 个 GPU)、p2.16xlarge (16 个 GPU)。

NVIDIA K80 是一个有趣的 GPU。单个 NVIDIA K80 其实就是一块物理板上的两个 GPU,NVIDIA 称之为双 GPU 设计。这意味着,当您启动一个p2.xlarge实例时,您只能在物理 K80 板上获得这两个 GPU 中的一个。同样,当你启动一个p2.8xlarge时,你可以在 4 个 K80 GPU 上访问 8 个 GPU,而使用p2.16xlarge时,你可以在 8 个 K80 GPU 上访问 16 个 GPU。在p2.xlarge上运行nvidia-smi,你看到的是 NVIDIA K80 板上的两个 GPU 中的一个,它有 12 GB 的 GPU 内存

P2 实例特征一目了然:

  • GPU 一代 : NVIDIA Kelper
  • 支持的精度类型 : FP64、FP32
  • GPU 内存: 12 GB
  • GPU 互连 : PCIe

那么,我甚至应该使用 P2 实例进行深度学习吗?

不,上面讨论过有更好的选择。在亚马逊 EC2 G4 和 G5 实例推出之前,P2 实例是推荐的具有成本效益的深度学习训练实例类型。自从 G4 实例推出以来,我推荐 G4 作为深度学习培训的首选性价比培训和原型 GPU 实例。P2 对于科学计算中的 HPC 工作负载来说仍然是经济高效的,但你会错过几个新功能,例如支持混合精度训练(张量核)和降低精度推断,这已经成为新一代的标准。

如果您在p2.16xlarge GPU 实例上运行 nvidia-smi ,由于 NVIDIA K80 具有双 GPU 设计,您将看到 16 个 GPU,它们是 8 个 NVIDIA K80 GPUs 的一部分。这是您在 AWS 上的单个实例中可以获得的最大数量的 GPU。如果你运行nvidia-smi topo --matrix,你会看到所有的 GPU 间通信都是通过 PCIe,不像 P3 多 GPU 实例使用更快的 NVLink。

Amazon EC2 G3:不再推荐仅用于 ML 工作负载

G3 实例让您访问基于 NVIDIA Maxwell 架构的 NVIDIA M60 GPUs。NVIDIA 将 M60 GPUs 称为虚拟工作站,并将其定位于专业图形。然而,对于 P3、G4、G5、G5g 实例的深度学习,G3 具有更强大和更具成本效益的选项,因此不是深度学习的推荐选项。我把它包括在这里只是为了一些历史和完整性。

G3 实例特征一览:

  • GPU 一代:英伟达 Maxwell
  • 支持的精度类型 : FP32
  • GPU 内存 : 8 GB
  • GPU 互连 : PCIe

应该考虑深度学习的 G3 实例吗?

在 Amazon EC2 G4 实例发布之前,单个 GPU G3 实例在开发、测试和原型制作方面非常经济。尽管 Maxwell 架构比在 P2 实例上发现的 NVIDIA K80 的开普勒架构更新,但对于深度学习,您仍然应该考虑 G3 之前的 P2 实例。你的选择顺序应该是 P3 > G4 > P2 > G3。

G3 实例有 4 种大小,g3s.xlargeg3.4xlarge (2 个 GPU,不同系统配置)g3.8xlarge (2 个 GPU)和g3.16xlarge (4 个 GPU)。在一个g3s.xlarge上运行nvidia-smi,你会看到这个实例让你访问一个 8 GB GPU 内存的 NVIDIA M60 GPU。

AWS 上的其他机器学习实例选项

NVIDIA GPUs 无疑是深度学习的主要产品,但 AWS 上还有其他实例选项和加速器,可能是您训练和推理工作负载的更好选择。

  • CPU :用于训练传统的 ML 模型,原型和推理部署
  • 基于英特尔 Habana-Gaudi 的 DL1 实例:借助 8 x Gaudi 加速器,您可以将其用作 P3dn 和 P4d GPU 实例的替代方案,用于培训
  • Amazon EC2 Trn1 实例:使用多达 16 个 AWS Trainium 芯片,您可以使用它作为 P3dn、P4d 和 DL1 实例的替代方案进行培训
  • AWS 弹性推理:通过利用 EI 为您的 CPU 实例添加适量的 GPU 加速来节省推理工作负载的成本在这篇博文中讨论
  • Amazon EC2 Inf1 实例:最多 16 个 AWS 推理芯片,每个芯片上有 4 个神经元内核,这是推理部署的一个强大且经济高效的选项,在这篇博文的中有更详细的讨论。

关于推理部署选项的详细讨论,请参考关于为推理选择正确的 AI 加速器的博文:

博文:深度学习推理 AI 加速器完全指南——GPU、AWS 推理和亚马逊弹性推理

为 ML 使用 GPU 实例时的成本优化技巧

您有几个不同的选项来优化您的训练和推理工作负载的成本。

斑点实例

即时定价使高性能 GPU 更加实惠,并允许您以比按需费率更低的折扣访问多余的 Amazon EC2 计算能力。要按实例和地区查看最新的价格列表,请访问 Spot Instance Advisor 。在某些情况下,您可以节省 90%以上的培训成本,但您的实例可能会被抢占,并且只需 2 分钟的通知就可以终止。您的训练脚本必须实现频繁的检查点操作,并且能够在 Spot 容量恢复后恢复训练。

亚马逊 SageMaker 管理培训

在开发阶段,你的大部分时间都花在原型制作、调整代码和在你最喜欢的编辑器或 IDE(显然是 VIM)中尝试不同的选项上——所有这些都不需要 GPU。你可以通过简单地分离你的开发和培训资源来节省成本,而亚马逊 SageMaker 将让你轻松做到这一点。使用 Amazon SageMaker Python SDK,您可以在您的笔记本电脑、台式机、EC2 实例或 SageMaker 笔记本实例上本地测试您的脚本。

当你准备好训练时,指定你想要训练的 GPU 实例类型,SageMaker 将提供实例,将数据集复制到实例,训练你的模型,将结果复制回亚马逊 S3,并拆除实例。您只需为培训的确切时间付费。Amazon SageMaker 还支持管理现场培训,以提供额外的便利和成本节约。

下面是我的指南:亚马逊 SageMaker 使用 Spot 实例的快速指南

通过 Amazon Elastic 推论使用所需数量的 GPU

通过利用 EI 为本文讨论的 CPU 实例添加适量的 GPU 加速来节省推理工作负载的成本: 深度学习推理的 AI 加速器完整指南——GPU、AWS 推理和亚马逊弹性推理

通过提高利用率来优化成本

  1. 通过启用混合精度训练,优化您的训练代码,以充分利用 P3、G4 和 G5 实例张量核。每个深度学习框架都有不同的做法,你必须参考特定框架的文档。
  2. 对 G4 和 G5 实例类型使用降低精度(INT8)推理来提高性能。NVIDIA 的 TensorRT 库提供了将单精度模型转换为 INT8 的 API,在其文档中提供了示例

在 Amazon EC2 GPU 实例上使用什么软件?

下载你最喜欢的深度学习框架很容易,对吗?只需pip install XXXconda install XXXdocker pull XXX就可以了,对吗?不尽然,您从上游存储库安装的框架通常没有针对它们将运行的目标硬件进行优化。这些框架旨在支持各种不同的 CPU 和 GPU 类型,因此它们将支持最小公分母的功能和性能优化,这可能会导致 AWS GPU 实例的性能大幅下降。

为此,我强烈推荐使用 AWS 深度学习 AMIs 或者 AWS 深度学习容器(DLC) 来代替。AWS 在所有亚马逊 EC2 GPU 实例上对它们进行了资格认证和测试,它们包括针对网络、存储访问以及最新的 NVIDIA 和英特尔驱动程序和库的 AWS 优化。深度学习框架在上游和下游依赖于更高级别的调度器和编排器以及更低级别的基础设施服务。通过使用 AWS AMIs 和 AWS DLCs,您知道它已经过端到端测试,并保证为您提供最佳性能。

HPC 使用案例应考虑哪些 GPU?

高性能计算(HPC)是另一个科学领域,它依靠 GPU 来加速模拟、数据处理和可视化的计算。虽然深度学习训练可以在从 FP32(单精度)到 FP16(半精度)的较低精度算法以及 Bfloat16 和 TF32 等变体上进行,但 HPC 应用需要高达 FP64(双精度)的高精度算法。NVIDIA A100、V100 和 K80 GPUs 支持 FP64 precision,这些分别在 P4、P3 和 P2 提供。

所有 GPU 实例及其特性的完整且详细的电子表格

在今天的“ 中,我把这个放在一起,因为我已经找不到一个“ 的贡献了,我向你呈现一个 AWS 特性列表上的 GPU。我经常想知道特定的 GPU 上有多少内存,或者 GPU 是否支持特定的精度类型,或者该实例是否有 Intel、AMD 或 Graviton CPU 等。在我启动一个 GPU 实例之前。为了避免浏览各种网页和 NVIDIA 白皮书,我煞费苦心地将所有信息汇编成一个表格。你可以使用下面的图片,或者直接进入文章末尾嵌入的 markdown 表,这个表由你选择的 GitHub 托管。尽情享受吧!

GPU 特性一览

您是否喜欢以图形格式消费内容,我也为您做了介绍!下图显示了 AWS 上所有 GPU 实例的类型和大小。没有足够的空间容纳所有的功能,因此我仍然推荐电子表格。

你好。感谢阅读!

感谢您的阅读。如果你觉得这篇文章很有趣,可以考虑给它一点掌声,然后在 medium 上跟我学。也请查看我在媒体上的其他博客帖子,或者在 twitter ( @shshnkp )、 LinkedIn 上关注我,或者在下面留下评论。想让我写一个特定的机器学习主题吗?我很想收到你的来信!

选择正确的性能指标可以挽救新冠肺炎的生命

原文:https://towardsdatascience.com/choosing-the-right-performance-metrics-can-save-lives-against-coronavirus-2f27492f6638?source=collection_archive---------21-----------------------

评估深度学习模型的性能,以使用相关指标检测新冠肺炎

冠状病毒病例的地理分布显示,它几乎影响了所有国家

最近宣布的疫情新冠肺炎震撼了世界上所有的医疗保健系统。它已经显示出的指数增长率,并且已经传播到 164 个国家。每个国家都处于指数曲线的不同点,都在采取预防措施和实施降低增长率的政策。

各国正在通过使用技术并在其基础设施中纳入大数据分析和实时监控来跟踪潜在的感染者和与他们有过互动的人,从而抗击疫情。这标志着这种技术首次被用于防止疫情病毒的传播。

虽然采取了这些预防措施,但病例数量仍在迅速增加。原因之一是测试套件不可用(或者使用了有故障的测试套件)。另一个原因是像意大利这样的国家缺少医疗专家,那里的病人流入量远远超过了他们的处理能力。为了克服这种情况,学者和研究人员正在研究使用深度学习来帮助专家诊断这种疾病。来自中国的一项研究显示了深度学习在 CT 扫描上的使用,“以便在病原测试之前提供临床诊断,从而为疾病控制节省关键时间”。与此同时,蒙特利尔大学的一名学者已经编译并开源了一个数据集,这样研究就可以实施并测试不同的算法(比如在这里的上完成的)。

:新冠肺炎阳性 x 光片。右图:链球菌感染。(两者都被授权为 CC-NC-SA)

随着更多的数据变得可用,来自不同研究人员和机构的更健壮和准确的实现将变得可用。部署这样的系统可以减轻医生和医院面临的负担,特别是在亚洲和非洲的发展中国家。

根据所用数据的类型以及模型的参数和超参数,这些系统将具有不同的精确度。大多数数据科学家和人工智能专家使用准确性作为标准衡量标准,来决定他们的模型有多有效,以及它与其他模型相比如何排名。他们力争最准确的型号,但在现实生活中,我们会想要最有用的型号

通过使用在特定阶段有用的指标,有多种方法来衡量模型的性能。为了解释它们,我将使用疾病在地理位置上的两个阶段(在这种情况下是新冠肺炎):当在一个地区发现感染并开始传播时,我们称之为感染出现和当病原体感染的人数超过该地区的治疗能力时,即感染饱和。但是在进入这些阶段之前,我想解释一下什么是混淆矩阵。混淆矩阵显示了实际标签与预测标签的组合计数。它有四个街区。让我们以狗和非狗的图像分类器为例。

  1. 真阳性:有多少张狗的图片被模型标记为“狗”
  2. 假阳性:有多少非狗的图像(如猫、树等)被模型标记为“狗”
  3. 假阴性:有多少张狗的图片被模型标记为“非狗”
  4. 真阴性:有多少张非狗图片被模特贴上了“非狗”的标签

混淆矩阵显示了数据集中实际标签的数量与你预测的数量的对比。

我们开始吧。

1.感染出现

让我们假设我们是深度学习专家,在一个出现了前 20 个案例的国家。我们有一个训练集,包括从全球收集的 400 个健康人的 CT 扫描和 100 个感染者的 CT 扫描。我们已经训练了两个模型,模型 A 和模型 B,它们都具有不同的架构。我们有一个 100 个 CT 扫描的测试集(70 个健康,30 个受感染),并对它们的预测制作一个混淆矩阵,以观察实际标签与预测的计数:

为了评估两个模型的性能,最常用的指标是准确性,它决定了模型正确预测的案例百分比,即它正确分配了多少标签。它的公式是:

模型 A 的准确度为 80% ,而模型 B 的准确度为 76% 。使用模型 A 进行诊断似乎是非常明显的。但模型 A 的问题是,在假阴性的情况下(即诊断受感染的患者为健康),它宣布 18 名患者为健康并让他们出院,让感染传播得更快。模型 B 做得更好,它宣布 10 个被感染的病人是健康的,从而多诊断了 8 个病人。在这种情况下应该使用的指标是召回。维基百科:

Recall(也称为 sensitivity)是实际检索到的相关实例总数的一部分。

它的基本意思是,它衡量模型捕捉尽可能多的正面案例的能力。为了计算召回率,我们使用:

A 型召回 40%,B 型召回 67%!这意味着我们应该使用模型 B,因为它可以正确诊断更多受感染的患者。

关于模型及其召回,有一些事情需要注意:

  1. 模型 B 预测 14 名健康患者被感染,模型 A 预测 2 名。这意味着你将会隔离 12 名健康的人。如果最终目标是减缓传播速度并且隔离资源可用,这可能是一个有效的选择。
  2. 通过降低根据模型的预测概率决定标签的阈值,可以提高召回率。这也可能导致更多健康的人被隔离。同样,如果目标如前所述,那么这是一个有效的选择。

2.感染饱和度:

现在,让我们假设我们在一个传染病已经蔓延全国的国家。医院和隔离区已经接近满负荷。在这种情况下,你是否正确地诊断某人被感染并不重要,因为流入的病人太多了,难以处理。如何选择谁接受治疗是一个单独的话题。但是有一件事是有害的:将健康人诊断为感染者。当感染者没有机会接受治疗时,没有人会想把资源用在健康人身上。

让我们使用模型 A 和模型 b 的混淆矩阵。为了强调影响,我将数字乘以 50:

假设所有的医院都满负荷运转,只有一家医院能容纳 500 人。这些是模型 A 对模型 B 的预测,可以通过沿着预测轴将各个类别相加得到:

模型 A 和模型 B 的每类预测数

虽然模型 B 似乎更优越,但如果我们计算有多少预测实际上是正确的概率,我们会发现其他东西。我们来计算一下有多少结果实际上是正确的概率。对于模型 A,700 个病例中有 600 个实际被感染,也就是说,如果我们从这 700 个病例中随机选择 1 个人,他或她被感染的几率为 85.7%。相反,对于模型 B,如果我们随机选择一个人,他/她有 58.8% 的几率被感染。为了比较这种影响,我们将得到 420 名真正的 A 型患者和 290 名真正的 b 型患者。使用 A 型,将增加 130 名患者得到所需的治疗。这一指标被称为精度,它是实际案例占预测案例总数的百分比。根据维基百科:

精度(也称为正预测值)是检索实例中相关实例的分数。

使用以下公式计算:

真实世界场景

疫情的饱和总会有一个起点(即浮现)。这是一条连续的指数曲线。因此,为了防止最终的危机,你会想要一种模型,它不仅能捕获尽可能多的病人,而且不会因为允许健康的人占据隔离区和医院病床而成为资源的负担。为了量化这样一个场景,需要一个能够结合精确度和召回率属性的度量。一个简单的平均值似乎是合适的,但是如果任何一个单独的指标较低,则没有惩罚。如果模型 1 的精度为 0,召回率为 100%,而模型 2 的精度和召回率都为 50%,则两个模型的平均值都为 50,这意味着它们的性能相似。有一个称为 F1 得分的指标,它将两者结合起来,如果其中一个指标较低,也会导致较低的值。它通过采用精度和召回的调和平均值来实现:

因此,模型 1 的 F1 值为 0,而模型 2 的 F1 值为 25%

让我们以模型 A 和模型 B 的混淆矩阵为例

两个模型的 F1-分数对于模型 A 是 27.3%,对于模型 B 是 31%。这可以通过模型 B 在识别受感染患者方面相对较好并且将健康人标记为受感染的比率也不太差的事实来观察。对于这两个任务,它比模型 A 更平衡。

还有一种 F1 分数的加权形式,称为 F-Beta

如果 0 < beta < 1, then more weightage is given to precision and if beta > 1,则给予回忆更多的权重。

注意:上面讨论的度量标准有缺陷,因为它们都依赖于测试集的数量和分布。而且有才能 100%召回。但是,如果模型经过适当的训练,并且测试集中有大量的示例与真实世界的分布相匹配,那么这些度量是可以依赖的。

结论

根据为不同情景计算的模型 A 和模型 B 的指标,最合理的方法是在紧急情况下使用模型 B,并随着越来越多的情况出现而倾向于模型 A。但是如果你因为某种原因只能使用一种模式,你可以把钱押在模式 b 上。

[1]:王等。艾儿,一种深度学习算法利用 CT 图像来筛查冠状病毒疾病(新冠肺炎)

[2]: 新冠肺炎 CT 扫描数据集由约瑟夫·保罗·寇恩收集。蒙特利尔大学 Mila 博士后研究员。

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

使用 Plotly 的 Choropleth Maps - 101

原文:https://towardsdatascience.com/choropleth-maps-101-using-plotly-5daf85e7275d?source=collection_archive---------13-----------------------

使用 Plotly 图形库绘制 Choropleth 图的介绍。

谢栋豪在 Unsplash 上的照片

我已经做了将近 5 年的数据分析师,但是在这段时间里,我主要使用商业智能软件来完成我所有的数据可视化任务。所以我在可视化方面的经验仅限于知道何时绘制条形图,何时绘制折线图。为了纠正这一点,我最近开始学习 matplotlib 和其他绘图和图形库。这是朝着那个方向的尝试。你可以用它来指导 choropleth 地图,或者 plotly,或者两者都有。希望这有所帮助。

绘制的地图我们的数据世界

Choropleth 地图是一种专题地图,其中的区域按照统计变量的比例进行阴影化或图案化(来自维基百科)。例如,这张地图显示了 2016 年肥胖成年人的比例。

Plotly 是一家总部位于加拿大的公司,开发分析和数据可视化工具。他们为 Python 创建了一个开源的科学图形库,我正在这里使用它。

为了这个任务,我正在寻找美国宗教信徒的数据(来源:theARDA.com)。该数据包含 1980 年、1990 年、2000 年和 2010 年不同宗教团体的县级信息。它还包括该年各县的人口,以及其他一些信息。

因此,让我们首先加载我们将需要的数据和库。

***#import libraries*** %matplotlib notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots***#import raw data*** df = pd.read_excel(‘RCMSMGCY.xlsx’, dtype={“FIPSMERG”: str})
df.head()

现在,接下来的 3 个步骤涉及清理、过滤和汇总数据以供分析,因此如果您愿意,可以跳过这一步,直接进入 Choropleth 图。

数据清理

为了绘制美国县数据,我将使用 FIPS 代码,存储在 FIPSMERG 列中。FIPS 代码是唯一的 5 位数字代码,用于标识美国的县。从上面的数据快照可以看出,在前 5 行中,FIPSMERG 只有 4 位数。这意味着前导零丢失了。让我们用 lambda 函数添加它。

***#adding 0 to FIPS code***
df[‘FIPSMERG’] = df[‘FIPSMERG’].apply(lambda x: str(0)+str(x) if len(str(x))<5 else x)

现在,每个宗教团体都被归类到一个宗教传统和家庭中,由 RELTRAD & FAMILY 列表示。我添加了这些类别的名称和州名,以使数据更容易理解。

***#religious family name mapping (FAMILY)***
rel_fam = pd.read_csv(‘religious_family.csv’)
***#religious tradition name mapping (RELTRAD)***
rel_trad = pd.read_csv(‘religious_tradition.csv’)
***#merging the 2 dataframes on group Code to get the corresponding religious family name & religious tradition catgeory*** df = pd.merge(pd.merge(df, rel_fam, left_on=’FAMILY’, right_on=’FAMILY’, how=’left’), rel_trad, left_on=’RELTRAD’, right_on=’RELTRAD’, how=’left’)
print(‘Shape: ‘+str(df.shape))***#state names mapping (STATEAB)***
state_code = pd.read_csv(‘us_state_code_data.csv’)
***#merging the dataframes***
df = (pd.merge(df, state_code, left_on=’STATEAB’, right_on=’Postal 
Code’, how=’inner’)).drop([‘Postal Code’], axis = 1)

过滤数据

对于分析的第一部分,我想看看 2010 年州和县一级信徒的百分比。为此,我需要人口和信徒的数量。

***#filtering data for only 2010*** 
df_2010 = df[df['YEAR']==2010]***#population at county level (year wise)***
pop_county = df[[‘YEAR’,’FIPSMERG’,’STATEAB’, ‘State Name’, ‘CNTYNM’, ‘TOTPOP’]].drop_duplicates().reset_index(drop=True)***#population at state level (year wise)***
pop_state = pop_county.groupby(by=[‘YEAR’,’STATEAB’, ‘State Name’]).agg({‘TOTPOP’:sum}).reset_index()

汇总数据

下一步是计算州和县一级信徒的百分比。使用 pandas groupby 函数和人口估计值,我创建了两个数据框架,一个汇总了州一级的数据,另一个汇总了县一级的数据。

***#creating state level data for %of adherents***
adh_state = df_2010.groupby(by=['STATEAB','State Name']).agg({'ADHERENT':sum}).reset_index()
adh_state = pd.merge(adh_state, pop_state[['YEAR','STATEAB', 'TOTPOP']], left_on='STATEAB', right_on='STATEAB', how='inner')
adh_state['PER_ADH'] = np.round(adh_state['ADHERENT']/adh_state['TOTPOP']*100,decimals=1)

州级汇总

***#creating county level data for %of adherents***
adh_county = df_2010.groupby(by=[‘FIPSMERG’, ‘CNTYNM’, ‘STATEAB’]).agg({‘ADHERENT’:sum}).reset_index()
adh_county = pd.merge(adh_county, pop_county[[‘FIPSMERG’, ‘TOTPOP’]], left_on=’FIPSMERG’, right_on=’FIPSMERG’, how=’inner’)
adh_county[‘PER_ADH’] = np.round(adh_county[‘ADHERENT’]/adh_county[‘TOTPOP’]*100,decimals=1)

县级汇总

Choropleth 地图

现在,我们已经准备好了州和县一级的数据框架,我们可以绘制 Choropleth 图。我正在使用来自 plotly.express 的函数 choropleth

choropleth 函数的 locations 参数与 locationmode 参数协同工作。对于美国州数据,locationmode = "USA-states "和 location 参数将采用州代码(AL、CA 等)。

***#shows %adherents at state level for the year 2010***
fig1 = px.choropleth(adh_state, locations=adh_state[‘STATEAB’], locationmode=”USA-states”,
 color=’PER_ADH’,color_continuous_scale=”inferno”,
 range_color=(0, 100),scope=”usa”,labels={‘PER_ADH’:’%Adherents’},hover_name=’State Name’,
 hover_data={‘STATEAB’:False,’State Name’:False,’ADHERENT’:False,’TOTPOP’:False,’PER_ADH’:True})fig1.update_layout(margin={“r”:0,”t”:0,”l”:0,”b”:0})
fig1.show()

要绘制各县的数据,请使用参数 geojson,该参数采用面的要素集合。你可以在这里 找到我们这些县 的收藏。同样,将位置参数设置为 FIPS 代码。

with urlopen(‘[https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json'](https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json')) as response:
 counties = json.load(response)***#plot %adherents at county level for the year 2010***
fig1 = px.choropleth(adh_county, geojson=counties, locations=’FIPSMERG’, color=’PER_ADH’,color_continuous_scale=”inferno”,
 range_color=(0, 100),scope=”usa”,labels={‘PER_ADH’:’%Adherents’},hover_name=’CNTYNM’,
 hover_data={‘FIPSMERG’:False,’CNTYNM’:False,’STATEAB’:False,’ADHERENT’:False,
 ‘TOTPOP’:False,’PER_ADH’:True})
fig1.update_layout(margin={“r”:0,”t”:0,”l”:0,”b”:0})
fig1.show()

现在我们知道了如何创建 Choropleth 地图,让我们试着给它们添加更多的功能。对于分析的第二部分,我想看看各州最大的宗教传统团体在 1980 年至 2010 年间是如何变化的。我将在我的 choropleth 地图上添加一个滑块,并使用它来改变年份。

首先,我需要确定每个州每年最大的传统群体。

df_ = df.copy()reltrad = df_.groupby([‘YEAR’,’STATEAB’,’State Name’,’RELTRADNM’]).agg({‘ADHERENT’:sum}).reset_index()
reltrad = pd.merge(reltrad, pop_state, left_on=[‘YEAR’,’STATEAB’,’State Name’], right_on=[‘YEAR’,’STATEAB’,’State Name’], how=’inner’) 
reltrad[‘PER_ADH’] = (reltrad[‘ADHERENT’]/reltrad[‘TOTPOP’])*100**#adding Ranks and filtering Rank = 1**
reltrad[‘RANK’] = reltrad.groupby([‘YEAR’,’STATEAB’])[‘PER_ADH’].rank(ascending=False,method=’first’)
reltrad_top = reltrad[reltrad[‘RANK’]==1].reset_index(drop=True)

要添加滑块,请使用函数 choropleth 的参数 animation_frame。

n = [‘Evangelical Protestant ‘,’Mainline Protestant ‘,’Black Protestant ‘,’Catholic ‘,’Orthodox ‘,’Other ‘]
cdm = dict(zip(n, [‘#003f5c’,’#444e86',’#955196',’#dd5182',’#ff6e54',’#ffa600']))figz = px.choropleth(reltrad_top, locations = ‘STATEAB’, locationmode = “USA-states”, scope = “usa”,
 color = ‘RELTRADNM’, hover_name = ‘State Name’, 
 color_discrete_map = cdm,
 hover_data = {‘YEAR’:False,’STATEAB’:False,’State Name’:True,’RELTRADNM’:False,
 ‘ADHERENT’:False,’TOTPOP’:False,’PER_ADH’:False,’RANK’:False}, 
 animation_frame=’YEAR’)figz.update_layout(margin={“r”:0,”t”:0,”l”:0,”b”:0})
figz[“layout”].pop(“updatemenus”)
figz.show()

我认为滑块在这里没有达到预期的目的。当你不得不在几年之间不停地移动时,比较这些州是很麻烦的。所以,我认为支线剧情会更好。

现在,因为一个 choropleth 没有参考笛卡尔坐标系,我们不能在子情节中使用 plotly.express' Choropleth 函数。所以我将在这里使用 plotly.graph_objects 中的 choropleth 函数。

ndf = reltrad_top[[‘YEAR’,’STATEAB’,’RELTRADNM’,’State Name’]]
ndf = pd.merge(ndf, df_[[‘RELTRADNM’,’RELTRAD’]].drop_duplicates(), left_on=’RELTRADNM’, right_on=’RELTRADNM’, how=’left’)
ndf[‘text’] = ‘State: ‘ + ndf[‘State Name’] + ‘<br>’ + ‘Tradition: ‘+ ndf[‘RELTRADNM’]years = (ndf[‘YEAR’].sort_values(ascending=True).unique()).tolist()cscale = [‘#003f5c’,’#444e86',’#dd5182',’#ffa600',’#ff6e54',’#955196']
rows = 2
cols = 2
fig = make_subplots(rows=rows, cols=cols, 
 specs = [[{‘type’: ‘choropleth’} for c in np.arange(cols)] for r in np.arange(rows)],
 subplot_titles = years, vertical_spacing=0.1, horizontal_spacing=0)for i, y in enumerate(years):
 fig.add_trace(go.Choropleth(locations=ndf.STATEAB[ndf[‘YEAR’]==y],z = ndf.RELTRAD[ndf[‘YEAR’]==y],
 locationmode = ‘USA-states’, zmin=1, zmax=6, colorscale=cscale,hoverinfo=’text’,
 hovertext=ndf.text[ndf[‘YEAR’]==y]), row = i//cols+1, col = i%cols+1)fig.update_layout(title={‘text’:’Religious Tradition by Year’, ‘xanchor’: ‘center’,’x’:0.5},
 **{‘geo’ + str(i) + ‘_scope’: ‘usa’ for i in [‘’] + np.arange(2,rows*cols+1).tolist()},
 coloraxis_showscale=False, margin={“r”:10,”t”:70,”l”:10,”b”:0},
 hoverlabel=dict(bgcolor=’#e6e6e6', font_size=12, font_family=”Rockwell”))fig.update_traces(showscale=False)
fig.show()

现在,我们有了。希望这个指南能在某些方面帮助你。你可以在这里找到数据和完整的源代码。你也可以跳到 Neptune.ai 的 Plotly Python 教程这里获得更多的提示和技巧。

PS:仅将此用作 Plotly 和 Choropleth 地图的指南。不要把数据看得太重。数据来源基于 ARDA 进行的调查,因此可能遗漏了较小的宗教团体,尤其是在 1980 年和 1990 年。

PPS:第一次写作,所以请原谅我的错误。欢迎建设性的反馈。提前感谢。

带叶的 Choropleth 图

原文:https://towardsdatascience.com/choropleth-maps-with-folium-1a5b8bcdd392?source=collection_archive---------7-----------------------

2018 年西班牙各社区总出生率的可视化

choropleth 地图是一个专题地图,根据地图上显示的统计变量对区域进行着色。这种可视化对于使用顺序配色方案来表示某个区域中测量值的可变性非常有用(测量值越高,颜色越强)。在这篇文章中,我们将学习如何使用叶子创建 choropleth 地图,以可视化西班牙各社区的(每 1000 名居民的出生率)

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

探索性数据分析包括分析数据集的主要特征,通常采用可视化方法汇总统计。目标是理解数据,发现模式和异常,并在我们执行进一步评估之前检查假设。

在这篇文章中,我们采用了一个数据集,其中包含了从 1975 年到 2018 年西班牙各社区的总出生率(每 1000 名居民的出生率)的信息。

数据集(选项—CSV separado por;)可从以下链接下载:

[## tasa Bruta de Natalidad for community autonom。无尾。自治社区。印度人…

自治社区土著居民基本情况表。无尾。自治社区。民主指数…

datos.gob.es](https://datos.gob.es/es/catalogo/ea0010587-tasa-bruta-de-natalidad-por-comunidad-autonoma-anual-comunidades-autonomas-indicadores-demograficos-basicos-identificador-api-1432)

探索性分析的第一步包括使用Pandas . read _ CSV函数将 csv 文件加载到 Pandas 数据框中,并使用 pandas 可视化前 5 行。data frame . head方法。我们跳过了文件开头的 5 行(skip prows = 5)和底部的 2 行( skipfooter=2 ),因为它们不包含有用的信息(只是关于正在显示的数据的注释)。

很容易观察到,数据帧的最后一列不包含有用的信息,应该删除。此外,我们必须用一个更具描述性的名称来修改第一列的名称。

在删除并重命名列之后,我们可以使用 pandas 来评估数据类型和缺失值。DataFrame.info 方法。

如上所示,数据集不包含空值,但是数据类型不是预期的类型。列 1975–2018 属于 object 类型,但它们包含数字数据。我们可以使用 熊猫将这些列转换成浮动。Series.astype 函数,将逗号前的句点替换为熊猫。Series.str.replace****

正如我们所观察到的,我们已经成功地将 1975–2018 列的数据类型从对象修改为浮点数。

现在!我们有一个干净的数据集来创建 choropleth 地图:)

带叶的 Choropleth 图

数据帧的修改

****leave是一个 python 库,允许你创建多种类型的传单地图。为了创建一个 choropleth 地图叶子需要一个 Geo JSON 文件,包括该地区的地理空间数据。对于西班牙的 choropleth 地图,我们需要一个 Geo JSON 文件来定义所有社区的边界。您可以从以下链接下载该文件:

** [## code for America/click _ the _ hood

github.com](https://github.com/codeforamerica/click_that_hood/blob/master/public/data/spain-communities.geojson)

为了成功绑定数据框json 文件,数据框中的社区名称必须与 json 文件中的社区名称完全匹配。因此,我们必须分析 json 文件中包含哪些名称,并相应地修改数据帧中的名称。

以下代码显示了我们如何在 json 文件中获取社区的名称:

json 文件中的名称

如上图所示, json.load() 方法返回一个 Python 字典。然后,我们遍历字典来获得社区的名称。

现在,我们用 json 文件的名称来修改数据帧的名称。请注意,我们已经创建了一个 json 文件名列表,其顺序与它们在数据框中出现的顺序相同。

修改的数据帧

现在!我们准备使用叶子来创建 choropleth 地图。

choropleth 图的生成

首先,我们创建一个叶子地图对象,以【40.416775,-3.703790】为中心(位置参数允许将地图居中在一个特定的位置)。我们还提供了一个初始缩放级别为 6 的来放大地图。尽管有初始缩放级别,但生成的地图是交互式的,这意味着您可以轻松地放大和缩小。最后,我们指定了瓷砖** ( 雄蕊水彩)。**

一旦创建了地图对象,我们就使用显示 choropleth 地图。choropleth() 法(我们也可以用叶。Choropleth() 函数)。该方法将数据帧中包含的数据json 文件几何图形绑定。

下图描绘了 2018 年西班牙各社区的毛出生率(每 1000 名居民的出生人数)。

正如你所观察到的,北部地区的出生率较低。

梅利利亚是一个西班牙自治城市,位于非洲西北海岸,与摩洛哥接壤。这座城市的出生率是西班牙最高的。为了正确观察梅利利亚,我们需要放大。

地图的定制

中有多个参数可以自定义 choropleth 贴图。以下参数是我们之前在可视化中使用的参数:

地图功能

  • 位置 →地图经纬度。
  • zoom_start →地图的初始缩放级别。
  • 平铺 →地图平铺。

Choropleth 函数

  • 地理数据→JSON 文件的名称。该文件必须位于工作目录中。
  • 数据→ 包含数据的数据帧的名称。
  • 列→ 用于生成 choropleth 图的列。
  • 包含国家名称的 json 文件中的 key_on → Key。
  • 填充颜色→ 可视化中使用的颜色方案。
  • fill_opacity →区域填充不透明度,范围 0–1(默认为 0.6)。
  • 线不透明度 → GeoJSON geopath 线不透明度,范围 0–1(默认为 1)。
  • 图例 _ 名称 →图例标题(默认空字符串)。
  • smooth_factor → 在每个缩放级别上将折线简化多少。

接下来,我详细解释一下我认为特别相关的三个参数:(1) tiles 、(2) zoom_start 、(3) fill_color

瓷砖

follow 包含多个内置 tilesets 来定制您的可视化。当创建一个地图对象时,我们可以很容易地用关键字 tiles 指定一个地图块。

我们可以使用叶创建多个瓷砖层。Tilelayer() 函数并将它们追加到地图中。为了在图层之间切换,我们添加了一个图层控件对象(leav。LayerControl() )到贴图如下。

平铺层控制

缩放开始

在叶,地图是交互式的,这意味着我们可以很容易地放大和缩小。然而,当生成地图对象时,我们可以使用参数( zoom_start )指定初始缩放级别。如下所示,我们使用三种不同的初始缩放级别创建一个地图对象:(1) 2,(2) 4,(3) 6。

初始缩放级别的修改

填充颜色

正确传达你的信息的一个关键点是为你的设计选择一个合适的配色方案。配色主要有三种类型:(1) 顺序、( 2) 发散、(3) 定性

  • 顺序配色方案从低到高进行逻辑排列,非常适合表示不包含关键中点或有序分类数据(低/中/高)的数字数据。

顺序配色方案

  • 发散配色方案突出显示高于或低于有趣的中点值(如平均值)的值。发散方案用于可以被中点有意义地分割的数据。

发散配色方案

  • 定性颜色方案用于名义分类数据(即数据没有内在排序)。类别之间的差异以不同的色调显示,亮度和饱和度相似。

定性配色方案

在我们的地图中,我们使用了顺序配色方案,因为我们想要表示一个没有有趣中点的数字变量(总出生率)。如下图所示,我们尝试了四种不同的调色板:(1)“YlGnBu”,(2)“BuPu”,(3)“OrRd”,(4)“RdPu”。

颜色的修改

正如你所观察到的,叶子为设计 choropleth 贴图提供了极大的灵活性。看一看文档,发现更多的参数来定制您的地图!🍁!

[## 叶子——叶子 0.10.1 文件

使用用于绘制地图的 Python 和 fleed . js 类制作漂亮的交互式地图。基地…

python-visualization.github.io](https://python-visualization.github.io/folium/modules.html)

信息标签

作为一个附加功能,我们使用follow . features . geojsontooltip()函数在悬停时显示社区的名称。我们提供想要显示的 GeoJson “属性”的标签作为输入(在本例中为名称】)。接下来,我们定义标签的样式,用 CSS 语言提供一个字符串。该语言描述了 HTML 元素应该如何显示。

在创建了 GeoJsonTooltip 对象之后,您可以将它传递给由 Choropleth 函数创建的 geojson 对象。

带有社区名称的标签

瞧!有标签的地图!

我鼓励你尝试用叶子来创建 choropleth 地图,记住在所有的地图中,我们已经可视化了2018总出生率(每 100 名居民的出生率)。如果您想显示另一个年份,您只需将年份提供给叶的参数(列)。Choropleth()函数。

在以后的文章中,我将解释如何用其他库如 PlotlyGeoviews 创建地图。Sooo,继续读!

🍀阿曼达🍀**

使用 Python 中的 NLTK 和 Fuzzy Wuzzy 构建故障故事并提高可靠性

原文:https://towardsdatascience.com/chronic-failure-stories-for-better-component-reliability-using-python-64e142e112e1?source=collection_archive---------77-----------------------

NLP 如何应用于航空或其他机器的部件可靠性分析

来源: @flyingraffi未刷

O 操作员或机械师一般在看到机器(大型卡车、飞机或轮船)出现问题时,会在存储这类信息的历史故障手册或系统中描述并报告(mro)。

在航空领域,每个故障都必须报告(由飞行员或机械师)。通常,这些故障是手工编写的,并存储在计算机系统中。但是作为人类,错误或描述失败的方式并不总是一致的,或者可能有打字错误,这使得很难联系或创建一个慢性失败史

在离开之前,我们将定义什么是故障历史:

想象一条时间线(图 1 ),其中每个向下的箭头代表机器上的一个故障或问题,向上的箭头代表故障的解决方案,颜色代表相同的故障,但在词汇上它们是不同的。

随着时间的推移,会出现许多故障和解决方案,因此系统之间一定存在某种关系或模式,这可能是我们在通常的分类形式中所看不到的(故障通常按机器系统进行分组,但并不总是正确分类)。在这种情况下,对于红色故障,解决方案 X 比 y 更有效。

图 1:机器 A 的故障历史

所以我们有可以改善的情况:

  • 能够对同一故障模式下的故障进行分组。
  • 能够确定这种故障模式的最佳可能解决方案,从而保证更好的可靠性。

首先,我们可以定义一个问题,其中我们有 3 台机器,我们将只关注其中的 3 个系统,每个系统都有独立的故障(MF),有不同的纠正措施。我们可以在图 2 中看到:

图 2:明确的问题

故障模式(MF)是部件的确切故障。我们不会深入 MF 的分类,但它可以通过专业工程师或部件手册进行组装。这是一个重要的输入,我们必须集中调查。无论如何,如果我们没有它,我们可以通过观察系统之间的单词可重复性来建立它,然后在专家工程师的支持下,定义故障模式。

噪声消除

让我们继续图 2 中提出的问题:我们有一个数据库,其中包含图 2 中 3 台机器的 MF 信息,它们的 3 个系统是:

  1. 我们将寻找与我们的任何失败都不相关的词,以及机械师已经写下的词,例如,“今天我发现了问题 X ”,在本文中,只有“ X ”是重要的,其他所有我们必须消除的词,在文献中这种词被称为“停用词”。为此,我们将使用 Python NLTK 库
  2. 在清理完我们所有的文本后,最好对我们归类为错误的单词进行第二次检查,但这第二步最好依靠专家工程师,我们将使用一种称为 标记化 的技术来进行单词处理。

这个过程可以在图 3 中清楚地看到:

图 3:文本数据处理

因此,用于标记化和文字处理的 python 代码如下:

图 4:实际情况

在前面的代码中,我们将机械师编写的所有内容进行了分组,并使用 NLTK 来消除单词 stop ,即使如此,在图 5 的图表中,我们可以看到我们可以继续移除与 MF 无关的单词,例如, found 、、 form 等。

图 Python 之后的词频

我们将继续清理我们的代码,我们将消除所有我们知道不是失败的单词(我们可以咨询专家),我们还将消除所有的数字。

开始开发吧!

现在,看上面的图,我们可以使用 pandas 来编写我们真正的代码(上一个是解释标记化的前一个)。我们将使用图 5 中的图表,我们将清理我们的代码,我们将删除停用词,然后我们将使用fuzzywuzzy匹配库,然后我们将对结果进行注释。

fuzzywuzzy匹配是每个人与每个人,按系统名称和每个人与每个人进行匹配会很有趣,在此之后,留下最佳结果(我们可以将此作为后续步骤)。

图 6:结果

在图 6 中,我们得到了问题的结果。
‘故障名称 _ 清除’列是我们去除了所有噪声的故障。
‘故障名称 _ 原始’列是由机械师编写的列。
‘模式 _ 故障’是每个系统 MF 词汇表的最佳匹配故障模式。
最后,列‘匹配’匹配‘故障 _ 名称 _ 清除’和‘模式 _ 故障’的百分比。

在绿色中,我们可以看到我们拥有的巧合,例如,我们成功地将 62%归类为“问题 v break”(“id _ failure”= 11),这非常好!另一方面,红色表示仍有大量噪声可以消除

下一步!

大型机器上的系统可能非常多样,MF 甚至更多,因此进行交错匹配、系统之间的测试或同一系统的测试并最终留下所有匹配中的最佳匹配将非常有用(因为一个系统有其自己的 MF,但有时系统的选择可能是错误的)。了解更多关于【NLTK】以及查看同义词或反义词选项也是不错的。另一方面,与专家坐下来消除所有可能的噪音是很好的,噪音总是存在的。

我们仍然必须分析纠正措施,选择最佳解决方案,这样我们就可以得到 MF 排名及其最佳纠正措施。这可以通过查看对于相同的故障和机器,哪个动作花费最长时间而不再次失败来确定。我们已经迈出了创建失败案例的第一步,现在还缺少拥有完整工具的下一步。

自然语言处理中的分块:解码

原文:https://towardsdatascience.com/chunking-in-nlp-decoded-b4a71b2b4e24?source=collection_archive---------8-----------------------

它在文本处理中起什么作用

当我开始学习文本处理时,我坚持了很长时间的一个话题是组块。(我知道,很难相信🙆)通常,我们可以在网上找到许多文章,从容易到难的主题,但当谈到这个特定的主题时,我觉得没有一篇文章可以对组块有全面的理解,然而下面的一篇文章是我迄今为止研究的所有与该主题相关的文章或视频的合并。

所以下面是我对组块的理解。

那么,什么是组块?

组块是从非结构化文本中提取短语的过程,这意味着分析句子以识别成分(名词组、动词、动词组等)。)然而,它没有具体说明它们的内部结构,也没有说明它们在主句中的作用。

它工作在词性标注之上。它使用词性标签作为输入,并提供组块作为输出。

简而言之,组块意味着将单词/标记分组为组块

为什么需要?

我曾经认为,在我进一步了解这些主题之前,通常文本处理是通过简单地将句子分解成单词来完成的。所以简单的打断文字并没有太大的帮助。知道这个句子涉及到一个人、一个日期、一个地点等等是非常重要的..(不同实体)。所以他们单独是没有用的。

组块可以将句子分解成比单个单词更有用的短语,并产生有意义的结果。

当你想从文本中提取信息时,比如地点、人名,组块是非常重要的。(实体提取)

让我们从头开始理解它。

一个句子通常遵循由以下部分组成的层次结构。

句子→从句→短语→单词

词组组成短语,有五大类。

  • 名词短语
  • 动词短语
  • 形容词短语
  • 副词短语
  • 介词短语

短语结构规则:

S -> NP VP

NP--> { Det N,Pro,PN}

VP -> V (NP) (PP) (Adv)

PP -> P NP

AP -> A (PP)

组块:短语被分成组块(来源:https://www.nltk.org)

在深入研究组块之前,先简要了解一下语法树和语法规则是有好处的。

正如我们所见,这里整个句子被分成两个不同的名词短语。

现在让我们用 python 实验来理解这个概念。

  1. 基于正则表达式的分块

基于正则表达式模式的分块器代码段

解析树(名词短语基于给定的正则表达式生成)

这里,我们介绍了一个语法。
其中 NP(名词短语)由
DT 组合而成?→一个或零个限定词
JJ* →零个或多个形容词
NN →名词

我们用 NLTK 定义的正则表达式解析器来解析这个语法。正如我们所看到的,整个句子 S 被分成几个组块,并用树状结构表示。基于定义的语法,创建内部树状结构。所以你可以定义你的语法,基于这个句子将被分块。

2。基于标签的训练分块器

我使用了“conll2000”语料库来训练 chunker。conll2000 语料库使用 IOB 标签定义组块。

它指定了块的开始和结束位置,以及它的类型。
POS 标签员可以接受这些 IOB 标签的培训

块标签使用 IOB 格式。
IOB : Inside,Outside,Beginning
标签前的 B 前缀表示,它是块的开始
I 前缀表示它在块内
O 标签表示令牌不属于任何块

#Here conll2000 corpus for training shallow parser modelnltk.download('conll2000')
from nltk.corpus import conll2000data= conll2000.chunked_sents()
train_data=data[:10900]
test_data=data[10900:]print(len(train_data),len(test_data))
print(train_data[1])

“conll2000”数据集的记录

tree2conlltags,conlltags2tree 是分块实用函数。

**tree 2 conltags**,获取三元组(每个令牌的单词、标签、块标签)。然后,这些元组最终用于训练标签器,并且它学习 POS 标签的 IOB 标签。

**conlltags2tree**从这些令牌三元组生成解析树
Conlltags2tree()是 tree2conlltags()的反转。我们将使用这些函数训练我们的解析器

from nltk.chunk.util import tree2conlltags,conlltags2treewtc=tree2conlltags(train_data[1])
wtc

tree=conlltags2tree(wtc)
print(tree)

def conll_tag_chunks(chunk_sents):
    tagged_sents = [tree2conlltags(tree) for tree in chunk_sents]
    return [[(t, c) for (w, t, c) in sent] for sent in tagged_sents]def combined_tagger(train_data, taggers, backoff=None):
    for tagger in taggers:
        backoff = tagger(train_data, backoff=backoff)
    return backoff

tagger 是什么?

它读取文本并给每个单词分配一个 POS 标签。(单词、标签)

Unigram tagger :确定 POS 时,只使用一个单词。(基于单词上下文的标记器)

UnigramTaggerBigramTaggerTrigramTagger是继承自基类NGramTagger的类,基类本身继承自ContextTagger类,后者继承自SequentialBackoffTagger

我们现在将定义一个类NGramTagChunker,它将接受带标签的句子作为训练输入,获取它们的(单词、词性标签、组块标签)WTC 三元组并训练一个带有UnigramTaggerBigramTagger作为补偿标签。

我们还将定义一个 parse()函数来对一个新句子执行浅层解析。

from nltk.tag import UnigramTagger, BigramTagger
from nltk.chunk import ChunkParserI#Define the chunker class
class NGramTagChunker(ChunkParserI):
  def __init__(self,train_sentences,tagger_classes=[UnigramTagger,BigramTagger]):
    train_sent_tags=conll_tag_chunks(train_sentences)
    self.chunk_tagger=combined_tagger(train_sent_tags,tagger_classes)def parse(self,tagged_sentence):
    if not tagged_sentence:
      return None
    pos_tags=[tag for word, tag in tagged_sentence]
    chunk_pos_tags=self.chunk_tagger.tag(pos_tags)
    chunk_tags=[chunk_tag for (pos_tag,chunk_tag) in chunk_pos_tags]
    wpc_tags=[(word,pos_tag,chunk_tag) for ((word,pos_tag),chunk_tag) in zip(tagged_sentence,chunk_tags)]
    return conlltags2tree(wpc_tags)#train chunker model
ntc=NGramTagChunker(train_data)#evaluate chunker model performance
print(ntc.evaluate(test_data))

现在,我们将利用这个模型对我们的新闻标题样本进行浅层解析和分块。

import pandas as pd
sentence='No new emoji may be released in 2021 due to COVID-19 pandemic word'
nltk_pos_tagged=nltk.pos_tag(sentence.split())
pd.DataFrame(nltk_pos_tagged,columns=['word','POS tag'])

chunk_tree=ntc.parse(nltk_pos_tagged)
print(chunk_tree)

语法树

chunk_tree

解析树

你也可以根据需要定义基于分类器的分块器。你可以在这里了解更多。

https://www . geeks forgeeks . org/NLP-classifier-based-chunking-set-1/?ref=rp

分块的另一个子过程叫做“分块”

我们创建一个令牌序列,它不包含在块中。所以这是寻找洞察力或背景。(我不在这一部分讨论)

感谢您的阅读。🙏

我试图最大程度地涵盖这个话题。欢迎建议。

作为荣誉奖,我要感谢迪潘然(DJ)萨卡尔。我一直跟着他的教程从零开始学 NLP。

页(page 的缩写)这是我的第一篇技术文章。希望随着学习的进步,我会继续写作。

参考

流失预测:使用 Apache Spark 的 Sparkify 案例研究

原文:https://towardsdatascience.com/churn-prediction-a-case-study-of-sparkify-using-apache-spark-e67722a84de?source=collection_archive---------46-----------------------

音乐流媒体平台用户的大数据建模

Soure:AWS

简介:

当前席卷各行业的数字化浪潮导致了数据的爆炸,因为信息正通过各种方式被利用。这一点,加上社交媒体的出现,极大地鼓励了对人工智能的倾向和匹配。这种倾向建立在从海量数据中获得洞察力的能力上这些数据有时是实时获得的,同时为依赖这些数据的产品提供动力。Apache Hadoop 和 Spark 正在支持处理这种大数据的技术。一台计算机无法处理如此大规模的数据集,需要使用计算平台(如亚马逊网络服务(AWS)、微软 Azure、IBM Watson 和谷歌云)在线托管多台计算机。这就引出了本文的目标,它将应用大数据技术(Spark)并在 AWS 上运行,以分析 12 GB 大小的大数据。这里的数据集来自一个名为“Sparkify”的伪音乐流媒体服务的 Udacity。一些用户在作为付费用户使用该服务一段时间后,最终取消了他们的订阅。因此,目标是能够预测此类用户的流失,此处定义为当用户在“取消确认”页面中被跟踪时,使用用户使用平台时测量的不同特征。

业务和数据理解:

使用探索性数据分析(EDA),可以了解不同用户在决定取消订阅之前的行为。有些事实是惊人的,而有些是清晰的。

  1. Length: 每个用户花在流媒体歌曲上的平均时间长度的合计长度。这表明没有取消用户具有稍高的歌曲平均长度。

  2. 点赞: 通过每个用户竖起大拇指的总计数来聚集点赞显示,与后来取消的用户相比,没有取消的用户更倾向于对歌曲竖起大拇指。

图一。两个用户组在其他事件中的点赞百分比

  1. 不喜欢: 按每个用户的 page -thumbs_down 总数合计不喜欢。与后来取消的用户相比,没有取消的用户不太喜欢歌曲。

图二。两组用户对其他事件的不喜欢百分比

  1. 新增好友: 按每个用户页面新增好友总数合计新增好友。与后来取消的用户相比,没有取消的用户更倾向于添加朋友(通过“添加朋友页面”与所有其他页面的百分比来衡量)。

5.Playlist_adds:按每个用户添加到播放列表的页面总数合计“Playlist _ adds”,显示与后来取消的用户相比,未取消的用户在“add_playlist”页面中出现的百分比更高。

  1. 降级: 按页面总计数累计降级-每个用户降级,已知未取消的用户在“降级”页面中出现的百分比比后来取消的用户低。

  2. 已升级: 根据每个用户的页面升级总数进行升级,已知未取消的用户比后来取消的用户具有更高的升级百分比。

  3. NumSongs: 通过每个用户的歌曲总数来聚集歌曲,已知没有取消的用户与后来取消的用户相比具有更高的歌曲平均数。“NextSong”页面类似于播放长度不是 None 的有效播放,这应该是歌曲计数的同义词,如果包括在内,不会给模型增加额外的好处。

图三。流失用户更多地使用 GET 方法。

  1. Method_PUT: 按每个用户使用 Put 方法的次数汇总 Put 方法。这是因为用户可能使用了不止一种方法,因此,将其设置为简单分类将不会清楚地反映此功能的效果

  2. Method_GET: 按每个用户使用 Get 方法的次数来聚合 Get 方法。与 PUT 方法的逻辑相同

  3. 性别: 根据性别对用户进行分组,因为没有用户拥有一个以上的性别。因此,性别是一个纯粹的分类特征。

  4. 【状态 _307: 按每个用户使用状态 307 的次数汇总状态。这是因为某些用户使用了不止一种类型状态

  5. 状态 _200: 状态由每个用户使用状态的次数 200 来汇总。

  6. 【状态 _404: 通过每个用户使用状态 404 来流传送歌曲的次数来聚集状态。

15.Level _ payed:根据每个用户使用付费级别播放歌曲的次数来汇总级别。

图 4。流失用户更多地作为免费用户流入

16。Level_free: 根据每个用户使用免费级别播放歌曲的次数来汇总状态。

  1. 注销: 汇总每个用户注销的总次数。这表明取消的用户经常被发现已经注销。

特征工程:

这显然是任何机器学习中最重要的部分之一,因为无论你在这里做什么,都将决定你的模型能够在多大程度上对用户行为进行分类。对于这个项目,从对数据集(EDA)的探索性分析中获得了一些见解,以了解就其对因变量(此处为标签列)的影响而言可能重复的特征。一些列具有不特定于用户的子特征,因此给定用户可能具有不止一个这样的特征。每个用户使用的级别就是一个例子。有时,可能会发现用户使用了免费级别,后来又使用了付费级别。因为,在这种情况下,它们被设计成计数、总和或平均值的集合,这取决于哪个更有意义。另一方面,有些列是纯分类列,如性别。对于这些,简单的编码(使用字符串索引器)就可以了。其他列是可以使用每个用户的总和来设计的某些变量,例如每个用户的收听时长。在所有情况下,都要避免特征的重复,或者用两个特征来解释相似的事件。显示了一个列有所有所需特征的数据框:

图 5:简要查看用于建模的特征数据框架

空元素:

因为有些用户没有某些特性的值,所以它们被捕获为 NULL。实际上,考虑到使用了聚合,这些空元素是零值。因此,对于所有列,这些空元素都被替换为零。

缩放:

数据集中所有要素的值的范围显示出相当大的差异。因此,对于某些机器学习模型,如逻辑回归,它们需要被缩放。为了找到最合适的定标器,通过绘制所有列的直方图来检查所有特征的分布。这表明偏离了正态分布,在一些特征中存在异常值。因此,选择了 MinMaxScaler 而不是标准 Scaler。

降维:

使用主成分分析(PCA),可以减少为预测而设计的特征,以提高模型的性能,同时加速预测。一项旨在了解不同要素在解释数据集中的差异方面所起作用的测试显示,前 10 个要素解释了数据集中 99.9%的差异。因此,预测中使用了前 10 个特征。

建模:

首先在 sparkify 数据集上尝试了三种不同的机器学习模型,看看哪一种能给出更好的预测。F1 分数被用作决定性指标。F1 定义为精确度和召回率的调和平均值。请记住,精度是对所有肯定预测的真实肯定的度量,而召回是对所有肯定标签的真实肯定预测的度量。因此,F1-score 用于捕捉模型在其预测中区分两个类别的程度,同时量化正电子的预测(此处定义为流失或标签== 1)。这与准确性相反,准确性将不会捕捉对将取消其订阅的用户做出的预测有多好。由于这是一个简单的二进制分类问题,即“流失”(标签 1)或“不流失”(标签 0 ),因此使用 multiclassclarticationevaluator 作为评估器。

将数据分成训练集和测试集:

数据集按照 0.75/0.25 的顺序分成两部分,训练集具有较大的份额。对于每种机器学习技术,训练集用于拟合/建立模型,而建立的模型应用于测试集以研究性能

基线模型:

构建了一个基线模型,用作衡量要在数据集上测试的其他机器学习模型的性能的起点。作为一个典型的二元分类问题,首先想到的模型是逻辑回归模型。使用大多数默认参数,除了定义的elasticNetParammaxIterregParam:

regParam = [0.3]
elasticNetParam = [0.8]

maxIter = [10]

逻辑回归分析的准确率和 F1 值分别为 82%和 72%。查看所有对流失用户的预测{1}可以发现,它未能成功预测测试集中的流失。

随机森林分类器:

Spark 的分类模块有一个随机森林分类器的实现,它是树和集成分类器的成员。作为被吹捧为分类任务中性能最好的算法之一,这也进行了实验。超级参数针对树的数量numTree和树构建的最大深度进行了调整,以使用折叠数量numFold等于 3 的交叉验证技术来尝试maxDepth。。此参数网格设置为:

numTree:【3,5,8,10,12,15】

maxDepth: [4,8]

交叉验证后,表现最好的模型的numTree为 8,而maxDepth为 4。这一最佳表现用于在测试集上进行预测,结果显示F1-得分 为 0.73。该模型能够预测一个正确的流失用户。

使用 RandomForest 进行流失预测

决策树分类器:

假设我们有一个少于 200 行的数据框架可用于训练,我认为在预测用户流失时应用一个不太复杂的树技术是明智的,特别是使用RandomForestClassifier 的不太好的性能。 超参数针对树的数量maxBinsmaxDepth进行了调整。使用的参数网格是:

maxBins:[2,10,32]

maxDepth:【1,2,3】

交叉验证的最佳表现模型是 3 个模型中的maxDepth和 32 个模型中的maxBins。当该模型应用于测试集时,性能显示出 0.86 (86%)的,0.85 (85%)的,0.4 (40%)的**

另一种机器学习算法 梯度推进树 也被测试,以查看是否可以在预测方面有所改进。与 决策树分类器 相比,这种技术显示出较高的召回率为 60%,但较低的 F1 得分为大约 82%。**

结论:

该项目利用了了解 Sparkify 音乐流媒体平台上用户行为的机会。利用RandomForestClassifierdecisiontreeclassifier等机器学习模型,可以预测订阅平台的用户可能的离开/取消。由于用户标签中存在巨大的不平衡,这两者对所用数据集的测试集进行预测的能力受到了阻碍。该数据集主要具有未取消的用户,比例为 173/52,只留下很少的数据集用于训练。这使得预测可能的流失更加困难。

然而, 决策树分类器 表现更好,其 F1 得分 为 0.76,而 随机森林分类器F1 得分 为 0.73,基准模型使用 逻辑回归 显示 F1 进一步提高性能的步骤包括添加新功能,如注销长度从总和变为每个用户的平均值,然后使用 PCA 将功能减少到 10 个最重要的功能(解释了 99.9%以上的差异),性能在结果(指标)和训练数据集的速度上都有显著提高。这使得 决策树 的 F1 分数从 76%提高到了 85%左右,同时召回率从 20%提高到了 40%。另一个提高性能的尝试包括测试另一个机器学习模型——梯度提升树*** ,它看到了大约 82%的 F1 分数和 60%的召回率。*****

这种改进很好,使我的最佳模型对可能流失的预测达到 60%——考虑到数据集中的不平衡,这个值足够大,不能称之为猜测。

此外,由于这种不平衡,有人试图通过 SMOTE 采样来增加流失用户的数量,改编自 github 的代码。然而,这种尝试并没有产生结果的改善。

建议:

进一步的工作应该包括测试其他机器学习算法,如 NaiveBayes。此外,通过对标签进行加权来增加数据集的另一种尝试,以便给予流失用户比非
流失用户更高的权重,可以帮助减轻数据集中不平衡的影响。最后,仍然可以设计更多的特征,同时仍然利用 PCA 将特征的数量减少到最多 10 个。

参考文献:

*https://github . com/Angkirat/Smote-for-Spark/blob/master/python code . py

https://medium . com/@ sajad 1009/credit-card-fraud-detection-with-spark-and-python-high-accuracy-27 A8 ba 8 ed 32

https://www . research gate . net/post/How _ to _ determine _ the _ number _ of _ trees _ to _ be _ generated _ in _ Random _ Forest _ algorithm*

源代码可以在我的 GitHub 资源库 这里

我欢迎所有读者的评论和改进建议。在引用时,可以自由使用本书的内容和成果。

连接:

LinkedIn:Chijioke Idoko

基于 Spark 的 AWS 集群 Sparkify 客户流失预测

原文:https://towardsdatascience.com/churn-prediction-on-sparkify-using-spark-f1a45f10b9a4?source=collection_archive---------60-----------------------

我的 Udacity 数据科学家 Nanodgree 的顶点项目

https://up swell . org/2018/10/01/what-heck-is-a-spark-talk/

流失预测,即预测可能想要拒绝服务的客户,是机器学习最常见的商业应用之一。这对那些提供流媒体服务的公司尤为重要。在这个项目中,分析了一个虚构的音乐流媒体公司 Sparkify 的事件数据集。完整数据集(12GB)的一小部分(128MB)首先在 Jupyter Notebook 中使用 Spark 中的可扩展脚本进行本地分析,然后在 AWS EMR 集群上分析整个数据集。在这里找到代码。

数据准备

我们先来看一下数据。迷你数据集中有 286500 行和 18 列(大数据集中有 26259199 行)。列和前五行如下所示。

数据帧的前五行

让我们检查数据集中缺失的值。我们将从下表中找到缺失值的模式:在“艺术家”、“长度”和“歌曲”列中有相同数量的缺失值,在“名字”、“性别”、“姓氏”、“位置”、“注册”和“用户代理”列中有相同数量的缺失值。

数据帧中缺少值

如果我们仔细观察“userId ”,它的“firstName”丢失了,我们会发现这些“userId”实际上是空字符串(在 bid 数据中是 Id 为 1261737 的用户),正好有 8346 条记录(在 bid 数据中有 778479 行),我决定将其视为丢失的值并删除。这可能是某个只访问过 Sparkify 网站而没有注册的人。

UserId 中的空字符串

缺失用户 Id 的数量

删除“有问题的”userId 后,还剩下 255 个独立用户(对于大数据,这个数字是 22277)。

让我们进一步挖掘剩下的缺失值。由于数据是事件数据,这意味着单个用户的每一个操作都被记录下来。我假设“艺术家”列中那些丢失的值可能与用户的某些操作(访问的页面)有关联,这就是为什么我检查与丢失的“艺术家”相关联的访问的“页面”,并与完整数据中的“页面”进行比较,发现:“丢失的艺术家”与除“下一首歌”之外的所有其他页面相结合,这意味着只有当用户点击“下一首歌”时,才会记录“艺术家”(歌曲的演唱者)信息。

“页面”列中的类别

如果我删除那些“空”艺术家行,数据集中就不会再有丢失的值,干净数据集中的唯一用户数仍然是 255。

在处理了丢失的值之后,我将时间戳转换为纪元日期,并简化了两个分类列,只从“location”列中提取“states”信息,从“userAgent”列中提取用户使用的平台(标记为“agent”)。

数据清理步骤至此完成,我们开始探索数据,找出更多的信息。由于最终目的是预测流失,我们需要先对流失的用户进行标注(降级也是用同样的方法标注的)。我使用“取消确认”事件来定义流失:那些访问了“取消确认”页面的流失用户被标记为“1”,没有访问的被标记为“0”。类似地,谁访问页面“降级”至少一次被标记为“1”,谁没有被标记为“0”。现在,包含 278154 行和列的数据集已经准备好进行一些探索性分析了。让我们比较一下被搅动的用户和留下来的用户。

已清理数据框中的列名和行号

流失和滞留用户的数量、性别、级别和降级情况

在小数据集中,有 52 个被搅动的用户和 173 个停留的用户(对于大数据,这些数字分别是 5003 和 17274),两组中男性略多于女性(下图)。在留下来的用户中,似乎有更多的人至少降级过一次他们的账户(下图)。

“级别”列有两个值“免费”和“付费”。有些用户可能不止一次更改了他们的级别。为了检查“级别”在流失和停留用户之间有什么不同,创建了一个“valid_level”列来记录最新的用户级别。如下图所示,入住用户中付费用户较多。

注册天数、每天的歌曲数量和每次会话的歌曲数量

显然,停留的用户比流失的用户注册了更多的天数,并且停留的用户平均每天播放的歌曲都比流失的用户多。

每个会话的每日平均项目和平均会话持续时间

如下图所示,停留用户的每日平均项目数略高于流失用户。

停留用户(标记为 0)和搅动用户(标记为 1)之间的平均每日项目数

停留用户的平均会话持续时间也比频繁使用的用户长。

流失(标记为 1)和停留(标记为 0)用户之间的平均会话持续时间

用户活动分析

为了分析搅动和停留用户之间的用户活动有何不同,计算了每个用户的“竖起大拇指”、“添加到播放列表”、“添加朋友”、“滚动广告”和“拇指向下”的日平均数。之所以选择这些功能,是因为它们是访问量最大的页面(见下表)。

因此,与不变的用户相比,不变的用户添加的朋友更少,竖起大拇指的次数更少,每天添加到播放列表中的歌曲也更少。而与留下来的用户相比,被搅动的用户每天给出更多的“否定”和滚动更多的广告。

两组用户的平台和位置

用户使用的平台(表中标记为“代理”)如下图所示。六种试剂的搅拌速率似乎不同。这意味着用户使用 Sparkify 服务的平台可能会影响用户流失。

类似地,不同州的搅拌率似乎也在变化(见下图)。

特征工程

在拟合任何模型之前,组装以下列以创建用于建模的最终数据集 df_model

响应变量

标签:1 表示搅动,0 表示未搅动

解释变量(分类变量)

降级:1 表示降级,0 表示未降级

性别:M 代表男性,F 代表女性

有效级别:免费或付费

代理:五类用户使用的平台(windows、macintosh、iPhone、iPad 和兼容)

解释变量(数值)

registered_days:通过“ts”(动作的时间戳)的最大值减去“registration”时间戳来计算,并转换为天数

avg_daily_song:每天平均收听的歌曲

songs_per_session:每次会话收听的平均歌曲数

avg_session:平均会话时长

朋友:用户每天添加的朋友数量

竖起大拇指:用户每天竖起大拇指的次数

否决:用户每天否决的次数

add_playlist:“添加到播放列表”操作的每日次数

滚动广告:每日“滚动广告”的次数

分类变量“gender”、“valid_level”和“agent”首先使用 StringIndexer 转换为索引。

# creating indexs for the categorical columns
indexers = [StringIndexer(inputCol=column, outputCol=column+"_index").fit(df_model) for column in ['gender','valid_level','agent'] ]pipeline = Pipeline(stages=indexers)
df_r = pipeline.fit(df_model).transform(df_model)
df_model = df_r.drop('gender','valid_level','agent')

数字变量首先使用 VectorAssembler 组装成一个向量,然后使用 StandardScaler 进行缩放。

# assembeling numeric features to create a vector
cols=['registered_days','friends','thumbs_ups','thumbs_downs','add_playlist','roll_advert',\
      'daily_song','session_song','session_duration']assembler = VectorAssembler(inputCols=cols,outputCol="features")# use the transform method to transform df
df_model = assembler.transform(df_model)# standardize numeric feature vector
standardscaler=StandardScaler().setInputCol("features").setOutputCol("Scaled_features")
df_model = standardscaler.fit(df_model).transform(df_model)

最后,所有的分类和数字特征被组合并再次转换成一个向量。

cols=['Scaled_features','downgraded','gender_index','valid_level_index','agent_index']
assembler = VectorAssembler(inputCols=cols,outputCol='exp_features')# use the transform method to transform df
df_model = assembler.transform(df_model)

建模

由于目标是预测二元结果(1 表示流失,0 表示没有流失),因此选择了逻辑回归、随机森林和梯度提升树分类器来拟合数据集。计算 F1 评分和 AUC 作为评价指标。因为我们的训练数据是不平衡的(搅动的用户比停留的用户少)。从公司的角度来看,错误地识别出一个将要流失的用户会付出更大的代价。在这种情况下,F1-score 是一个比准确性更好的指标,因为它提供了对错误分类情况的更好的衡量(有关更多信息,请单击此处)。另一方面,AUC 为我们提供了一个关于模型在可分性方面有多好的视角,换句话说,区分 1(流失)和 0(停留)。

数据集首先被分成 80%的训练数据和 20%的测试集。

rest, validation = df_model.randomSplit([0.8, 0.2], seed=42)

逻辑回归模型

在整个数据集中,停留用户比流失用户多,在我们的训练集中,流失用户的数量是 42,只占总用户的 22%左右。为了解决这一不平衡问题并获得更好的预测结果,在模型中引入了类权重值。

如下构建具有加权特征的逻辑回归模型,并使用 BinaryClassificationEvaluator 评估该模型。

# Initialize logistic regression object
lr = LogisticRegression(labelCol="label", featuresCol="exp_features",weightCol="classWeights",maxIter=10)# fit the model on training set
model = lr.fit(rest)# Score the training and testing dataset using fitted model for evaluation purposes
predict_rest = model.transform(rest)
predict_val = model.transform(validation)# Evaluating the LR model using BinaryClassificationEvaluator
evaluator = BinaryClassificationEvaluator(rawPredictionCol="rawPrediction",labelCol="label")#F1 score
f1_score_evaluator = MulticlassClassificationEvaluator(metricName='f1')
f1_score_rest = f1_score_evaluator.evaluate(predict_rest.select(col('label'), col('prediction')))
f1_score_val = f1_score_evaluator.evaluate(predict_val.select(col('label'), col('prediction')))#AUC 
auc_evaluator = BinaryClassificationEvaluator()
roc_value_rest = auc_evaluator.evaluate(predict_rest, {auc_evaluator.metricName: "areaUnderROC"})
roc_value_val = auc_evaluator.evaluate(predict_val, {auc_evaluator.metricName: "areaUnderROC"})

逻辑回归模型的得分如下:

The F1 score on the train set is 74.38%
The F1 score on the test set is 73.10%
The areaUnderROC on the train set is 79.43%
The areaUnderROC on the test set is 76.25%

特征重要性如下所示。该功能注册天数、每次会话收听的平均歌曲数和平均会话持续时间与客户流失呈负相关,而每次会话收听的平均歌曲数和降级行为与客户流失呈正相关。换句话说,每天听更多歌曲并且至少降级一次的用户更有可能流失。然而,一次会话持续的时间越长,每次会话听的歌曲越多,用户流失的可能性就越小。

一个人每天听的歌曲越多,他就越有可能流失,这听起来有点不合理。为了得出一个安全的结论,我将包含更多的样本来再次拟合模型。这将是以后的工作。

随机森林模型

以类似的方式,随机森林模型被拟合到训练数据中,参考原始代码这里。衡量标准如下:

The F1 score on the train set is 90.21%
The F1 score on the test set is 70.31%
The areaUnderROC on the train set is 98.21%
The areaUnderROC on the test set is 80.00%

明显存在过拟合的问题。F1 和 AUC 分数对于训练集来说都非常高,而在测试集中较差。特征重要性分析显示:除了注册天数和每天收听的歌曲,每天添加的朋友数量、竖起大拇指和竖起大拇指是关于流失预测的最重要的特征。作为未来的工作,我将在大数据集上再次拟合这个模型,看看添加样本是否会解决过度拟合问题。

梯度增强树模型

GBT 模型显示了更严重的过度拟合问题。改进的建议将与前面提到的相同。首先在大数据集上尝试,如果必要的话做更精细的特征工程或者尝试其他方法

The F1 score on the train set is 99.47%
The F1 score on the test set is 68.04%
The areaUnderROC on the train set is 100.00%
The areaUnderROC on the test set is 64.58%

超参数调整和交叉验证

根据所有三个模型的 F1 和 AUC 分数,我决定选择逻辑回归模型来做进一步的超参数调整和 3 重交叉验证。

# logistic regression model parameters tuning
lrparamGrid = ParamGridBuilder() \
    .addGrid(lr.elasticNetParam,[0.0, 0.1, 0.5]) \
    .addGrid(lr.regParam,[0.0, 0.05, 0.1]) \
    .build()

然而,除了在训练集上模型性能的明显改善。测试组的 F1 和 AUC 分数都较低。对于过度拟合的情况,参数调整有点棘手,交叉验证在这种情况下无助于提高模型性能,检查这里的链接可能会对这个问题有所了解。

The F1 score on the train set is 87.73%
The F1 score on the test set is 72.74%
The areaUnderROC on the train set is 91.27%
The areaUnderROC on the test set is 78.33%

参数调整和交叉验证后,逻辑回归的特征重要性显示出与之前不同的模式。注册日是最有希望的客户流失指标(服务提供商公司可能对该信息不感兴趣)。此外,竖起大拇指、添加好友、竖起大拇指和滚动广告的数量是最重要的功能。

结论

在这个项目中,流失预测是基于一个音乐流媒体提供商的事件数据集进行的。这基本上是一个二元分类问题。在加载和清理数据之后,我进行了一些探索性的分析,并对特征工程的下一步提供了见解。总共选择了 13 个解释性特征,并将逻辑回归、随机森林和梯度增强树模型分别拟合到训练数据集。

在小数据集上,模型性能对于逻辑回归是最好的,在测试集上 F1 得分为 73.10。其他两个模型都遭受过拟合。超参数调整和交叉验证对解决过度拟合没有太大帮助,可能是因为样本数量较少。由于时间和预算的限制,最终的模型没有在大数据集上进行测试。然而,完全可扩展的流程为使用 Spark on Cloud 解决大数据上的客户流失预测问题带来了曙光。

讨论

特征工程

如何选择合适的解释特征是这项任务中最关键的步骤之一。在 EDA 之后,我简单地包含了我创建的所有特性。我想创建更多的功能,然而,进一步的计算被有限的计算能力所拖累。在这个步骤中,特征工程中有一些技术(例如 Spark ML 提供的 ChiSqSelector)可能会有所帮助。“state”列有 58 个不同的值(大数据为 100)。我试图使用 StringIndexer 将它们转换成索引值,并将其包含到解释性特性中。然而,不可能构建索引超过 maxBins (= 32)的随机森林/GBTs 模型,这就是为什么我必须排除这个特性。如果可以使用该特性的虚拟变量,问题就可以避免。遗憾的是,我没有时间了,没能做进一步的实验。

计算能力

我花在这个项目上的大部分时间都是在“等待”结果。非常令人沮丧的是,由于集群内存不足,由于阶段错误,我不得不停下来一遍又一遍地从头运行代码。为了解决这个问题,我必须将我的代码分成两部分(一部分用于建模,另一部分用于绘图),并分别运行它们。我必须减少我创造的解释变量的数量。遗憾的是,我只成功地在 AWS 集群上运行了一次大数据集的简单版本代码(这里指的是代码)并且不得不停止,因为它花费了太多的时间和成本。不幸的是,构建模型在大数据集上的分数并不令人满意。但是,代码的最后版本(Github repo 中的 Sparkify_visualization 和 Sparkify_modeling)应该是完全可扩展的。如果要在大数据上再次运行最新的代码,那么模型在大数据集上的性能应该得到提高。

测试选择性抽样方法

因为训练数据集不平衡,带有“0”标签的行比“1”多,所以我想试试随机选择与“1”行数相同的“0”行是否会提高模型性能。由于时间的限制,这将只是未来的工作。

ps:一个额外的提示可能非常有用,在关键点上执行“缓存”来加速程序。

欢迎任何讨论!请通过 LinkedInGithub 联系我

使用神经网络和 ML 模型的流失预测

原文:https://towardsdatascience.com/churn-prediction-using-neural-networks-and-ml-models-c817aadb7057?source=collection_archive---------19-----------------------

Unsplash 上由 Alexa 拍摄的照片

这个故事是我上传到 Kaggle 上的一个笔记本的演练。最初,它只使用机器学习模型,从那以后,我添加了几个基本的神经网络模型。许多媒体博客和 Kaggle 上的笔记本广泛报道了客户流失预测主题,然而,很少有使用神经网络的。将神经网络应用于结构化数据本身在文献中很少涉及。我通过 Coursera 上的 deeplearning.ai 专门化和 Keras 的 Tensorflow 文档学习了神经网络。

简介

当客户或订户停止与公司或服务做生意时,就会发生客户流失或客户流失。客户流失是一个关键指标,因为保留现有客户比获得新客户更具成本效益,因为它节省了销售和营销成本。留住客户更具成本效益,因为你已经赢得了现有客户的信任和忠诚。

有多种方法可以计算这一指标,因为流失率可能代表客户流失总数、客户流失占公司客户总数的百分比、经常性业务流失的价值或经常性价值流失的百分比。但是,在这个数据集中,它被定义为每个客户的二进制变量,计算费率不是目的。因此,这里的目标是确定和量化影响流失率的因素。

这是一个相当简单的初级项目,变数较少。对于神经网络来说,这不是一个有用的应用,因为训练样本的数量相对较少,但是使用它很容易理解神经网络。

探索性数据分析

这里跳过了数据清理步骤。丢失的值只是微小的,在总费用栏中找到,因此被删除。由于多重共线性,没有要素被删除,因为只存在少数几个要素。

熟悉自己的功能。

数据分析的第一步是熟悉数据变量、特征和目标。该数据集包含 20 个特征和一个目标变量。客户 ID 特性是一个字符串标识,因此对预测没有用处。

恰好有 3 个类的分类特征的唯一值。

在分类特征中,有些特征是二进制的,有些正好有 3 个唯一值。在检查时,注意到只有合同和互联网服务在分类特征中具有不同数量的唯一值。在 Kaggle 的一些笔记本中,“无互联网服务”类可以被指定为“否”。然而,虚拟变量似乎是更好的编码选择,因为在前一种情况下,尽管有互联网服务,但客户选择不选择服务,将会丢失数据。在特征的数量较大的情况下,将考虑标签编码或映射,因为然后一个热编码将变成大的稀疏矩阵。

检查数据中提供的这些特征的分布是很重要的,以检查特征值是否公平分布。下面的函数用于绘制分布图。

def srt_dist(df=df,cols=cat_feats):
    fig, axes = plt.subplots(8, 2,squeeze=True)
    axes = axes.flatten()

    for i, j **in** zip(cols, axes):

        (df[i].value_counts()*100.0 /len(df)).plot.pie(autopct='**%.1f%%**',figsize =(10,37), fontsize =15,ax=j )                                                                      
        j.yaxis.label.set_size(15)
srt_dist()

一些分类特征的分布

据观察,很少是老年人,只有 30%有家属,只有 10%没有电话服务。因此,从这些变量中得出的相关性是值得怀疑的。

合同任期。

自然,月合同客户的任期低于两年合同客户。

目标变量的分布。

因此,目标变量有 73 %的“无流失”实例。机器学习模型将因此而被扭曲,并且在更多“流失”的情况下,在看不见的数据上不会表现得那么好。

抵消这种类不平衡的一种方法是使用分层交叉验证,这种方法使实例的折叠具有统一的比例。

sns.pairplot(df,vars = ['tenure','MonthlyCharges','TotalCharges'], hue="Churn")

从顶行中间图可以观察到,租期较短和月费较高的客户倾向于流失,几乎呈线性关系。可以注意到,如总费用分布所示,神经网络模型也表明总费用较低的客户会流失。但是,这可能是因为随着时间的推移,任期越长的客户总费用越多。

也正如你在下面看到的;逐月合同和光纤 obtic 互联网对客户流失概率有着巨大的影响。

cat_feats=['gender', 'SeniorCitizen', 'Partner', 'Dependents','PhoneService','MultipleLines', 'InternetService', 'OnlineSecurity', 'OnlineBackup','DeviceProtection', 'TechSupport', 'StreamingTV', 'StreamingMovies','Contract', 'PaperlessBilling', 'PaymentMethod'] # As formed in notebook in upper blocks
fig,axes = plt.subplots(16)
axes = axes.flatten()
for i, j in zip(cat_feats, axes):
sortd = df.groupby([i])['Churn'].median().sort_values(ascending=False)
    j=sns.catplot(x=i,
                y='Churn',
                data=df,
                kind='bar')
    j.set_ylabels("Churn Probability")

根据不同的分类特征,此处显示了合同的流失概率。

据观察,对于高度相关的功能,如无合作伙伴或依赖关系、无技术支持、按月合同等,客户流失的可能性很高。

系统模型化

数据集根据范围为 0 到 1 的最小最大缩放器进行缩放,训练集是根据分配的前 3993 个观察值。

以下函数用于分层交叉验证。

def stratified_cv(X, y, clf_class, shuffle=True,  **kwargs):
    stratified_k_fold = StratifiedKFold().split(X,y)
    y_pred = y.copy()
    for ii, jj in stratified_k_fold: 
        Xtrain, Xtest = X.iloc[ii], X.iloc[jj]
        ytrain = y.iloc[ii]
        clf = clf_class(**kwargs)
        clf.fit(X_train,y_train)
        y_pred.iloc[jj] = clf.predict(Xtest)
    return y_predprint('Gradient Boosting Classifier:\n {}\n'.format(
    metrics.classification_report(y, stratified_cv(X, y,                                                  ensemble.GradientBoostingClassifier))))                                            
print('Support vector machine(SVM):\n {}\n'.format(
    metrics.classification_report(y, stratified_cv(X, y, svm.SVC))))
print('Random Forest Classifier:\n {}\n'.format(
       metrics.classification_report(y, stratified_cv(X, y,                                                  ensemble.RandomForestClassifier))))
print('K Nearest Neighbor Classifier:\n {}\n'.format(
       metrics.classification_report(y, stratified_cv(X, y,                                                  neighbors.KNeighborsClassifier,n_neighbors=11))))
print('Logistic Regression:\n {}\n'.format(
       metrics.classification_report(y, stratified_cv(X, y,                                            linear_model.LogisticRegression))))
print('XGBoost Classifier:\n {}\n'.format(
     metrics.classification_report(y, stratified_cv(X, y,        XGBClassifier))))Code used for classification reports of ML model

模型的加权平均 F1 分数。

最大似然模型的超参数调整

对于随机森林,调整每棵树的估计器数量和最大特征数:

# Tuning Random Forest
from sklearn.ensemble import RandomForestClassifier
# Create param grid.   
param_rf=[{'n_estimators' : list(range(10,150,15)),
            'max_features' : list(range(6,32,5))}]
# Create grid search object
clf = RandomizedSearchCV(RandomForestClassifier(), param_distributions = param_rf, n_iter=50, cv = 5, refit=True,verbose=1, n_jobs=-1,)
# Fit on data
best_clf = clf.fit(X, y)
print(best_clf.best_params_)
best_clf.best_score_

Out[]:

{'n_estimators': 130, 'max_features': 6}
0.78967497404260

对于逻辑回归,调整逆正则化参数 C:

# Tuning Logistic Regression
from sklearn.linear_model import LogisticRegression
param_grid = [
    {'penalty' : ['l1', 'l2'],
    'C' : np.logspace(-5, 5, 20),
    'solver' : ['liblinear'] }]
clf = RandomizedSearchCV(LogisticRegression(), param_distributions = param_grid, n_iter=20, cv = 5, refit=True,verbose=1, n_jobs=-1,)# Fit on databest_clf = clf.fit(X, y)
print(best_clf.best_params_)
best_clf.best_score_

Out[]:

{'solver': 'liblinear', 'penalty': 'l2', 'C': 8858.667904100832}
0.8043221203472578

神经网络

对于神经网络,两种类型的建模,预制估计和 Keras 序列模型都被使用。此外,我遇到的大多数参考资料是关于卷积神经网络和图像分类的超调预制估计器。Keras 模型对学习速率和层数进行了超调。超参数调整模型显示了类似的性能,因为数据集比通常的神经网络应用程序小。

为了使博客简洁,这里只展示了 Keras 模型。

使用一个 64–8–1 密集分层模型,学习率衰减,批量大小为 32。还使用了每一层的 L2 正则化和去除。

*# Model 1*
nn_model = Sequential()
nn_model.add(Dense(64,kernel_regularizer=tf.keras.regularizers.l2(0.001), input_dim=46, activation='relu' ))
nn_model.add(Dropout(rate=0.2))
nn_model.add(Dense(8,kernel_regularizer=tf.keras.regularizers.l2(0.001),activation='relu'))
nn_model.add(Dropout(rate=0.1))
nn_model.add(Dense(1, activation='sigmoid'))
lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay( 0.001,
      decay_steps=(X_train.shape[0]/32)*50,
      decay_rate=1,
      staircase=False)
#This time decay means for every 50 epochs the learning rate will be half of 0.001 value
def get_optimizer():
    return tf.keras.optimizers.Adam(lr_schedule)
def get_callbacks():
    return [tf.keras.callbacks.EarlyStopping(monitor='val_accuracy',patience=70,restore_best_weights=True)]nn_model.compile(loss = "binary_crossentropy", 
                  optimizer = get_optimizer(), 
                  metrics=['accuracy'])

history = nn_model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=150, batch_size=32,   callbacks=get_callbacks(),verbose=0)

plt.plot(history.history['accuracy']) 
plt.plot(history.history['val_accuracy']) 
plt.title('model accuracy') 
plt.ylabel('accuracy')
plt.xlabel('epoch') 
plt.legend(['train', 'test'], loc='upper left') 
plt.show()

根据被训练的时期的训练和准确性。

因此,由于批量较小,该模型在 20 个时期左右收敛得更快。测试集上的模型准确率为 80.72%。

估价

yprednn=nn_model.predict(X_test)
yprednn=yprednn.round()
print('Neural Network:**\n** **{}\n**'.format(
    metrics.classification_report(yprednn, y_test)))
nn_conf_matrix=metrics.confusion_matrix(yprednn,y_test)
conf_mat_nn = pd.DataFrame(nn_conf_matrix, 
    columns=["Predicted NO", "Predicted YES"], 
    index=["Actual NO", "Actual YES"])
print(conf_mat_nn)

Out[]:

Neural Network:
               precision    recall  f1-score   support
         0.0       0.92      0.84      0.87      2443
         1.0       0.51      0.69      0.58       596 accuracy                           0.81      3039
   macro avg       0.71      0.76      0.73      3039
weighted avg       0.84      0.81      0.82      3039
Confusion Matrix :
            Predicted NO  Predicted YES
Actual NO           2042            401
Actual YES           185            411

使用 Keras 进行超参数调谐

Keras tuner 的文档对此做了很好的解释。这里隐藏单元的数量、隐藏层中神经元的数量、学习率和辍学率都是超调的。

根据吴恩达的课程,学习率是最重要的,其次是动量贝塔、小批量和隐藏单元的数量。

from tensorflow import keras
from tensorflow.keras import layers
from kerastuner.tuners import RandomSearch
import IPython
import kerastuner as kt
def build_model(hp):
    inputs = tf.keras.Input(46,)
    x = inputs
    for i **in** range(hp.Int('num_layers', 1,3)):
        x =  tf.keras.layers.Dense(units=hp.Int('units_' + str(i),32,256, step=32, default=64),
             kernel_regularizer=tf.keras.regularizers.l2(0.001))(x)
        x = tf.keras.layers.BatchNormalization()(x)
        x = tf.keras.layers.ReLU()(x)
    x = tf.keras.layers.Dense(
      hp.Int('hidden_size', 4,64, step=4, default=8),
             kernel_regularizer=tf.keras.regularizers.l2(0.001),
             activation='relu')(x)
    x = tf.keras.layers.Dropout(
      hp.Float('dropout', 0, 0.5, step=0.1, default=0.5))(x)
    outputs = tf.keras.layers.Dense(1, activation='sigmoid')(x)model = tf.keras.Model(inputs, outputs)
    model.compile(
    optimizer=tf.keras.optimizers.Adam(
      hp.Float('learning_rate', 1e-3,1e-1, sampling='log')),
    loss="binary_crossentropy", 
    metrics=['accuracy'])
    return model

tuner = RandomSearch(
    build_model,
    objective='val_accuracy',
    max_trials=10,
    executions_per_trial=1)
batch_size=32
tuner.search(X_train, y_train,
                     epochs=100,batch_size=batch_size,
                     validation_data=(X_test,y_test),
                     callbacks= [tf.keras.callbacks.EarlyStopping(monitor='val_accuracy',                                                               patience=40,restore_best_weights=True)],verbose=False)
best_hp = tuner.get_best_hyperparameters()[0] 
best_hp.values

Out[]:

{'num_layers': 3,
 'units_0': 96,
 'hidden_size': 52,
 'dropout': 0.5,
 'learning_rate': 0.0075386035028952945,
 'units_1': 64,
 'units_2': 96}

超调建议采用 5 层模型,前三个单元如输出所示。

超调模型的历史图输出。

该图显示了一个复杂的模型可以有很大的差异。该模型的性能类似,但由于复杂性而略低。

超调对于小数据集可能没有大数据集有用。然而,在 Keras 文档的过拟合和欠拟合部分中,得出的结论是,随着神经网络的容量“变小”,精度会提高。因此,由于这是一个类似大小的数据集,我们也可以使用最多具有 64 到 128 个隐藏单元的 3 个隐藏层的网络。

测试不同的批量大小:小于 32 和大于 32 都会导致性能稍低。因此,此代码块可以跳过,但可以在笔记本中找到。具有 10e3 观测值的中小型数据集通常使用的批量大小为 8、32、64、128。8 的倍数使得批处理大小适合内存,并且运行更快。

批量大小为 1024 需要更长的时间来收敛,超过 100 个历元。

模型性能

混淆矩阵和 ROC 曲线给出了真正的正负准确性的意义,然而在不平衡的数据集中,正是精确-召回曲线给出了准确性的意义。在这个数据集中,负实例比正实例多,因此精确召回曲线显示了真实的性能。

ROC 可能过于乐观,因为如果模型正确地预测了负面实例,但在正面实例上失败,而精确召回曲线是基于正面实例的,则 ROC 会更乐观。

混淆矩阵值显示为百分比,因为神经网络模型使用一个集合验证,而不是 CV。XGBoost 性能与随机森林非常相似,因此这里没有显示。

1.随机森林性能

rf_conf_matrix  = metrics.confusion_matrix(y, stratified_cv(X, y, ensemble.RandomForestClassifier,n_estimators=113))
conf_mat_rf = pd.DataFrame(rf_conf_matrix, 
    columns=["Predicted NO", "Predicted YES"], 
    index=["Actual NO", "Actual YES"])
print((conf_mat_rf/7032)*100)
cv=StratifiedKFold(n_splits=6)
classifier=RandomForestClassifier(n_estimators=113)
from sklearn.metrics import auc
from sklearn.metrics import plot_roc_curve
from sklearn.model_selection import StratifiedKFold
tprs=[]
aucs=[]
mean_fpr=np.linspace(0,1,100)
fig,ax=plt.subplots()
for i,(train,test) **in** enumerate(cv.split(X,y)):
    classifier.fit(X.iloc[train],y.iloc[train])
viz=plot_roc_curve(classifier,X.iloc[test],y.iloc[test],name='ROC fold **{}**'.format(i),alpha=0.3,lw=1,ax=ax)
    interp_tpr = np.interp(mean_fpr, viz.fpr, viz.tpr)
    interp_tpr[0] = 0.0
    tprs.append(interp_tpr)
    aucs.append(viz.roc_auc)

ax.plot([0, 1], [0, 1], linestyle='--', lw=2, color='r',
        label='Chance', alpha=.8)
mean_tpr = np.mean(tprs, axis=0)
mean_tpr[-1] = 1.0
mean_auc = auc(mean_fpr, mean_tpr)
std_auc = np.std(aucs)
ax.plot(mean_fpr, mean_tpr, color='b',label=r'Mean ROC (AUC = **%0.2f** $\pm$ **%0.2f**)' % (mean_auc, std_auc),lw=2, alpha=.8)
std_tpr = np.std(tprs, axis=0)
tprs_upper = np.minimum(mean_tpr + std_tpr, 1)
tprs_lower = np.maximum(mean_tpr - std_tpr, 0)
ax.fill_between(mean_fpr, tprs_lower, tprs_upper, color='grey', alpha=.2,label=r'$\pm$ 1 std. dev.')
ax.set(xlim=[-0.05, 1.05], ylim=[-0.05, 1.05],
       title="Receiver operating characteristic example")
ax.legend(loc="lower right")
plt.show()
# Precision Recall # break code blockrfmodel=RandomForestClassifier(n_estimators= 130, max_features= 6,n_jobs=-1)
rfmodel.fit(X_train,y_train)
lg_probs = rfmodel.predict_proba(X_test)
lg_probs=lg_probs[:,1]
yhat = rfmodel.predict(X_test)
lr_precision, lr_recall, _ = precision_recall_curve(y_test,lg_probs)
lr_f1, lr_auc = f1_score(y_test, yhat), auc(lr_recall, lr_precision)
*# summarize scores*
print('RF: f1=**%.3f** auc=**%.3f**' % (lr_f1, lr_auc))
*# plot the precision-recall curves*
no_skill = len(y_test[y_test==1]) / len(y_test)
pyplot.plot([0, 1], [no_skill, no_skill], linestyle='--', label='No Skill')
pyplot.plot(lr_recall, lr_precision, marker='.', label='RF')
*# axis labels*
pyplot.xlabel('Recall')
pyplot.ylabel('Precision')
*# show the legend*
pyplot.legend()
*# show the plot*
pyplot.show()Out[]:
Confusion Matrix:
 Predicted NO  Predicted YES
Actual NO      70.036974       3.384528
Actual YES      6.143345      20.435154
Precision- Recall:
RF: f1=0.543 auc=0.603

2.逻辑回归

代码与上面类似。

Confusion matrix:
Predicted NO  Predicted YES
Actual NO      65.799204       7.622298
Actual YES     12.044937      14.533561
Precision-Recall AUC:
Logistic: f1=0.543 auc=0.640

3.神经网络模型性能

Confusion Matrix:
Predicted NO  Predicted YES
Actual NO      67.193156      13.195130
Actual YES      6.087529      13.524186
ROC:
No Skill: ROC AUC=0.500
Neural Network: ROC AUC=0.832
Precision-Recall:
Neural Network: f1=0.584 auc=0.628

我们可以看到,Random Forest 和 XGBoost 是最准确的模型,逻辑回归概括得最好,并且同样准确地预测了流失和不流失这两个类别。因此,根据精确召回曲线,逻辑回归具有最佳性能。神经网络在精确召回率上也比 RF 和 XGBoost 表现得更好。

因此,如果在看不见的数据中存在更多积极的实例,即流失标签,则逻辑回归将预测得更好。

4.特征重要性

1)根据逻辑回归的特征重要性。

weights = pd.Series(lgmodel.coef_[0],index=X.columns.values)
print (weights.sort_values(ascending = False)[:20].plot(kind='bar'))

逻辑回归模型使用的正负权重

2)根据随机森林的特征重要性

rf =  ensemble.RandomForestClassifier(n_estimators=130,max_features=6, n_jobs=-1)
rf.fit(X, y)
feature_importance = rf.feature_importances_
feat_importances = pd.Series(rf.feature_importances_, index=X.columns)
feat_importances = feat_importances.nlargest(19)
feat_importances.plot(kind='barh' , figsize=(10,10))

3)神经网络特征重要性

因为 Keras 在文档中没有提供特性重要性特性,所以我演示了两种方法。参考是一个堆栈流答案。

from keras.wrappers.scikit_learn import KerasClassifier, KerasRegressor
import eli5
from eli5.sklearn import PermutationImportance

def base_model():
    nn_model = Sequential()    nn_model.add(Dense(64,kernel_regularizer=tf.keras.regularizers.l2(0.001),
                input_dim=46, activation='relu' ))
    nn_model.add(Dropout(rate=0.2))
nn_model.add(Dense(8,kernel_regularizer=tf.keras.regularizers.l2(0.001),
                    activation='relu'))
    nn_model.add(Dropout(rate=0.1))
    nn_model.add(Dense(1, activation='sigmoid'))
    lr_schedule = tf.keras.optimizers.schedules.InverseTimeDecay(
                  0.001,
                  decay_steps=(X_train.shape[0]/32)*50,
                  decay_rate=1,
                  staircase=False)

    def get_optimizer():
        return tf.keras.optimizers.Adam(lr_schedule)
    def get_callbacks():
        return [
            tf.keras.callbacks.EarlyStopping(monitor='val_accuracy',patience=70,restore_best_weights=True)]
    nn_model.compile(loss = "binary_crossentropy", 
                  optimizer = get_optimizer(), 
                  metrics=['accuracy'])
    return nn_model

my_model = KerasRegressor(build_fn=base_model)    
my_model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=150, batch_size=32,
                    callbacks= get_callbacks(),verbose=0)

perm = PermutationImportance(my_model, random_state=1).fit(X[:500].values,y[:500].values,verbose=False)
eli5.show_weights(perm, feature_names = X.columns.tolist())

import shap
from tensorflow.keras import Sequential
*# load JS visualization code to notebook*
shap.initjs()

*# explain the model's predictions using SHAP*
*# (same syntax works for LightGBM, CatBoost, scikit-learn and spark models)*
explainer = shap.DeepExplainer(nn_model,data=X[:500].values)
shap_values = explainer.shap_values(X.values)

*# visualize the first prediction's explanation (use matplotlib=True to avoid Javascript)*
*#shap.force_plot(explainer.expected_value, shap_values[0,:], X.iloc[0,:])*

shap.summary_plot(shap_values, X, plot_type="bar")

结论

  1. 可以看出,总费用是最重要的功能,理所当然。如果客户发现服务昂贵或负担不起,他们会“流失”的首要原因。
  2. 任期也很重要,那些长期使用这项服务或签有长期合同的客户一般来说更便宜,不太可能流失。有趣的是观察到任期被列为更重要的神经网络模型。
  3. 正如在 EDA 中观察到的,大多数月合同的客户更有可能流失。可以假设,原因是由于客户的个人原因,对长期合同有所保留,或每月合同导致单位时间成本较高。
  4. 正如 EDA 中所看到的,其他重要的功能是在线安全、电子支付方式、光纤互联网服务、技术支持。
  5. 不重要的功能是性别、家属、伴侣、流媒体电视、备份和设备保护。

优惠和提高流失率:

  1. 折扣:由于最重要的特征是总费用,其次是月费用,通过建模确定的潜在客户应在下个月或几个月的合同中获得巨大折扣。这涵盖了 80 %的搅动原因。对于这个模型,应该最小化假阴性率或者最大化召回率,以便将折扣发送给最大的潜在顾客。
  2. 新合同:应执行六个月或四个月的合同。这将鼓励想要短期合同的保留客户,并增加他们在服务中的任期,从而使他们不太可能流失。
  3. 在线安全:这项服务应该得到更多的推广,并根据公司的成本在试用期内免费提供。没有在线安全的客户更有可能流失,因此此优惠可以与第一个提到的优惠相结合,折扣只能在此基础上提供。
  4. 光纤:光纤互联网的成本很高,因此要么向适当的目标受众推广,要么采用更好的技术来降低这项服务的成本。最终,市场研究团队必须决定这项服务的盈亏平衡点,它的利润是否与它造成的客户流失一样多。

另一种量化报价的方法是使用手动生成的特征及其对模型的影响。

参考

  1. 预测客户流失的随机森林与神经网络,Abhinav Sagar,Medium,https://towards data science . com/random-Forest-vs-Neural-Networks-for-Predicting-Customer-Churn-691666 c 7431 e
  2. 电信客户流失预测, Pavan Rajhttps://www . ka ggle . com/pavanraj 159/telecom-Customer-Churn-Prediction
  3. 电信客户流失预测,Melda Dede,https://www . ka ggle . com/meldadede/turn-Prediction-of-Telco-Customers
  4. 使用基本神经网络预测流失,Laurier Mantel,https://www . ka ggle . com/Laurier Mantel/using-basic-neural-networks-to-predict-churn
  5. 如何在 Python 中使用 ROC 曲线和精度召回曲线进行分类,Jason Brownlee,https://machine learning mastery . com/ROC-Curves-and-Precision-Recall-Curves-for-class ification-in-Python/
  6. Tensorflow、Keras、sklearn 文档
  7. 神经网络的特征重要性,StackOverFlow,https://stack overflow . com/questions/45361559/feature-importance-chart-in-Neural-Network-using-keras-in-python #:~:text = It % 20 most % 20 easily % 20 works % 20 with,using % 20it % 20is % 20very %直截了当。& text=At%20the%2

使用 PySpark 进行流失预测

原文:https://towardsdatascience.com/churn-prediction-using-spark-1d8f6bd4092d?source=collection_archive---------58-----------------------

预测音乐流媒体应用的用户流失

项目概述

该项目旨在探索用户交互数据,以识别客户流失。这个问题特别关注使用 Spark 处理大型数据集。PySpark 用于清理、辩论和处理数据,并执行建模和调优以构建流失预测模型。

问题陈述

Sparkify 是一家音乐流媒体公司,和 Spotify 一样。数据集包含用户交互的日志。完整的数据集为 12 GB。我们正在处理一个 128MB 的较小数据集。使用用户日志,我们需要识别有流失倾向的客户,以便为他们提供促销。我们可以确定哪些因素是客户流失的重要指标。

探索性数据分析

该数据集包含 286,500 个用户交互的日志。它有关于用户、交互、时间戳、用户使用的设备等信息。数据的模式如下:

数据模式

数据集快照如下所示:

数据清理

我们清理数据集以删除缺少 userIdsessionId 的记录,其中 userId 为空,我们有 278,154 条记录,因为这些记录中的大部分是尚未登录或希望注册的用户。我们还将注册日期和当前时间从时间戳转换为更容易理解的日期时间格式。页面功能列出了数据集中所有可能的用户操作。

用户操作

我们将客户流失定义为用户执行取消确认操作。这项服务有两种订阅级别——免费和付费。用户可以升级或降级他们的订阅级别。我们创建了一个标志来标识用户何时降级他们的帐户,以及用户是否发生了搅动。

电子设计自动化(Electronic Design Automation)

我们通过观察一些特征的分布来识别数据中的模式。

流失用户的分布

被搅动的用户在数据集中的分布表明数据集严重不平衡。虽然这是流失分析问题的标准,但我们需要在建模过程中考虑这一点。我们需要通过欠采样来平衡我们的数据集,或者选择适当的指标来更好地考虑少数类。

按订阅级别分发

我们音乐流媒体服务的免费用户比付费用户多得多。我们还应该检查给定订阅级别的用户是否有流失倾向。

按订阅级别划分的流失

我们注意到付费用户比免费用户更有可能流失。这可能是预测用户流失的一个重要因素。

用户的性别

我们的男性用户比女性用户多,但数字相差不大,所以我们可以认为我们的数据集性别基本平衡。

按性别划分的用户流失

我们注意到,与女性用户相比,男性用户更容易流失。我们还可以分析组合中订阅级别的趋势。

每次收听的歌曲数量

我们发现,与付费用户相比,免费用户每次收听的歌曲要少得多。此外,没有流失的用户平均每次听的歌曲略多,尤其是付费用户。

最后,让我们看看流媒体服务上最受欢迎的艺术家。

特征工程

由于数据集包含用户交互,我们需要在用户层面上对它们进行聚合,以构建用户档案,这将有助于识别客户流失倾向。

基于数据集中可用的特征和我们对用户行为的理解,我们创建代表用户参与度、用户简档等的特征。

我们识别用户寿命、用户性别等特征。

用户生命周期功能

我们还创建了用户参与功能,如添加的朋友数量,添加到播放列表的歌曲数量,对歌曲的褒贬。

添加的好友数量

我们还创建了与他们的音乐收听行为相关的功能,如用户收听的歌曲数量、用户收听的艺术家数量、每次会话的歌曲数量等

用户收听的歌曲数量

一旦我们创建了这些特征,我们就为每个用户合并它们,以创建我们将用于建模的最终数据库。

最终数据帧

接下来,我们移动到建模部分。

建模

注意:230 MB 的中型数据集用于建模部分,训练是在 IBM Watson 集群上完成的,而 EDA 是在 128 MB 的小型数据集上完成的。

在开始对数据集进行建模之前,我们需要将要素转换为数字要素,然后对要素进行缩放。是否缩放数据集取决于我们计划使用的模型。我们还将把我们的数据集分成训练验证测试集,以确保对模型性能的准确评估。我对数据集使用了 70:15:15 的分割。

现在我们已经准备好了数据集,我们将根据基线模型对其进行测试。在我们建立模型之前,我们将问题定义为一个二元分类问题,其中 0 表示用户没有流失,1 表示用户流失。此外,由于我们的数据集是不平衡的,准确性可能不是最好的衡量标准,因为我们可以预测所有值为 0,并具有高准确性,但召回率很低。因此,为了平衡这一点,我们使用 F1 作为我们的指标。

我认为虚拟分类器总是预测用户不会流失。我们也可以有一个随机预测用户流失的基线模型。我们的虚拟分类器的结果如下:

虚拟分类器

我们尝试其他模型,如逻辑回归、随机森林分类器、线性支持向量和梯度提升树分类器。我们在训练集上拟合模型,并对验证数据集进行预测。然后我们选择最好的 F1 分数。在我们的例子中,它是随机森林分类器。

逻辑回归度量

梯度增强的树分类器度量

接下来,我们调整我们的随机森林分类器模型。一旦我们有了一个最终的模型,我们就用它来对测试集进行预测,从而对模型性能进行基准测试。

最终模型的测试集结果

我们可以看看我们模型的特征重要性。

特征重要性

我们看到 user_lifetime 对预测客户流失的影响最大。

结论

我们利用 CRISP-DM 过程研究了客户流失预测问题。这与增加商业价值的真实问题非常相似。我们可以通过战略性地实施从探索和建模中收集的见解来留住用户并增加公司收入。

对于像这样高度不平衡的数据集,准确性不是一个可靠的指标,所以我们使用 F1 分数。我们还可以尝试对数据集进行 SMOTE 过采样或随机欠采样,以平衡类。

我们可以提取其他特征,如用户使用的设备,并查看它们对客户流失预测的影响。

我们尝试在中小型数据集上进行建模练习。我们可以探索完整的 12GB 数据集。拥有更多少数民族的记录将会提高预测能力。

该项目的完整代码可以在我的 Github 上找到。

使用 Spark 进行流失预测

原文:https://towardsdatascience.com/churn-prediction-using-spark-d9c2da720bc8?source=collection_archive---------52-----------------------

扎拉克·汗在 Unsplash 上的照片

项目描述

下面这个项目试图预测一个名为 Sparkify 的虚拟音乐流媒体服务的用户流失率。

我在 Amazon Web Services ( AWS )中使用 Spark 和一个由 3 台 m5.xlarge 机器组成的弹性 Map Reduce ( EMR )集群。一名司机和两名工人。数据集大小为 12gb,以 JSON 格式从 AWS 简单存储服务(S3)桶中读取。该文件包含用户每天使用服务时注册的活动。

至于软件库,我用过 PySpark,Python 的 Spark API。AWS EMR 版本 5.29.0。逻辑回归、随机森林、梯度提升树(GBT)分类器和朴素贝叶斯形成了 Spark 的机器学习库。来自标准数据科学 Python 堆栈的 Pandas 和 Matplotlib。

商业理解

客户流失预测是银行、保险公司、电信公司、有线电视运营商以及网飞、Hulu、Spotify 和 Apple Music 等流媒体服务的一个重要分类用例。能够预测更有可能取消其服务订阅的客户的公司可以实施更有效的客户保留策略。

根据一家领先的客户参与度分析公司的研究,客户流失每年给公司带来大约 1360 亿美元的损失。

贝恩公司所做的研究显示,增加客户保留率,仅增加5%25%至 95%* 2 。*

在减少客户流失方面投入资源的理由是基于 Lee Resource Inc .的一项研究,该研究表明,吸引新客户的成本是保持现有客户的五倍以上! 3

数据理解

数据集总共有543705 行18 列。该模式如下所示:

数据集架构

页面类别中,我们总共有 22 个唯一的条目。

页面栏目内容

我定义了一个名为 流失 的新列,它由任何 取消确认提交降级 事件组成,作为用户已经离开服务或停止付费(免费订阅)的确认。每页的点击量分布如下:

每页点击量的分布

我们可以看到 NextSong 页面被大量访问,这是有意义的,因为它表明用户正在听歌。接下来,是 首页 后跟三个表示与服务交互的: 竖起大拇指添加到播放列表添加好友 。这三项表明对服务的积极体验。另一方面,我们有 滚动广告拇指向下* 和 错误 作为用户对服务的不良体验的可能指标。*

从总结中可以看出,我们面对的是一个非常不平衡的数据集。未流失(0)和流失(1)的比率为2516

总共有 225,393 名女性302,612 名男性用户,其中有 15,700 名用户没有透露他们的性别,我将其归类为(不可用)😗*

性别栏分布

我们在计划/服务中共有 428,597 付费 用户和 115,108 用户。正如我们之前所说的,我们必须确保尽可能多地保留这些付费用户,以最大化收入(或最小化损失)。

付费用户与免费用户

数据准备

我首先着手解决的是不平衡的问题。我用了一种叫做 过采样 的技术。这是一个非常基本的方法,我利用 PySpark 的 explode dataframe 特性从代表不足的类中选择尽可能多的事件(在本例中,流失等于 1)来填充差异,直到我得到一个平衡的数据集来处理。

我读到过一些更高级的方法,但它们大多是为Pandas/Numpydata frames/sets 构建的,在我的 Spark 环境中不能很好地并行化。这肯定需要更多的时间和调查,以找到一个更强大的解决方案。我了解到的最有希望的方法是击打,感兴趣的读者可以在这里找到更多细节。**

应用这种技术后,我扩展并平衡了数据帧,使其增加了 ~50% :

从总共 543,705 个条目到总共 1,086,945 个条目。这被证明是非常有用的,因为我的模型的准确性提高了,我大大减少了没有它时我所面临的过度拟合问题。尽管它并不完美,还可以进一步改进。

userAgent 提供了我构建的两个特性的一些信息,我使用了: os浏览器

浏览器可以看到642801使用 Safari249372使用 Firefox**

Windows 是使用较多的操作系统,其次是 MacintoshX11 (Linux)。 iPhone 是第四个更常用的,兼容可能是指安卓?

我使用了 ts (时间戳)列来构建更多的特性。从 ts 我构造了 星期几小时 列。

使用这些新的栏目,我们可以看到用户倾向于在一天结束时听更多的歌曲。用户在午饭后开始收听,下午 4-5 点达到高峰(在通勤开车期间?).

一天中每小时播放的歌曲数量

用户在工作日也更多地听歌。周四似乎是引人注目的一天,但并不能得出什么结论。

按星期几播放的歌曲数量

我构建了以下特征:

  • saved _ Settings所有按“ userId 分组的“保存设置”页面事件的计数**
  • num_songs 用户播放的'歌曲'的数量统计(按' userId '分组)**
  • 拇指向上 按“用户标识”分组的所有“拇指向上”页面事件的计数**
  • num _ advertisement按“ userId ”分组的所有“滚动广告”页面事件的计数**
  • thumbs_down 按“ userId ”分组的所有“ Thumbs Down 页面事件的计数
  • Playlist _ added所有按“ userId ”分组的“ Add to Playlist ”页面事件的计数
  • 好友 _ 添加 所有按“ userId ”分组的“添加好友”页面事件计数**
  • errors_pages 按“ userId ”分组的所有“ Error ”页面事件的计数
  • songs _ persession用户(按' userId' )在给定会话( sessionId' )上播放的平均歌曲数(按'下一首歌'页面事件分组)**

我使用了 PySpark ML 特性库中的 StringIndexer、VectorAssembler 和 Normalizer。 StringIndexer 将一列标签编码成一列标签索引。 VectorAssembler 是一个转换器,它根据 ML 算法的要求,将给定的列/特征列表组合成一个向量列。最后,规格化器是一个转换器,它转换一个数据集的向量行,规格化每个向量以具有单位规格化。它采用参数 p,该参数指定用于归一化的 p 范数。(默认情况下 p=2。)这种规范化可以帮助标准化您的输入数据,并改进学习算法的行为。**

建模

我已经在训练集和测试集中分别分割了 80–20%的数据集,以进入建模阶段。

对于建模,我使用了来自 Spark ML 库中的逻辑回归、随机森林分类器、GBT 分类器和朴素贝叶斯算法。我衡量了表现最好的人,使用 F-1 评分标准作为所有人的参数来选择最好的并进行微调。

F-1 分数对我们的流失率预测模型更有意义,因为我们对假阴性假阳性更感兴趣。第一个是因为它表明我们预测用户不会离开,不会流失。第二个表示我们预测要离开但没有离开的用户。综上所述,我并不是说真阴性(预测离开服务的用户不会离开)也不重要!**

型号选择

我用“训练”数据集上的默认参数训练了逻辑回归随机森林分类器GBT 分类器朴素贝叶斯算法,并用“测试”数据集对其进行了评估。**

表 1 —模型结果总结

其中:

F1- F-1 得分

WP - 加权精度

WR -加权召回

最佳型号选择

表 1* 中我们可以看到性能最好的型号是 GBTClassifier 。我对这个模型进行了微调,运行了一个交叉验证,带有 5 个折叠和一个参数网格,如下所示:***

用于模型微调的参数网格

在获得以下值之前,我使用相同的指标对模型进行了评估:

表 2 —最佳模型参数汇总

结论

正如我们所看到的,与之前的运行相比,这个经过微调的模型的所有指标都提高了 4% ,与其他模型相比几乎提高了 10%

我们的模型预测了 46,435 名离开的用户(真正)和 58,499 名没有离开的用户(真负)。该模型还预测了 13,790 个用户离开,而没有离开(假阳性),以及 4,047 个用户没有离开(假阴性)。**

尽管我们的模型远非完美。用一个的精度只有的 77%和一个 的召回的 92%意味着我们准确地正确预测了 2/3 的流失案例。******

GBTClassifier 是我在这个项目中尝试的所有算法中最好的,也是需要更长时间训练的一个,因为它一个接一个地训练树。我在 EMR 集群的性能方面遇到了问题,必须进行一些配置才能成功地在 Spark 中训练所有这些模型。对于所有这些细节,请前往我的 GitHub 仓库。

正如我之前提到的,这个不平衡数据集的过采样/欠采样还有很大的改进空间。如果时间和预算允许,可以使用比我在这里使用的更多的超参数进行更广泛的网格搜索,以提高模型性能,但这将需要时间和预算,因为 EMR 不是免费服务。

基于机器学习的客户流失预测

原文:https://towardsdatascience.com/churn-prediction-with-machine-learning-c9124d932174?source=collection_archive---------14-----------------------

斯科特·格雷厄姆Unsplash 上的照片

用 SVC、Logistic 回归和 XGBoost 构建流失预测模型

对任何公司来说,建立和保持忠诚的客户群都是一项挑战,尤其是当客户可以自由地从一个产品类别的众多供应商中进行选择的时候。此外,留住现有客户通常比获得新客户更划算。

因此,评估客户保持率对企业来说至关重要。重要的是,不仅要衡量客户满意度,还要衡量停止与某个公司或服务做生意的客户数量。

客户流失,也称为客户流失,是在特定时期内停止使用公司服务的客户的百分比。保持尽可能低的流失率是每个企业的追求,了解这些指标可以帮助公司及时识别潜在的客户,以防止他们离开客户群。

在本文中,我们将基于电信公司数据集构建客户流失预测模型。

关于数据

数据集由 IBM 开发者平台提供,可在这里获得。一些信息,如公司名称和私人客户数据,为了保密而保持匿名,不会影响模型的性能。

我们将处理来自 7043 个客户的数据,我们有 20 个特征,如下所示:

人口统计客户信息

  • genderSeniorCitizenPartnerDependents

每位客户已签约的服务

  • PhoneServiceMultipleLinesInternetServiceOnlineSecurityOnlineBackupDeviceProtectionTechSupportStreamingTVStreamingMovies

客户账户信息

  • tenureContractPaperlessBillingPaymentMethodMonthlyChargesTotalCharges

上个月离开的客户(这是我们的模型将要预测的特征)

  • Churn

让我们检查一下目标变量Churn的值分布。

图一。流失分布

流失率为 26.54%,我们正在处理一个不平衡的数据集。搅棒的数量明显小于非搅棒的数量。

数据准备

初步观察表明,我们正在处理 10 个分类变量、7 个二元变量和 3 个数值变量。然而,这项研究将这些分类特征中的一些视为二元的。为了说明,列StreamingTVTechSupport具有值“否”、“是”和“没有互联网服务”。在这些情况下,“没有互联网服务”将被视为“没有”。最终模型将使用 4 个分类变量、13 个二元变量和 3 个数值变量进行计数。

在继续之前,让我们检查一下数值变量中的异常值,更具体地说,是在MonthlyChargesTotalCharges中。

图二。检查异常值

乍一看,数字特性一切正常。检查箱线图,没有离群值的证据。

如前所述,对初始数据集进行了调整。为了改进我们的模型,一些具有 3 个唯一值的特征被转换为二进制。解决了所有特性之后,让我们来看一个这些特性的客户流失分布的例子。

图三。流失分布

看上面的例子,我们可以解释性别可能不是模型的一个有意义的变量,因为男女客户的流失率非常相似。另一方面,有受抚养人的客户不太可能停止与公司的业务往来。

至于互联网服务,有光纤计划的客户更有可能退出。他们的流失率是 DSL 和无互联网用户的两倍多。

谈到保护服务,拥有设备保护和在线安全计划的客户更有可能维持他们的合同。

最后,合同的类型可能是模型的一个有价值的特性。请注意,逐月合约的流失率远高于一年期和两年期合约的流失率。

在建立 ML 算法之前,我们需要执行一些预处理。考虑到大多数机器学习算法在处理数字输入时效果更好,我们将使用 Scikit Learn 的LabelEncoder和 pandas 的get_dummies对数据进行预处理。以下是数据集外观的示例:

图 4。预处理后的数据集示例

机器学习模型

需要做的第一件事是将数据分成训练集和测试集。之后,为了管理不平衡的情况,我们将使用StardardScaler标准化训练集的特性,然后应用RandomUnderSampler,根据官方文档,这是一种“通过为目标类随机选择数据子集来平衡数据的方法”。

数据经过标准化和平衡后,将使用以下模型,我们将确定哪种模型显示的结果更好:

  • 支持向量分类器
  • 逻辑回归
  • XGBoost

为了评估这些模型的有效性,我们可以使用PrecisionRecall。精确将会给我们正确识别的比例,而回忆将会决定正确识别的比例。

考虑到我们正在努力解决的问题,Recall将更适合于这项研究,因为这里的目标是确定实际上倾向于停止与该公司做生意的客户的最大数量,即使一些“非搅动者”被错误地确定为“搅动者”。也就是说,在我们的情况下,最好是追求尽可能小的一些假阴性。

我们还使用了交叉验证来获得更好的结果。cross_validate方法不是简单地将数据分成训练集和测试集,而是将我们的训练数据分成 k折叠,从而更好地利用数据。在这种情况下,我们进行了 5 重交叉验证。

图五。回忆价值观

请注意,所有 3 个模型都提供了相似的结果,召回率约为 80%。我们现在将调整模型上的一些超参数,看看我们是否可以实现更高的召回值。这里使用的方法是GridSearchCV,它将搜索每个估计器的指定参数值。每个模型都有各种可以调整的参数,但我们只调整那些更有可能影响预测的参数(在param_grid参数中指定),而其余的可以保留默认值。

请在下面找到每个型号的调校:

支持向量分类器

param_grid = {'kernel': ['linear', 'poly', 'rbf', 'sigmoid'], 'C': [0.0001, 0.001, 0.01, 0.1, 1, 10, 100]}

最佳召回率:0.96 对于{'C': 0.01,' kernel': 'poly'}

请注意超参数调整是多么有效。我们搜索了Ckernel的不同值,对于 C = 0.01 和内核类型“poly”,我们得到了 96%的增加的召回率。

逻辑回归

param_grid = {'solver': ['newton-cg', 'lbfgs', 'liblinear'], 'C': [0.0001, 0.001, 0.01, 0.1, 1, 10, 100]}

最佳召回率:对于{'C': 0.0001,' solver': 'liblinear'},召回率为 0.88

转向逻辑回归,我们也实现了更好的召回,对于 C = 0.0001 和 solver =“liblinear”,召回率为 88%。

最后,让我们对 XGBoost 估计量进行一些调整。XGBoost 被认为是最有效的机器学习算法之一,因为它在分类和回归预测建模问题的结构化和表格化数据集上表现出色。它具有高度的可定制性,可以调节更大范围的参数。

XGBoost

第一步,我们将确定 XGBoost 模型中最优的树的数量,搜索n_estimators参数的值。

param_grid = {'n_estimators': range(0,1000,25)}

最佳召回率:0.82 对于{'n_estimators': 25}

我们已经可以检测到召回率的提高。现在我们已经确定了更好的n_estimators值,我们可以继续搜索两个相关参数max_depthmin_child_weight

param_grid = {'max_depth': range(1,8,1), 'min_child_weight': np.arange(0.0001, 0.5, 0.001)}

最佳召回率:{'max_depth': 1,' min_child_weight': 0.0001}的 0.86

在接下来的步骤中,我们将确定gamma的最佳值,这是一个用于控制模型过度拟合趋势的重要参数。

param_grid = {'gama': np.arange(0.0,20.0,0.05)}

最佳召回率:0.86 对于{'gama': 0.0}

最后,我们将搜索最佳的learning_rate值。

param_grid = {'learning_rate': [0.0001, 0.01, 0.1, 1]}

最佳召回率:{'learning_rate': 0.0001}的 0.88

在测试集上评估模型

在调整了 SVC、逻辑回归和 XGBoost 的参数之后,我们注意到所有三个模型都有所改进。在测试集上运行每个模型的调整版本,以检查它们的性能是至关重要的。

现在,让我们为这些算法中的每一个绘制一个混淆矩阵,以可视化它们在测试集上的性能。

支持向量分类器

图六。SVC 混淆矩阵

逻辑回归

图 7。逻辑回归混淆矩阵

XGBoost

图 8。XGBoost 混淆矩阵

在测试集上运行算法后,我们有一个显示,显示当我们调整一些参数时,模型的性能如何得到改善。这三个模型在调优后召回率都有所提高,其中 XGBoost 的召回率最高。

结论

该项目的目的是开发一个模型,能够尽可能有效地确定电信公司的大量客户。

能够提前识别潜在的客户,使公司能够制定策略,防止客户离开客户群。有了这些数据,公司可以提供激励措施,如折扣或忠诚度计划,或提供额外的服务,以降低流失率。

值得一提的另一点是调整超参数的重要性,调整 ML 算法以获得更好的结果。参数调整后,三个模型的召回率都有所提高。

XGBoost 已经在数据科学项目中证明了它的有效性,在这个项目中,它提供了模型中最好的结果。出于这个原因,XGBoost 算法将是我们解决这里提出的问题的选择。

完整代码请参考笔记本

基于机器学习的客户流失预测

原文:https://towardsdatascience.com/churn-prediction-with-machine-learning-ca955d52bd8c?source=collection_archive---------3-----------------------

机器学习项目的分步说明。

流失预测是机器学习领域的一个常见用例。如果你不熟悉这个术语,churn 的意思是“离开公司”。对于一个企业来说,了解客户可能流失的原因和时间是非常重要的。拥有一个强大而准确的客户流失预测模型有助于企业采取措施防止客户离开公司。

克里斯·利维拉尼在 Unsplash 上的照片

在这个项目中,我将使用 Kaggle 上的“电信客户流失”数据集。

对于 7043 个客户,有 20 个特征(自变量)和 1 个目标(因变量)。目标变量表明客户是否在上个月离开了公司(即客户流失=是)。由于目标变量有两种状态(是/否或 1/0),这是一个二元分类问题。

这些变量是:' customerID ',' gender ',' SeniorCitizen ',' Partner ',' Dependents ',' tension ',' PhoneService ',' MultipleLines ',' InternetService ',' OnlineSecurity ',' OnlineBackup ',' DeviceProtection ',' TechSupport ',' StreamingTV ',' StreamingMovies ',' Contract ',' PaperlessBilling ',' PaymentMethod ',' MonthlyCharges ',' TotalCharges ',' Churn '。

乍一看,只有 customerID 似乎与客户流失无关。其他变量可能会也可能不会对客户流失产生影响。我们会弄清楚的。

该项目的结构如下:

  1. 探索性数据分析
  2. 数据预处理
  3. 模型创建和评估
  4. 改进模型

1。探索性数据分析

让我们从导入所需的库开始,然后导入数据集:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline#Dataset
df = pd.read_csv("Telco-Customer-Churn.csv")
df.shape
(7043, 21)

我总是寻找缺失的值,并尝试处理它们。我们使用的数据集是预先清理过的,所以我认为没有丢失值。让我们检查一下以确保:

df.isna().sum().sum()
0

数据集中没有丢失的值,因此我们可以跳转来研究它。我们可以从目标变量开始:

df.Churn.value_counts()
No     5174
Yes    1869

目标变量具有不平衡的类分布。正类(流失=是)比负类(流失=否)少很多。不平衡的类别分布会对机器学习模型的性能产生负面影响。我们将使用上采样或下采样来克服这个问题。

在试图建立模型之前探索特征(独立变量)总是有益的。我们先来发现只有两个值的特性。

columns = df.columns
binary_cols = []for col in columns:
    if df[col].value_counts().shape[0] == 2:
        binary_cols.append(col)

剩余的分类变量有两个以上的值(或类)。

二元分类特征

让我们检查二进制特征的类分布。

fig, axes = plt.subplots(2, 3, figsize=(12, 7), sharey=True)sns.countplot("gender", data=df, ax=axes[0,0])
sns.countplot("SeniorCitizen", data=df, ax=axes[0,1])
sns.countplot("Partner", data=df, ax=axes[0,2])
sns.countplot("Dependents", data=df, ax=axes[1,0])
sns.countplot("PhoneService", data=df, ax=axes[1,1])
sns.countplot("PaperlessBilling", data=df, ax=axes[1,2])

老年人和电话服务变量之间存在严重的不平衡。大多数顾客都不是老年人,同样,大多数顾客都有电话服务。

最好根据二进制特征检查目标变量(churn)如何变化。为了能够进行计算,我们需要改变目标变量的值。“是”将为 1,“否”将为 0。

churn_numeric = {'Yes':1, 'No':0}
df.Churn.replace(churn_numeric, inplace=True)

让我们看看男性和女性的流失率是否不同:

df[['gender','Churn']].groupby(['gender']).mean()

男性和女性的平均流失率大致相同,这表明性别变量不会给模型带来有价值的预测能力。因此,我不会在机器学习模型中使用性别变量。

同样,我们可以根据流失率检查其他二元分类特征:

其他二元特征对目标变量有影响。如果你认为 2%的差异可以忽略不计,电话服务也可能被跳过。我已经决定在模型中使用这个特性。

我们还可以使用 pandas pivot_table 函数来检查特征和目标变量之间的关系。

table = pd.pivot_table(df, values='Churn', index=['gender'],
                    columns=['SeniorCitizen'], aggfunc=np.mean)
table

其他分类特征

是时候探索其他分类特征了。我们也有连续的功能,如任期,每月收费和总费用,我将在下一部分讨论。

互联网服务

互联网服务有 6 个变量,分别是流媒体电视、流媒体电影、在线安全、在线备份、设备保护和技术支持。如果客户有互联网服务,这些变量就会发挥作用。

sns.countplot("InternetService", data=df)

互联网服务变量在预测流失率方面无疑是重要的。如您所见,使用光纤互联网服务的客户比其他客户更容易流失,尽管使用 DSL 和光纤的客户数量没有太大差异。这家公司可能在光纤连接方面存在一些问题。然而,只根据一个变量进行假设并不是一个好方法。让我们也检查一下每月的费用。

光纤服务比 DSL 贵得多,这可能是客户流失的原因之一。

我们现在可以检查互联网服务相关变量的分布:

fig, axes = plt.subplots(2, 3, figsize=(12, 7), sharey=True)sns.countplot("StreamingTV", data=df, ax=axes[0,0])
sns.countplot("StreamingMovies", data=df, ax=axes[0,1])
sns.countplot("OnlineSecurity", data=df, ax=axes[0,2])
sns.countplot("OnlineBackup", data=df, ax=axes[1,0])
sns.countplot("DeviceProtection", data=df, ax=axes[1,1])
sns.countplot("TechSupport", data=df, ax=axes[1,2])

所有与互联网服务相关的功能对于它们的类别似乎具有不同的流失率,因为流失率根据拥有这些服务的客户而变化。流媒体电视和流媒体电影的区别并不大,但它们仍然可以为模式带来价值。您可以决定不包括这两个特性。

电话服务

df.PhoneService.value_counts()
Yes    6361
No      682df.MultipleLines.value_counts()
No                  3390
Yes                 2971
No phone service     682

如果客户没有电话服务,他/她就不能拥有多条线路。与 PhoneService 列相比,MultipleLines 列包含更具体的数据。所以我将不包括电话服务栏,因为我可以从多线栏了解有电话服务的人数。MultipleLines 列将 PhoneService 列向前推进了一步。

让我们看看拥有多条生产线是否会改变流失率:

它类似于 StreamingTV 和 StreamingMovies 变量,因此在模型中利用这些变量取决于您。我会将它们包含在模型中。

合同及付款方式

plt.figure(figsize=(10,6))
sns.countplot("Contract", data=df)

正如预期的那样,签订短期合同的客户更有可能流失。这清楚地解释了公司与客户建立长期关系的动机。

plt.figure(figsize=(10,6))
sns.countplot("PaymentMethod", data=df)

使用电子支票支付的客户更有可能流失,这种支付方式比其他支付方式更常见。因此,如果使用电子支票支付的客户有任何其他共同之处,可以进一步调查该细分市场。

连续特征

连续功能是任期,每月收费和总费用。总费用栏中的金额与任期(月数)乘以每月费用成正比。因此没有必要在模型中包含总费用。添加不必要的特征会增加模型的复杂性。如果可能的话,最好有一个更简单的模型。复杂的模型往往会过度拟合,不能很好地推广到新的、以前看不到的观察结果。由于机器学习模型的目标是预测或解释新的观察结果,过拟合是一个至关重要的问题。

我们再来看看连续特征的分布。

fig, axes = plt.subplots(1,2, figsize=(12, 7))sns.distplot(df["tenure"], ax=axes[0])
sns.distplot(df["MonthlyCharges"], ax=axes[1])

任期:客户在公司呆的月数。

根据任期变量的分布,大多数客户要么是新客户,要么已经在公司呆了很长时间。我们的目标应该是找到一种方法来留住这些客户长达几个月的任期。

月度费用也有类似的趋势。低利率和高利率之间似乎有差距。

让我们来看看流失率是如何随着任期和每月费用而变化的:

很明显,已经成为客户很长时间的人倾向于留在公司。离开公司的人的平均任期比留下来的人少 20 个月。

似乎月费对流失率也有影响。

合同和任期特征可能相互关联,因为长期合同的客户可能会在公司呆更长时间。让我们弄清楚。

正如所料,合同和任期是高度相关的。拥有长期合同的客户比拥有短期合同的客户成为客户的时间更长。我认为合同对保有权特性没有什么价值,所以我不会在模型中使用合同特性。

在研究了这些变量之后,我决定不使用下面的变量,因为它们很少或根本不增加模型的信息量:

  • 客户 ID
  • 性别
  • 电话服务
  • 合同
  • 总费用
df.drop([‘customerID’,’gender’,’PhoneService’,’Contract’,’TotalCharges’], axis=1, inplace=True)

2。数据预处理

分类特征需要转换为数字,以便它们可以包含在由机器学习模型完成的计算中。我们数据集中的分类变量不是有序的(也就是说,它们没有顺序)。例如,“DSL”互联网服务并不优于“光纤”互联网服务。有序分类变量的一个例子是从 1 到 5 的评级,或者是具有类别“差”、“一般”和“好”的变量。

当我们对分类变量进行编码时,会给每个类别分配一个数字。具有较高数字的类别将被认为更重要或对模型的影响更大。因此,我们需要对变量进行编码,使每个类别由一列表示,该列中的值为 0 或 1。

我们还需要缩放连续变量。否则,具有较高值的变量将被赋予更大的重要性,这会影响模型的准确性。

from sklearn.preprocessing import LabelEncoder, OneHotEncoder
from sklearn.preprocessing import MinMaxScaler

分类变量编码:

cat_features = ['SeniorCitizen', 'Partner', 'Dependents',
'MultipleLines', 'InternetService','OnlineSecurity'      'OnlineBackup', 'DeviceProtection', 'TechSupport', 'StreamingTV',
'StreamingMovies', 'PaperlessBilling', 'PaymentMethod']X = pd.get_dummies(df, columns=cat_features, drop_first=True)

缩放连续变量:

sc = MinMaxScaler()
a = sc.fit_transform(df[['tenure']])
b = sc.fit_transform(df[['MonthlyCharges']])X['tenure'] = a
X['MonthlyCharges'] = b

让我们检查数据集的新维度:

X.shape
(7043, 26)

重采样

正如我们在开始时简要讨论的,具有不平衡类别分布的目标变量对于机器学习模型来说是不期望的。我将使用上采样,这意味着通过从类中随机选择行,用较少的样本增加类的样本数。

sns.countplot('Churn', data=df).set_title('Class Distribution Before Resampling')

分离积极类别(流失=是)和消极类别(流失=否):

X_no = X[X.Churn == 0]
X_yes = X[X.Churn == 1]

向上采样正类:

X_yes_upsampled = X_yes.sample(n=len(X_no), replace=True, random_state=42)print(len(X_yes_upsampled))
5174

结合正反类,检查类分布:

X_upsampled = X_no.append(X_yes_upsampled).reset_index(drop=True)sns.countplot('Churn', data=X_upsampled).set_title('Class Distribution After Resampling')

3。模型创建和评估

我们需要将数据集划分为训练和测试子集,以便我们能够在新的、以前未见过的示例上测量我们的模型的性能。

from sklearn.model_selection import train_test_splitX = X_upsampled.drop(['Churn'], axis=1) #features (independent variables)y = X_upsampled['Churn'] #target (dependent variable)

将数据集划分为训练和测试子集:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=42)

山脊分级机

我已经决定使用脊分类器作为基础模型。然后我会尝试一款我认为性能会更好的车型。

from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import accuracy_score

创建脊线分类器对象并对其进行训练:

clf_ridge = RidgeClassifier() #create a ridge classifier object
clf_ridge.fit(X_train, y_train) #train the model

对训练集进行预测并评估:

pred = clf_ridge.predict(X_train)accuracy_score(y_train, pred)
0.7574293307562213

对测试集进行预测并评估:

pred_test = clf_ridge.predict(X_test)accuracy_score(y_test, pred_test)
0.7608695652173914

该模型在训练集和测试集上的准确率分别达到了 75%和 76%。该模型没有过度拟合,因为训练集和测试集的精度非常接近。然而,75%的准确度不是很好,所以我们将尝试使用不同的模型来获得更好的准确度。

随机森林

from sklearn.ensemble import RandomForestClassifier

创建随机林对象并训练它:

clf_forest = RandomForestClassifier(n_estimators=100, max_depth=10)clf_forest.fit(X_train, y_train)

这里需要提到两个参数。

  • n_estimators:森林中树木的数量。
  • max_depth:树的最大深度。

这些参数在模型的准确性以及防止模型过度拟合方面具有关键作用。一般来说,如果我们使用深树(max_depth 非常高),模型可能会过拟合。

对训练集进行预测并评估:

pred = clf_forest.predict(X_train)accuracy_score(y_train, pred)
0.8860835950712732

对测试集进行预测并评估:

pred_test = clf_forest.predict(X_test)accuracy_score(y_test, pred_test)
0.842512077294686

训练集的精度比测试集的精度高 4%,这表明有轻微的过度拟合。我们可以减少树在森林中的深度,因为随着树越来越深,它们会变得越来越具体,这导致不能很好地概括。但是,减少树深度也可能会降低准确性。所以我们在优化参数时需要小心。我们还可以增加森林中的树木数量,这将有助于模型更加通用,从而减少过度拟合。几乎在每个项目中,参数调整都是非常关键的部分。

另一种方法是进行交叉验证,允许使用训练集和测试集中的每个样本。

4。改进模型

GridSearchCV 提供了一种简单的参数调整方法。我们可以使用 GridSearchCV 进行交叉验证并尝试不同的参数。

from sklearn.model_selection import GridSearchCV

创建 GridSearchCV 对象:

parameters = {'n_estimators':[150,200,250,300], 'max_depth':[15,20,25]}forest = RandomForestClassifier()clf = GridSearchCV(estimator=forest, param_grid=parameters, n_jobs=-1, cv=5)

cv = 5 意味着具有 5 重交叉验证。因此数据集被分成 5 个子集。在每次迭代中,4 个子集用于训练,另一个子集用作测试集。当 5 次迭代完成时,模型使用所有样本作为训练样本和测试样本。

n_jobs 参数用于选择使用多少处理器。-1 表示使用所有处理器。

clf.fit(X, y)

让我们检查一下最佳参数和总体精度:

clf.best_params_
{'max_depth': 20, 'n_estimators': 150}clf.best_score_
0.8999806725937379

best _ score _:best _ estimator 的平均交叉验证分数。

我们已经实现了将近 90%的总体准确率。这是 best_estimator 的平均交叉验证分数。在前一个随机森林中,平均分数约为 86%(训练 88%,测试 84%)。使用 GridSearchCV,我们将模型精度提高了 4%。

我们总是可以尝试改进模型。机器学习模型的燃料是数据,因此如果我们能够收集更多的数据,对改进模型总是有帮助的。我们还可以在 GridSearchCV 中尝试更大范围的参数,因为稍微调整一个参数可能会略微增加模型。

最后,我们可以尝试更健壮或更高级的模型。请记住,在做出此类决定时,会有一个权衡。高级模型可能会提高准确性,但它们需要更多的数据和更多的计算能力。所以这归结为商业决策。

你可以从这个回购下载该项目的完整笔记本。

感谢您的阅读。如果您有任何反馈,请告诉我。

使用 PySpark 进行流失预测

原文:https://towardsdatascience.com/churn-prediction-with-pyspark-cdb7293c0850?source=collection_archive---------38-----------------------

搅动婴儿搅动器!

你不讨厌你的顾客离开吗?

马科斯·保罗·普拉多在 Unsplash 上的照片

很难过,他们可能再也不会回来了!

正如 Flo 在的文章:中提到的,根据 《哈佛商业评论》 的说法,获得新客户比留住现有客户要贵五到二十五倍。”

你可以做点什么!

如果我告诉你,你可以预测客户流失。

在本文中,我将为您提供实用的机器学习实现,使用一个虚构的数字音乐流媒体服务来预测客户流失。

我们将讨论以下几点:

  1. 客户参与度指标的特征工程
  2. 秘方是过采样
  3. 最佳性能模型

介绍

在讨论细节之前,让我们先解释一下数据源。

该数据集来自一个名为 Sparkify 的虚拟数字音乐流媒体服务。它包含几个从网站交互日志中派生出来的潜在有趣的字段。

我们使用 Spark ,因为数据集是 12GB,我们需要分布式机器学习技术的力量来帮助我们完成繁重的工作。

在我们的例子中,客户流失被定义为 page == "取消确认"

数据的模式如下所示:

客户参与度指标的特征工程

我们的数据集允许多种特征工程方法。我把重点放在结合使用“页面”字段和我们的时间“ts”组件来理解用户对我们网站的参与度。

页面字段是分类字段,有几个不同的值,如下所示:

在 PySpark 中,从分类列创建虚拟变量一点也不简单。值得展示这些步骤:

使用 StringIndexer 将分类列转换为索引列

使用 OneHotEncoder 将索引转换为稀疏向量

这可能就足够了,因为机器学习函数的输入接受特征作为稀疏向量。然而,让我们想想我们现在所拥有的。对于每个“页面”分类值,我们在稀疏向量矩阵中有 1 和 0。

功能选择

我们希望获得一种客户参与度指标。当从用户的角度考虑这个问题时,我希望我的所有页面交互都有每日使用量以及每周和每月的平均值。此时,我不确定哪个分类值在预测客户流失方面最重要,所以我将保留所有分类值。

为了检查特定参与度指标的增长或下降是否会影响流失率,我们将在每日、7 天和 30 天平均值之间进行比较。

以下是我想要的功能列表:

最后,我们将在平台上添加终身职位作为附加功能。这是一个常用的用户参与度指标。

为了获得每日、每周和每月的指标,我需要将“ts”转换为日期,并对每个功能使用某种窗口功能。

使用行提取器获取每个稀疏事件项的各个列:

日期操作:从“ts”到天数

创建每日数据框

这将为我们提供日常指标:

创建衍生指标

现在来点好玩的。我发现了一种很好的方法来遍历这个每日数据集,以获得 7d 和 30d 的平均值,并导出几个度量对的方差度量。听起来很复杂。但我预计,如果你每天听的歌曲明显低于你的 7d 平均水平,你就会变得无所事事,因此更有可能取消。

达到平均值:

获取差异指标:

在平台上添加任期

最后,我创建了一个任期指标,如下所示:

检查您的空值

我们现在已经做了许多计算。存在一种风险,即它们并不都产生值(例如除以 0)。使用这个堆栈溢出答案检查每列的空值。

这告诉我,我肯定需要填充我的数据框架:

矢量装配器

在继续之前,对于 PySpark ML 中的建模,我们需要将所有单独的度量组合回一个 SparseVector 中。我们可以使用向量组装器:

秘方是过采样

你曾经因为你的逻辑回归只预测你标签的大多数类别而沮丧过吗?

不是模特的错。它正确地预测了最可能的分类。

这是由数据集中的不平衡造成的。有许多方法可以处理不平衡的数据。特别是,如果您感兴趣的类非常小,过采样可以工作。

这是你的模型表现更好的秘方,通过训练更多的少数民族的例子。

我为万军的 Pyspark 找到了这个简洁的过采样方法:

最佳性能模型

我们测试了 3 种不同的模型:

  • 物流回收
  • 随机森林分类器
  • 梯度推进树分类器

首先,在 PySpark 中进行训练测试分割:

继续建模:

物流回归

结果:

随机森林分类器

结果越来越好:

梯度增强树分类器

结果:

GradientBoostingTree 分类器(CrossValidator)

这最后一个模型表现非常好。通过快速交叉验证,maxDepth=20 的结果甚至更好。由于性能问题,我无法运行完整的数据集。

以下是一小部分的结果:

基准模型分析

您可以在下面找到按型号划分的所有指标的摘要。maxDepth=20 的 GBT 明显胜出。

了解特征重要性

为了找出哪些特性是最重要的,我用下面的代码查看了我的 GBT 模型:

发现以下是预测客户流失的一些最重要的指标:

结论

在这篇文章中,我给了你一些预测客户流失的实用工具:

  1. 在我们的功能工程部门,我们创建了一个大的计算参与度指标集
  2. 我们给了你处理不平衡数据的秘密:过采样
  3. GradientBoostingTree 分类器在该数据集上表现出色

可能的改进

  1. 我处理向量的方式可能更优雅。我在努力从这些结构中获取信息。
  2. 此外,我可以使用主成分分析来降低特征维数,这将提高模型的整体执行速度。

编码时面临的困难

我在几个不同的领域遇到了困难:

  • AWS 集群的计算容量(自由层)。我想在 GBT 上运行的交叉验证无法在我的完整数据集上完成。我必须为我的特征工程的大部分定义函数,以便在较小的数据集上快速完成所有步骤
  • 超参数:由于性能问题,我一次只能测试有限数量的参数。即使在较小的数据集上
  • Datetime 计算:我花了很长时间才弄清楚如何处理 Pyspark 中的日期格式,以及随后如何添加 datatime 以得出任期指标。
  • BestModel:我花了很长时间才找到如何从 pipelin(或者 CV)选择 stages 来直接在模型上调用 BestModel 函数。
  • 载体:处理载体可能会令人困惑

我希望你喜欢这篇文章!

完整的 Github 库在这里:https://github.com/thijsessens/sparkify_churn_prediction

使用 Spark 进行客户流失预测

原文:https://towardsdatascience.com/churn-prediction-with-spark-e16d96bbf147?source=collection_archive---------45-----------------------

客户流失预测对于留住客户至关重要,也是成功的关键因素之一,因为它有助于企业在关键时刻主动向客户提供正确的优惠和折扣。

兰迪·法特在 Unsplash 上的照片

为了 Udacity 的数据科学家 Nanodegree 的顶点项目,我试图为虚构的音乐流媒体服务 Sparkify 建立一个机器学习管道来进行流失预测。我为这个项目写的代码可以在这个资源库中找到。

由 Udacity 提供的 Sparkify 虚构徽标

Sparkify 已经收集了一个关于其平台上成千上万独立用户活动的大型数据库。作为一项不断发展的服务,Sparkify 将在未来继续产生更多的数据(当然,前提是它已经存在)。在这种情况下,Spark 被证明是一个合适的工具,因为它提供了急需的可伸缩性。

问题陈述

Sparkify 提供的大型数据集(~12GB),包含用户活动的详细信息。具体来说,每一行代表一个用户活动,包括关于用户的基本信息(用户 ID、名字、姓氏、性别、他们的订阅级别、他们是否登录过……)和关于活动性质的进一步信息(例如,活动的时间戳、他们访问的页面的名称,或者他们请求的艺术家、歌曲和歌曲长度的名称)。每个唯一用户可以在数据集中记录多个活动。

给定数据集,主要任务是清理数据(如果必要的话),执行数据探索和分析,特征提取,最后,实现机器学习模型来对搅动的用户进行分类。理想情况下,当给定用户活动列表时,解决方案模型应该能够预测他们是否是搅动者(当然,不需要查看数据集中的取消事件)。

这些模型是根据它们的 F1 分数而不是准确性进行评估的,因为在这种情况下,与平台上的用户总数相比,被搅动的用户数量很少,并且数据是不平衡的。

设置

对于这个项目,我在 IBM Watson Studio 上使用了 Python 3.7Spark 3.0.1 ,它提供了 2 个执行器:1 个 vCPU 和 4 GB RAM,以及一个驱动程序:1 个 vCPU 和 4 GB RAM,采用 Lite 计划。由于硬件容量的原因,我只处理了原始数据集(大约 12GB)的一个子集(大约 200MB)。

数据探索

子数据集包含 543705 个观察值,每个观察值代表属于 448 个唯一用户之一的活动,以及 18 个特征。

数据模式—按作者分类的图像

页面列特别有趣,因为它包含记录的用户活动类型。

的独特价值—作者图片

请注意,该列中没有丢失数据,NextSong 是最受欢迎的活动,这是可以理解的,因为 Sparkify 是一种音乐流媒体服务。

然而升级降级的数量相对于提交升级提交降级取消取消确认的数量,甚至是唯一用户的数量,都是巨大的。因此,我们可能会猜测升级降级是用户可以选择升级或降级其订阅的页面,而不是这样做的实际事件。

清理数据集

下一步是清理数据集。查看每列中缺失数据的数量,有两组:

每列中缺失值的数量-按作者排序的图像

  1. 当且仅当页面类型为下一首歌曲时,艺术家长度歌曲不为空(包含一些值)。
  2. 名字姓氏性别地点注册用户代理在用户未登录或未注册时缺失。事实上, userId 在这种情况下也会丢失,但是丢失的值被伪装成空字符串。然而,这些用户无法访问 Sparkify 的主要功能,因此,我们可以安全地删除所有这些观察。

定义流失

接下来,我使用取消取消确认来定义客户流失。特别地,任何具有这些事件中的至少一个的用户被认为是被搅动的用户。我还检查了这些事件实际上是同时发生的,并且有 99 个用户,大约是数据集中用户总数的 22%

可视化数据

在清理数据集和定义客户流失后,我用一些图表来回答我认为对客户流失预测和用户行为至关重要的 4 个问题。

用户参与度和用户留存之间有什么关系?

每位用户的事件/互动总数-按作者分类的图片

我们可以看到,流失用户对服务的参与度略有下降。

在此分析中,时间戳有用吗?

作者图片

作者图片

绝对是的,用户群之间的上次交互和用户生存期明显不同。我们还可以注意到,长期用户对服务更忠诚。

免费用户会取消他们的服务吗?

作者图片

不幸的是,也是的。事实上,免费用户和付费用户的取消率大致相同。

关于流失,用户活动能告诉我们什么?

作者图片

一般来说,被取消的用户竖起大拇指的少,下一首少,加入播放列表少,竖起大拇指多,滚动广告多,降级多。我们可以看到,总的来说,这些用户并没有像以前那样喜欢这项服务。

注意:记住 降级 不是实际的账户降级事件,而可能是用户可以选择降级其账户的页面。

建模

功能选择

我按照用户 Id 对数据集进行分组,并选择了我认为最相关的 13 个特性:

  • 交互总数
  • 注册时间戳
  • 上次交互时间戳
  • 用户寿命
  • 一生中的平均相互作用
  • 等级(1 表示付费,0 表示免费)
  • 竖起大拇指的百分比
  • 拇指向下的百分比
  • 回家的百分比
  • next song 的百分比
  • 添加到播放列表的百分比
  • 滚动广告的百分比
  • 降级百分比

然后,产生的数据集被分成训练和测试数据集(分别为 90%和 10%)。

建造管道

在获得训练和测试数据集后,我为两种不同的分类方法建立了三个机器学习管道:逻辑回归和随机森林。每个管道执行三个主要任务:

  • 根据 PySpark 输入模式的要求,将所选要素组装成矢量。
  • 对矢量进行标准化(缩放平均值为 0,标准偏差为 1),将所有要素放在相似的尺度上。还有其他的缩放方法;然而,标准化对异常值是最稳健的。
  • 执行网格搜索并使用 F1 分数选择最佳超参数。

网格搜索中使用的超参数如下:

对于物流回收:

  • regParam: [0.01,0.1]

对于 RandomForestClassifier :

  • maxDepth(一棵树的最大深度) : [12,30]
  • numTrees(树的总数):【20,100】

结果

最佳逻辑回归模型能够在训练数据集上达到 F1 得分 0.868 ,并且在测试数据集(F1 得分 0.912,准确度 0.917)中正确预测 36 个用户中的 33 个,其中 regParam=0.01

有了一个 maxDepth 12 和 numTrees 100 的随机森林,我能够在 train 数据集上取得更好的结果(F1 得分= 0.887 )。该模型在测试数据集上产生了相同的预测(36 个中有 33 个正确,F1 值为 0.912,准确度为 0.917)。

两种方法在测试数据集上的预测结果—作者提供的图片

但是,测试数据集上的这种性能并不意味着随机森林模型不好。仅包含 36 个用户的测试数据集根本不够大,无法用于有效地比较不同的模型。

我认为,在这种情况下,随机森林比逻辑回归更好,因为它可以对一系列数据进行分组(例如,流失用户的寿命通常在 10 亿到 30 亿'时间单位')而逻辑回归只能根据与某个值(大于或小于该值)的比较对数据进行分类。为了用逻辑回归区分一系列数据,我们需要添加隐藏层,因此,使用深度学习。因此,我认为随机森林模型是一个更好的选择。

此外,随机森林的一个优点是,我们可以通过查看特性的重要性来了解每个特性对结果的影响:

作者图片

正如在上面的数据可视化部分中所猜测的,用户订阅级别贡献不大,而最后一次交互用户生命周期对模型的性能至关重要。因此,为了提高客户保持率,最简单和最有效的方法之一是针对最近不活跃的用户(上次互动的较低值)提供特殊优惠和折扣。这些折扣也可以在用户点击取消页面时提供。

可能的进一步改进

  • 使用 last interaction 可能不是最好的主意,因为我们可能想知道谁不喜欢 Sparkify,甚至在他们想取消之前。相反,我们可以把目标人群锁定在约会少、否决、滚动广告多、访问降级页面更频繁的人群。
  • 在这个项目中,我没有使用用户听过的艺人歌曲,或者用户的地点性别。这些特性可能对更好的模型有用。

结论

总之,我通过可视化和分析探索了数据集。我还清理、转换了数据,提取了 Sparkify 上关于用户的相关特征。根据这些特征,我使用逻辑回归和随机森林建立了不同的机器学习管道,并比较了结果。最佳随机森林模型在训练数据集上达到了 0.887 的 F1 分数,并且在测试数据集中对 36 个用户中的 33 个进行了正确分类。

通过这个项目,我学会了 Spark,并能够将我的知识应用到实际问题中。我还以一个漂亮的顶点项目结束了我与 Udacity 上的数据科学家 Nanodegree 的旅程。

带有 Azure DevOps 和的 Lambda 函数的 CI/CD。网络核心

原文:https://towardsdatascience.com/ci-cd-for-lambda-functions-with-azure-devops-and-net-core-9131b36582c0?source=collection_archive---------19-----------------------

卡尔·海尔达尔在 Unsplash 上拍摄的照片

自 AWS Lambda 功能首次发布(2014 年 11 月)以来,我们一直在挑战自己,以不同的方式思考开发。

随着时间的推移,无服务器模式越来越多地出现在具有新资源、工具和方法的软件开发中。

然而,如果没有控制,我们很容易制造一场噩梦。就像本叔叔说的:“权力越大,责任越大”。

帮助我们完成这一“责任”的方法之一是为 Lambda 函数建立 CI/CD 管道,并提取完整 ALM 的全部好处。

在这篇文章中所有这些观点的激励下,我们将创建一个管道来部署我们的 Lambda 函数。

所以,我们开始吧!😄

要求

  • Azure DevOps 帐户
  • AWS 帐户
  • C#的基础知识

AWS 帐户

我们需要创建一个编程访问用户,负责连接 AWS 和 Azure DevOps 账户。

对于测试且仅对于测试,您可以为您的用户设置此权限:

绝不、绝不、绝不授予生产中的所有访问权限。在安全性方面,越少越好:)

通过我们的 AWS 编程用户、访问密钥和秘密密钥,我们可以创建 Azure DevOps 项目。

Azure DevOps 管道

我最喜欢的 Azure DevOps 特性之一是管道。我是这种资源的忠实粉丝,因为它非常容易使用,必要时可以用来处理巨大而复杂的场景。

首先,我们将连接两个帐户:

Azure DevOps 的 AWS 工具包

这个工具包对于创建服务连接和启用我们将在管道作业中使用的 LambdaDeployFunction 任务是必要的。

您可以通过此链接安装工具

在我们的帐户上安装了工具包后,我们可以进入下一步。

将 AWS 帐户连接到 Azure DevOps

Azure Devops —项目主页

并创建服务帐户:

Azure DevOps —服务连接

AWS 服务连接:

Azure DevOps —服务连接

用您的 AWS 凭据填充它,并添加一个名称:

Azure DevOps —服务连接

Azure DevOps 变量组

对于这个例子,一个变量组是必要的,因为我们将使用它来存储 Lambda 函数 ARN,这个链接包含创建和配置该组所需的所有信息。

厉害!现在,我们已经在 AWS 帐户中连接了 Azure DevOps 项目。让我们最终看到一点代码:D

。网络核心

您可以从这里克隆完整的源代码:

git clone [https://github.com/lbazetto/dotnet-core-aws-lambda-ci-cd-pipeline-azuredevops.git](https://github.com/lbazetto/dotnet-core-aws-lambda-ci-cd-pipeline-azuredevops.git)

由于该项目基于。Net Lambda Tools ,我们保留了推荐的文件夹结构:

.
├── awsLambdaCICDPipeline.sln
├── azure-pipelines.yml
├── src
│   └── awsLambdaCICDPipeline
│       ├── Function.cs
│       └── awsLambdaCICDPipeline.csproj
└── test
    └── awsLambdaCICDPipeline.Tests
        ├── FunctionTest.cs
        └── awsLambdaCICDPipeline.Tests.csproj

src 文件夹包含 Lambda 函数,而 test 文件夹包含单元测试。

因为这个想法关注的是进程而不是 Lambda 函数本身,所以代码非常简单,它只是接收一个字符串并执行一个 ToUpper。在单元测试中,它只是模拟上下文并调用函数:

多级管道 YAML

一切都整理好了,是时候检查本教程最重要的部分,管道。我们的渠道分为两个阶段:

Azure DevOps —多级管道

构建阶段

这个阶段负责构建、运行单元测试,并将工件发布到 Azure DevOps。

部署阶段

该阶段部署在第一阶段创建的 Lambda 函数。

为什么我们有两个阶段?

将我们的构建定义分成几个阶段使它更加灵活,并帮助我们为每种情况创建一些特定的规则。在这个场景中,我们可以在创建拉请求或完成拉请求时运行相同的定义。

YAML 的定义:

创建 Azure DevOps 管道

现在是创建管道的时候了:

Azure DevOps —管道视图

选择代码位置:

Azure DevOps —源代码位置

根据您的代码位置,您可能需要输入一些凭据。

我们现在可以看到 YAML 的定义了:

azure devo PS-YAML 管道

只要保存它,您就可以在您的回购中看到管道。
重要提示:如果你的代码在 Github 上,会自动创建一个 pull 请求验证。如果没有,您可以通过分支策略进行设置。

一起测试

我们现在有:

  • 链接到 AzureDevOps 的 AWS 帐户
  • 带有λ函数和 YAML 定义的源代码

拉请求管道

当一个拉动被创建时,我们可以在 Github 上看到检查。

如果您单击 pipeline details,可能会注意到部署阶段已被跳过。

GitHub 管道检查和 Azure DevOps 多阶段

主管道

一旦管道完成,代码被合并到 master,我们就可以看到两个阶段都已运行:

Azure DevOps —管道阶段

λ函数

最后,我们可以看到从 Azure DevOps 部署的 Lambda 函数:

亚马逊 AWS Lambda 执行

就是这样!

你怎么想?你有没有用另一种方式做一些事情,或者你认为我可以改进?请告诉我:)

非常感谢您的宝贵时间!

最初发布于https://devandops . cloud/ci-CD-for-lambda-functions-with-azure-devo PS-and-net-core/

在 AWS 上构建 CICD 管道

原文:https://towardsdatascience.com/ci-cd-logical-and-practical-approach-to-build-four-step-pipeline-on-aws-3f54183068ec?source=collection_archive---------18-----------------------

DevOps — AWS CI/CD

在 20 分钟内建立一个无服务器的全自动 CICD 管道。

在本文中,我们将使用 AWS 原生工具构建一个 4 步 CI/CD 管道。为了从概念上理解 CI/CD 渠道,强烈建议重温以前的文章&持续集成【持续交付——神话、陷阱和,实用方法

AWS 上的四步 CI/CD 管道

在这篇文章中,我们将集体讨论选择构建 CI/CD 渠道的工具背后的思维过程和推理。在 AWS 平台上,我们将构建一个托管在 EC2 服务器上的简单 web 应用程序,并使用所有 AWS 本地服务。简要介绍为 CI/CD 实施选择正确工具的重要性:

安全性 —任何实施的第一步都应该是安全性。总的来说,应用程序架构、硬件、网络和数据应该有助于构建安全的环境。

还记得臭名昭著的优步事件吗?黑客获得了嵌入 GitHub 软件库中的 AWS 证书,窃取了 5700 万用户和 60 万名司机的个人信息。

需要注意的一点是,每一层的安全性都很重要。

架构 —架构应该允许多个并发的实现。同时,它应该允许对应用程序进行严格的测试,以确保一次成功(FTR)。微服务架构最适合实现这些目标;然而,不同的应用程序可能有不同的适用架构,如面向服务的架构(SOA)和 Lambda 架构。最终,重点应该是实现目标。

我们将使用以下服务建立 CI/CD 管道-

源代码管理存储库: AWS 代码提交

构建: AWS 代码构建

部署: AWS 代码部署

通知: AWS SNS

托管网络服务器: EC2 AMI

CI/CD 管道: AWS 代码管道

阶段 1:源代码控制库——AWS 代码提交

AWS 代码提交是无服务器的。默认情况下,静态数据是加密的,并且为传输中的数据启用了 SSH 或 HTTPS 端点。它提供数据持久性、数据可用性、自动扩展,并且更重要的数据存储在远离计算资源的地方。同时也相当便宜。

AWS 代码提交流程

我们将在 AWS 上设置代码库,将代码从本地机器推送到代码提交库。在整篇文章中,我们将使用 AWS 地区作为所有服务的 us-east-1 (N. Virginia)。

  1. 创建存储库- 登录 AWS 管理控制台,搜索代码提交。在主页上,单击“创建存储库”。填写以下详细信息,然后单击“创建”

我们可以使用 CodeCommit 控制台、AWS CLI 或 GIT 客户端将代码推送到 CodeCommit。在本文中,我们将使用 GIT bash。如果还没有安装 GIT 客户端,请按照官方网站给出的说明进行安装。

2。克隆存储库——在 AWS 控制台中,选择页面右上角的克隆 URL,然后选择克隆 HTTPS。克隆 GIT 存储库的地址被复制到剪贴板。打开 GIT bash,键入命令 GIT clone,后面跟着前面复制的 URL。这是第一次,它将提示输入通过 GIT 连接到 AWS 的凭证。

3。将代码推送到库— 点击此处或按照截图从我的 Github 库中下载示例代码。将代码放在文件夹 DemoCICD 中。作为最佳实践,我们应该创建一个分支并将代码合并到分支,但是为了使本文简单,我们现在将代码合并到主节点。切换到当前目录,使用下面的命令添加新文件。切换到当前目录,使用下面的命令添加新文件。

添加新文件后,使用下面的命令提交更改

现在使用下面的命令将文件推送到 AWS CodeCommit 存储库

检查 AWS 中的存储库,应复制所有文件。Appspec.yml 包含 CodeDeploy 的设置。Buildspec.yml 包含代码构建的设置

AWS 代码提交存储库

构建的先决条件:

EC2 实例托管应用程序并部署代码部署代理- 我们将启动 EC2 Linux 实例来托管 web 应用程序。然后我们将部署 codedeploy 代理,以便将构建工件部署到机器上。在启动实例之前,让我们创建一个 IAM 角色来分配正确的访问权限。

实例角色

1.点击此处的打开 IAM 控制台

2.从控制台仪表板中,选择角色,然后选择创建角色。

3.在“选择受信任实体的类型”下,选择 AWS 服务。在选择用例下,选择 EC2,然后选择下一步-权限。

4.搜索并选择名为 AmazonEC2RoleforAWSCodeDeploy 的策略,然后选择 Next- Tags。

5.选择下一步:复习。输入角色的名称(例如,DemoCICDEC2InstanceRole),然后选择“创建角色”。

启动 EC2 实例:

1.点击这里打开亚马逊 EC2 控制台

2.从控制台仪表板中,选择启动实例

3.在步骤 1:选择一个 Amazon 机器映像(AMI),找到 Amazon Linux 2 AMI (HVM),SSD 卷类型,然后选择 Select。

4.在“步骤 2:选择实例类型”页面上,选择 t2.micro 类型(符合自由层条件),然后选择下一步-配置实例详细信息。

5.在“步骤 3:配置实例详细信息”页面上,执行以下操作:

在自动分配公共 IP 中,选择启用。

在 IAM 角色中,选择您在前面的过程中创建的 IAM 角色(例如,DemoCICDEC2InstanceRole)。

6.展开高级详细信息,并在用户数据字段中输入将在启动安装时执行的以下脚本。

7.点击添加存储->点击添加标签->创建一个标签,其关键字为“目的”,值为 DemoCICD”。我们将使用这些标记来标识 EC2 实例以进行部署。->配置安全组

8.在“配置安全组”下,选择分配安全组:“创建新的安全组”。安全组名称为“SG-EC2-CICD”。添加 SSH(通过 putty 访问实例)和 HTTP(访问 web 应用程序)类型的端口,并在 source 中选择“My IP”。点击“查看并启动”。下载密钥文件,然后按“启动”。

构建包— AWS 代码构建

AWS service CodeBuild 是一个完全托管的服务,它编译代码、运行测试并创建一个可以随时部署的软件包。选择这项服务的原因是

无服务器 —您不需要管理构建服务器。

可伸缩性 —它自动伸缩,可以同时处理多个构建。

经济高效的 — CodeBuild 基于“按需付费”模式,这意味着构建一个包需要按分钟付费。

安全— 构建工件使用由 AWS KMS 管理的客户专用密钥进行加密。此外,可以使用 AWS IAM 提供细粒度的访问。记住提供最低特权访问。

下一步是从 CodeCommit 中的代码构建一个包。

AWS 代码构建流程

构建项目:

在这一步中,我们将创建一个构建项目,AWS CodeBuild 将使用它来运行构建。登录 AWS 管理控制台并搜索 CodeBuild 或点击此处。选择同一个 AWS 地区(N. Virginia)。单击“创建构建”并填写以下详细信息:

项目名称: BuildCICD。根据最佳实践填写描述并创建标签。

源下:源提供者— AWS 代码提交,存储库— DemoCICD,引用类型—分支,分支主

在环境下—选择托管映像,操作系统为 Amazon Linux 2,运行时—标准,映像—Amazon Linux 2–86 _ 64—标准:1.0(或适合您的使用情形),服务角色—新服务角色

在 Buildspec 下——选择一个 buildspec 文件(我们将很快对此进行讨论)

保持其他一切不变,然后单击 create build project

build spec—build spec 是 codeBuild 服务用来运行构建的命令和相关设置的集合。您可以将 buildspec.yml 文件作为源代码的一部分,或者在构建项目时输入构建命令。我们已经在代码库中上传了 buildspec.yml 文件。

它可以有不同的阶段,如安装、预构建、构建和后构建。

使用 AWS 代码部署的部署

CodeDeploy 是一个完全托管的服务,用于完全自动化软件部署。它可用于将代码部署到 AWS EC2 或本地服务器、AWS Fargate 和 AWS Lambda。优点是

完全托管服务: CodeDeploy 可随您的基础设施自动扩展,这意味着除了您正在部署的基础设施(如 EC2)之外,无需管理任何其他基础设施。CodeDeploy 可以与自动扩展组集成,以自动扩展 EC2 容量。

蓝/绿展开:该选项对应蓝/绿展开。应用程序的新版本与旧版本一起启动。一旦新版本经过测试并宣布就绪,CodeDeploy 就可以根据您的规范将流量从您以前的版本转移到您的新版本。

集中控制— CodeDeploy 允许您轻松启动和跟踪部署状态。它提供了详细的部署报告,您可以为更新配置推送通知。

定价— 通过 CodeDeploy 部署到 EC2 或 AWS Lambda 是免费的。对于其余的部署,它非常便宜。

在代码部署中,我们将创建一个包含要部署的软件应用程序的应用程序。我们将创建 CodeDeploy 包并将其安装到 EC2 实例中。

AWS 代码部署流程

CodeDeploy 角色:在 IAM 控制台中,通过单击“选择受信任实体的类型”下的创建角色- > 来创建角色,在“选择用例”下选择 AWS 服务- >,选择“CodeDeploy - >选择“下一步:权限”AWSCodeDeployRole 托管策略已附加到角色- >选择“下一步:标记- >下一步:审阅- >输入角色的名称(CodeDeploy) - >创建角色。

在代码部署中创建应用程序

1.单击此处的打开 CodeDeploy 控制台

2.如果“应用程序”页面没有出现,请在“AWS 代码部署”菜单上选择“应用程序”。

3.选择创建应用程序。在应用程序名称中,输入 CICDDemoApplication。

4.在计算平台中,选择 EC2/内部部署。

5.选择创建应用程序。

部署组— 在部署组中,我们将定义与部署相关的设置。在显示应用程序的页面上,选择“创建部署组”。

  1. 在部署组名称中,输入 DemoCICDDeploy。
  2. 在“服务角色”中,选择您之前创建的服务角色(例如,CodeDeploy)。
  3. 在“部署类型”下,选择“就地”。
  4. 在环境配置下,选择 Amazon EC2 实例。在“关键字”字段中,输入用于标记实例的名称(例如,MyCodePipelineDemo)。
  5. 在部署配置下,选择 CodeDeployDefault.OneAtaTime。
  6. 在“负载平衡器”下,清除“启用负载平衡”。对于本文,您不需要设置负载平衡器或选择目标组。
  7. 选择创建部署组。

至此,我们已经完成了构建管道所需的所有服务的配置。现在,我们将使用上面创建的服务构建一个即插即用的 CI/CD 管道。

CI/CD 管道

四步 AWS CI/CD 管道

AWS 代码管道是一个完全托管的无服务器服务,有助于自动化整个软件交付版本。这是一个管道,我们可以在其中以任何顺序和任何次数调用所有其他服务,如代码构建、代码提交、手动批准、测试和部署等。它之所以适合,是因为它完全不需要服务器,采用随用随付的方式,成本模型完全安全且可配置的工作流,并且支持一个位置监控和快速软件交付。

1.登录 AWS 管理控制台,点击这里打开代码管道控制台

2.选择创建管道。将管道名称命名为“DemoCICD”。按如下所述填写详细信息:

源阶段

构建阶段-

提供作为 AWS 代码构建的构建提供程序,并按如下所述填写详细信息,然后单击下一步。

部署阶段

选择 deploy provider as CodeDeploy,并像下面这样填写其余的详细信息。

单击下一步并查看更改。如果一切正常,那么点击创建管道。这将首次启动管道。如果一切都设置正确,它应该会成功。现在,这是持续部署。如果您提交任何更改,管道将自动触发。因为我们已经创建了一个 web 服务器,所以您可以尝试使用 EC2 实例公共 IP 访问网站。

产品升级和技术支持服务-手动批准:

让我们创建一个新步骤来添加手动批准。为此,请单击管道页面上的编辑。我们将在构建阶段后添加批准。为此,在构建阶段后单击+添加阶段。命名为“生产-签署”。在“生产-签署”下,单击“添加行动组”。我已经创建了一个 SNS 主题来发送电子邮件给我审批。

单击完成。这样,我们成功地添加了一个手动批准阶段。为了自动触发完整的管道,我们只需在本地修改 index.html,然后进行代码提交。我已经添加了一个重定向到我在 index.html 的媒体简介。这将自动启动管道。你的收件箱里一定有一封批准它的邮件。一旦完成应用程序将被部署,你可以使用 EC2 实例公共地址访问网站。

部署前的电子邮件批准

结论:

我们已经成功建立了一个 4 步 CI/CD 管道。记住舞台布置应该仔细考虑。如果你喜欢这篇文章,请告诉我,并关注我的下一篇文章。

免责声明——本文中的观点仅代表作者个人,并不代表作者所属任何组织的观点。

通过 Azure DevOps 为数据科学项目提供 CI/CD 管道。

原文:https://towardsdatascience.com/ci-cd-pipeline-with-azure-devops-for-data-science-project-f263586c266e?source=collection_archive---------18-----------------------

CI/CD 管道实施,或数据科学的持续集成/持续部署。

在本文中,我将展示如何使用 Azure DevOps 为机器学习项目构建持续集成和持续交付管道。

CI/CD 管道

首先,我们来定义一下 CI/CD。正如 Wiki 所说,“CI/CD 通过在应用程序的构建、测试和部署中实施自动化,在开发和运营活动以及团队之间架起了一座桥梁。现代的 DevOps 实践涉及软件应用程序在其整个开发生命周期中的持续开发、持续测试、持续集成、持续部署和持续监控。 CI/CD 实践或 CI/CD 管道构成了现代开发运营的支柱。”

好,让我们分别找出 CI 和 CD。

持续集成 是一种编码哲学和一套实践,驱动开发团队实现小的变更,并频繁地将代码签入版本控制库。因为大多数现代应用程序需要在不同的平台和工具上开发代码,所以团队需要一种机制来集成和验证它的更改。

连续交货 在连续积分结束的地方拾取。CD 自动向选定的基础架构环境交付应用程序。大多数团队使用除生产环境之外的多种环境,例如开发和测试环境,CD 确保有一种自动的方式将代码变更推给他们。

那么,它为什么重要呢?机器学习应用程序在我们的行业中变得越来越流行,但是,与更传统的软件(如 web 服务或移动应用程序)相比,开发、部署和持续改进它们的过程更加复杂。

好,让我们试着为我的项目建立一个简单的管道。该项目是关于以下 Azure 服务的预测分析:Azure SQL,Azure 数据工厂,Azure 存储帐户 V2,Azure 数据砖。

解决方案架构

这个解决方案包括三个步骤。第一步—运行 data ADF 数据流以从 SQL DB 获取数据,转换并从表中选择几个列格式,然后将这些结果保存到 Azure Data Lake 中的 Stage 文件夹。第二步—使用关于存储帐户的指定参数从 ADF 运行 Azure Databriks notebook,以准备历史数据集并运行训练模型。在这一步,我们可以使用 MLflow rack 实验来记录和比较参数和结果。最后一步——从 ADF 运行 Azure Databriks notebook,并使用关于存储帐户的指定参数对我们的模型进行评分,并将结果保存到 Azure Data Lake。

为了启动这个项目,我需要在 Azure 门户网站中创建 3 个资源组。这些资源组将负责不同的环境—开发、试运行和生产。在这些环境中,我创建了以下服务——Azure SQL、Azure Data Factory、Azure 存储帐户 V2、Azure Data Bricks 和 Azure Key Vault。

Azure 资源组和服务

在所有 Azure SQL 中,我上传了两个表——历史数据和分数数据。这个数据的描述你可以通过这个 链接 找到。在 Azure 存储帐户中,我创建了一个包含三个文件夹的容器——RawData、PreprocData 和 Results。下一步是在 Azure 密钥库中创建秘密。我需要一个 Azure 存储帐户的秘密,在那里我为我的 Azure SQL DB 使用了访问密钥和连接字符串。重要的是,要从 Azure Data Factory 访问您的秘密,您需要在 Azure 存储帐户的访问策略中进行一些配置

访问策略配置

正如你所看到的,我添加了一个带有适当的 Azure 数据工厂服务和 Azure 数据块的访问策略,这是我早期创建的,允许获取一个秘密。

下一步是配置 Azure 数据块。为了引用 Azure Key Vault 中存储的秘密,我创建了一个由 Azure Key Vault 支持的秘密范围。要创建它,请转到https://<databricks-instance>#secrets/createScope。此 URL 区分大小写;createScope中的作用域必须大写,并填写下表:

创建 Azure 密钥库支持的秘密范围

Azure Databricks 配置的下一步是—将我的笔记本连接到 Azure DevOps 存储库。要做到这一点,只需打开你的笔记本,按下同步,并填写关于你的 Azure DevOps 存储库的信息表单。这样,您可以将笔记本中的更新提交到存储库中。

Azure Databricks 笔记本连接到 Azure DevOps 存储库。

Azure 服务的基本配置已经完成,让我们开始在 Azure 数据工厂中创建管道。第一步是将 ADF 连接到 Azure DevOps 存储库。我可以通过两种方式连接它——在服务创建期间和在 ADF 配置中。我只需要为开发环境配置这个连接。

Azure 数据工厂连接到 Azure DevOps 存储库。

好了,现在我们可以选择我们想要发展管道的分支。下一步——创建所有 Azure 服务的链接服务。

列表链接的服务

为了创建 Azure Databricks 链接服务,我填写了下一个表单:

Azure Databricks 链接服务配置

为了创建 Azure SQL DB 链接服务,我填写了下一个表单:

Azure SQL 链接服务配置

为了创建 Azure 存储帐户关联服务,我填写了下一个表单:

Azure 存储帐户链接服务配置

为了创建 Azure Key Vault 链接服务,我填写了下一个表单:

为了创建 Azure Key Vault 链接服务,我填写了下一个表单:

为了控制不同环境之间的链接服务名称,我在 ADF 中使用了全局参数,创建了三个参数— dev、stg、prd。

让我们创建一个管道:

ADF 管道

我的管道的第一步是数据流:

ADF 数据流

在这个数据流中,我从 Azure SQL DB 获取数据,转换数据格式,从表中选择一些列,并将结果上传到 Azure Data Lake 的适当文件夹中。此流程是为历史记录和分数(新数据)表创建的。

管道的下一步是运行 data_preparation_model_train 和 score_new_data 脚本。为此,我们需要:

  1. 选择合适的链接服务
  2. 选择笔记本的目的地
  3. 添加带有存储名称的参数

配置 Azure Databricks 笔记本从 ADF 运行

与 score_new_data 脚本相同。

这是我的 ADF 管道的所有阶段,接下来的步骤是验证,创建 pull 请求以将我的分支与 master 连接,然后将所有更新从 ADF 发布到 master 分支。结果是:

Azure DevOps 存储库结构

让我们开始在 Azure DevOps 中配置 CI/CD。

第一步——创建新的发布管道(在 Azure DevOps 门户中,导航至“管道”->“发布”并点击新管道)

创建新的发布渠道(步骤 1)

选择显示各种预配置模板的模板窗口。在数据工厂的情况下,选择是创建一个空作业,并将其命名为ADF-devo PS 2020-CICD:

创建新的发布渠道(步骤 2)

创建一个新的阶段“登台”(测试环境):

空白释放管道

现在我们已经创建了一个空白的发布管道。下一步是创建任务将使用的变量组和变量。为此,我们需要导航到 Pipelines -> Library 并创建一个新的变量组。在新表单中填写下一个信息,然后克隆它,为生产阶段创建相同的信息。

变量组创建

结果,我得到了两个变量组。稍后我将被映射到相应的阶段。

下一步—创建发布管道变量。由于变量组值的继承,变量将包含与环境无关的值。因此,变量值将被调整到使用它的阶段。为了创建它,返回到管道- >释放,然后打开标签变量。我创建了下一个变量:

管道变量

是时候创建和配置开发阶段了。

配置开发阶段。

这些行动将创造一个发展阶段。每次我们更新我们的master分支时,它都会触发持续交付管道,将更新后的 ARM 模板交付给其他环境,如试运行和生产。我们还可以自动完成创建触发器的过程:

连续部署触发器

现在是时候配置试运行或测试阶段了。是时候为这个阶段创建几个任务了。对于我的第一个管道,我创建了两个工作——在 Azure Data Factory 中部署管道和将 Python 笔记本复制到 Azure Databricks。

测试阶段的工作

让我们更详细地了解任务臂模板部署。我想描述的主要内容是-

  • 在资源组字段中填入一个变量:$(resourceGroup)
  • 选择模板位置:“链接工件”
  • 选择 ARM 模板和模板参数文件

ARM 模板和模板参数文件位置

  • 用先前创建的变量覆盖默认模板参数

模板参数

在结果中,我们得到了下一种形式:

部署 ADF 任务

我的下一个任务是部署笔记本电脑。让我们更详细地了解一下。我们需要填充:

  1. 我要将 Azure Databricks 中的笔记本复制到的文件夹。app id,我之前创建的。(如何创建— 链接 )。)
  2. 相同的应用程序 id
  3. 订阅 id
  4. 租户 id

复制数据块笔记本任务

因此,我在这个阶段有两个任务:

我还需要制作阶段。点击克隆暂存环境到生产:

克隆测试阶段

生产阶段是通过克隆一个阶段创建的,没有额外的调整或添加。这是因为底层作业是由变量配置的,这些变量包含指向所有外部引用的指针,如资源组、密钥库、存储帐户。此外,对于此阶段,建议创建“预部署”批准。因此,当分段部署结束时,执行流将等待分配的批准者的操作。我可以通过电子邮件通知或使用 DevOps 门户 UI 直接做出反应。

配置“预部署”批准

所有配置的最后一步是将变量组映射到阶段。这一步对于将特定于阶段的变量值映射到特定阶段是必要的。例如,如果流水线在生产阶段处理作业,则变量$(环境)具有值“prd ”,并且如果作业在暂存阶段被触发,则将该值设置为“stg”。要使它打开标签变量->变量组并点击“链接变量组”。将变量组“生产”映射到阶段“生产”,并选择范围“阶段生产”而不是“发布”,然后对“阶段”重复相同的操作。

将变量组映射到阶段

是时候运行并检查这个简单的管道了。

创建并运行发布

结果,我在 Stage and Production Resource 组的适当服务上找到了 ADF pipeline 和 Azure Databricks 笔记本。我还可以分析每个阶段所有任务的细节,例如:

在测试阶段分析部署 ADG 任务

为了使这个管道更加完整,我还可以在测试阶段添加一些测试任务。例如,这些测试可以运行 ADF 管道并分析其结果 Azure Data Lake 中的一个又一个副本表、MLflow 日志以及得分后表中的结果。通过所有这些测试后,我们可以批准生产阶段。

在这个故事中,我将一步一步地详细说明如何创建和配置发布管道,以在 Azure 数据工厂环境中实现 CI/CD 实践。它显示了 Azure DevOps、Azure Data Factory、Azure SQL DB、Azure Data Lake 和 Azure Databricks 在一起使用时可能带来的限制和可能性。

感谢阅读。

有用的链接:

圆形线段:2D 的多维数据

原文:https://towardsdatascience.com/circle-segments-high-dimensional-data-on-2d-de67380db55f?source=collection_archive---------52-----------------------

数据可视化

用 python 中的“matplotlib”实现高维数据的圆段数据可视化

雷内·伯默的照片

可视化数据有助于更好地理解探索性数据分析。数据的频率、相关性和比例很容易解释。这些统计数据在决定机器学习方法时也起着重要的作用。尤其是理解变量之间的关系。因此,散点图是了解特定位置上一个或多个变量的分布或关系的最常用技术之一。散点图的挑战是可视化高维数据。人类可理解的维度最多只能是 x、y 和 z 三个。这意味着我们只能在同一个图中将三个变量可视化为点。此外,解释 3D 图比 2D 图更难。因此,我们可以尝试将颜色、形状和大小作为其他维度添加到 2D 图中。然而,这个问题的另一个解决方案是散点图矩阵。散点图矩阵是一种用每对变量创建 2D 散点图并在矩阵结构上显示它们的方法。由于这一点,我们可以在同一视图中看到所有散点图。

还有另一种在 2D 上可视化高维数据的选择,称为“圆段,由 Ankerst,m .等人在 2001 年提出[1]。在这篇文章中,我将解释;什么是圆段可视化,如何在 matplotlib 上应用。我们将看到以下部分:

  • 什么是圆段可视化
  • 圆分段算法如何工作
  • “matplotlib”在圆线段中的应用

什么是圆段可视化

众所周知,颜色是可视化的主要组成部分之一。它可用于可视化另一个维度的数据,而无需向绘图添加任何轴。圆段可视化技术主要依赖于颜色。它基本上将圆分割成变量(维度)的数量。从第一次观察到最后一次观察,每个切片都将变量值表示为像素。算法根据观察值给每个像素分配颜色。比如说;我们将变量的最高值设置为蓝色,最低值设置为红色。假设 X 变量的值从第一次观察到最后一次观察增加,Y 变量的值从第一次观察到最后一次观察减少。因此,片 X 中像素的颜色将从蓝色开始,并在片的末端变成红色,而片 Y 中的颜色将从红色开始,并在末端变成蓝色。另外,我们可以添加更多的切片(变量)并在 2D 图上进行比较。

我们将在本文中创建一个圆形部分可视化输出的例子(作者可视化)

圆分段算法如何工作

圆形片段可视化技术处理停留在切片下的像素。因此,如果有更多的观察,视觉将有更多的像素。变量切片下的像素根据该变量的值进行处理。但是,定义显示像素着色的方向也很重要。在比较不同的切片时,方向起着重要的作用。

圆段着色方案(由 Ankerst,m .等人于 2001 年创建[1])

上图显示了如何用圆形线段技术给像素着色。第一次观察从圆心开始,最后一次观察在圆的边界结束。这种方法已在研究中提出[1]。但是,当有太多的数据点时,可能很难跟踪每个像素来了解变量之间的相关性。因此,在另一项研究[2]中,切片边界之间的线条被着色,而不是像素。这种方法在切片边界之间画线,并根据值给它们着色。在本文中,我们将按照第二种方法创建圆段可视化。

“matplotlib”在圆线段中的应用

matplotlib ”中没有任何自动创建圆段可视化的方法。因此,我们将在本节中从头开始创建一个关于“ matplotlib 的算法。开始之前,请确保您的系统中安装了“ matplotlib ”。我们将使用 葡萄酒质量 数据集,您也可以从 Kaggle 下载。

如前所述,我们将在切片边界之间绘制线条,而不是像素。这种方法更容易理解。因此,我们需要定义在可视化中将使用多少个变量,以便决定在圆中有多少个切片。为此,我们需要完成以下步骤:

  • 导入所需的包
  • 读取数据文件并删除丢失的值
  • 选择将在可视化上显示的变量
  • 获取观察值和变量的数量
  • 获取变量名(为了显示附近的切片)

完成这一步后,我们知道将使用多少个切片(#26 处的“var”)以及将在切片中绘制多少条平行线(#23 处的“r”)。现在,我们可以创建一个方法,在每个切片和坐标之间绘制直线,这些坐标在切片内彼此平行,以表示变量中的每个值。我们还可以找到变量名的坐标,以便显示哪个切片属于哪个变量。

“切片”方法采用两个参数作为“ num 和“半径”。“ num 代表一个圆将有多少个切片,“半径代表将画多少条线。因此,“半径”将等于观测值的数量,“ num 将等于变量的数量。该方法返回 3 个数组,分别为“”、“”和“标签点”。“点”是将在切片之间绘制的线的坐标,“线”是每个切片中代表每个值的线的坐标,“ labelPoints ”是用于定位变量名的坐标。

我们还需要再创建两个方法。其中一个用于计算变量的单个值应该使用哪种颜色,另一个用于通过使用第一种方法从变量创建 RGB 数据。这个过程也称为线性颜色插值。" matplotlib "有自己的颜色插值方法,但它不符合我们可视化算法的要求。这就是为什么,我们将从头开始创建它。

方法“ colorFader ”采用三种颜色作为十六进制格式。第一种颜色代表最低值,第二种代表中间值,第三种代表变量中的最高值。它的作用是取 0 到 1 之间的单个值,并将其转换为 RGB 代码。例如,如果一个变量的值为 1,那么 RGB 将等于最高值的颜色。如果它是 0.75,RGB 颜色将是混合中间色和最高色的颜色

方法“发生器”取四个自变量为“ df ”、“”、“”、“”。" df "是 Pandas 数据框,包括所有变量和其他自变量颜色代码(十六进制字符串类型),用于最低、中间和最高值。最重要的部分是,我们需要通过使用最小-最大归一化方法来归一化 0 和 1 之间的每个变量。因为“ colorFader ”将颜色分配给 0 到 1 之间的值。标准化后,它会转换数据框中的每个值,以获得它们的 RGB 代码。

好吧!现在,我们所有的方法都准备好创建圆段可视化。我们需要做的就是将这些方法应用于我们的数据,并通过使用“ matplotlib ”在极坐标系统上绘制/着色线条。您可以执行以下代码来创建绘图。

运行上面的代码后,您应该会看到下面的画面。根据数据大小,渲染视觉效果可能需要一些时间。蓝色代表最高值,绿色代表中间值,红色代表最低值。例如,挥发性酸度的值从最高值开始到中间值,而总二氧化硫的值从中间值开始到最高值。这意味着当挥发性酸度增加时,总二氧化硫减少。因此,我们可以说挥发性酸和总二氧化硫之间存在负相关关系。我们还可以通过详细考虑颜色模式来检查其他变量。你也可以添加更多的变量和改变颜色。

结论

在这篇文章中,我们学习了如何使用圆段可视化技术来可视化 2D 空间上的高维数据。我们讨论了什么是圆段可视化技术,它的算法是如何工作的,以及如何用" matplotlib "应用该算法。正如你从技术输出中看到的,通过使用颜色插值,我们可以很容易地比较不同的变量。虽然,技术允许我们增加数量变量。由于这一点,我们可以在同一个绘图中检查更多的变量。

如果你有任何问题,请随时提问。希望有帮助…

参考

[1]安克斯特,米哈伊尔&凯米,丹尼尔&克里格尔,汉斯-彼得。(1996).圆形线段:一种可视化探索大型多维数据集的技术。第一次出版。见:可视化' 96,热门话题会议,旧金山,加州,1996 年 11 月。

[2] 林春平,王绍林,谭国生,Navarro,Jain,2010,使用圆段可视化技术进行神经网络特征选择和分析,神经计算,73,第 613–621 页。

循环队列或环形缓冲区

原文:https://towardsdatascience.com/circular-queue-or-ring-buffer-92c7b0193326?source=collection_archive---------3-----------------------

Python 和 C 实现。

介绍

循环队列有许多不同的实现方式,它们都可能更适合特定的应用。这篇博文旨在帮助理解循环队列的工作原理及其用途和优点。

环形队列

队列是一种简单的数据结构,它实现了 FIFO(先进先出)排序。这仅仅意味着添加到队列中的第一个项目是第一个出来的。就像在熟食店排队一样,第一个排队的顾客是最先被服务的。一个循环队列本质上是一个具有最大大小或容量的队列,它将继续以循环运动的方式返回自身。

应用程序

当数据流的输入和输出以不同的速率发生时,环形缓冲区是常用的数据结构。

  • 缓冲数据流
  • 计算机控制的交通信号系统
  • 内存管理
  • CPU 调度

优势

循环队列提供了一种快速、干净的方式来存储最大大小的 FIFO 数据。

  • 不使用动态内存→没有内存泄漏
  • 节省内存,因为我们只存储我们的容量(相反,如果输入超过输出,队列可能会继续增长。)
  • 简单实施→易于信任和测试
  • 从不需要重新组织/复制数据
  • 所有操作都发生在常数时间 O(1)中

不足之处

循环队列只能存储预先确定的最大数量的元素。

  • 必须事先知道最大尺寸

它是如何工作的?(数组实现)

循环队列中有两个主要操作:

1: 入队(项目):将项目添加到队列中。

if Queue.isfull()
    print "Queue is Full"
else 
    increase tail by 1
    Queue[tail] = item
    size++

2: Dequeue() :返回行前(头)的项,并将其移除。

if Queue.isEmpty()
    print "Queue is Empty"
else 
    tmp = Queue[head]
    increase head by 1
    size--
    return tmp

注意 :我们实际上并没有从数组中移除任何东西,我们只是增加了 来指向下一个“in line”项目。

让我们看看这些操作在大小为 6 的数组上是如何进行的:

  • 请注意当我们将第七个项目(35)排队时,如何绕回零。
  • 注意是如何随着我们出列而增加的,但是没有值从数组中移除,它们只是在 Enqueue()到达数组中的那个位置时被覆盖。

模运算符

如果我们应该将数组中的增加 1 个点,那么当我们到达末尾时,如何将它设置回零,以确保我们继续遍历数组?

我们可以这样做:

if (head + 1) = capacity 
    head = 0
else 
    head = head + 1

这真的没有错,但是,有一个更好的方法使用模操作符。模运算符 (%) 给出除法后的余数。在看两个整数 ab 的关系时;a 将是 b 乘以某个整数 q 加上某个整数 r : 的乘积

a = b x q + r
    q : quotient = a div b
    r : remainder = a mod b

让我们看一些简单的例子:

a = b x q + r                    a % b = r
5 = 3 x 1 + 2                    5 % 3 = 2
2 = 5 x 0 + 2                    2 % 5 = 2
9 = 3 x 3 + 0                    9 % 3 = 0
9 = 2 X 4 + 1                    9 % 2 = 1

注:这是欧几里德算法确定 GCD 的基础。

让我们将它应用于我们的循环队列实现:

self.head = (self.head + 1) % self.capacity
  • 现在,每当我们到达数组的末尾时,我们将自动从零开始。漂亮!让我们看看大小为 6 的循环队列会是什么样子:
0 % 6 = 0
1 % 6 = 1
2 % 6 = 2
3 % 6 = 3
4 % 6 = 4
5 % 6 = 5
6 % 6 = 0
...

Python 实现

这是一个简单的实现,其中我们只有两个主要方法,Enqueue(item)、Dequeue()和 display()方法,我认为这有助于理解。许多其他实现也可能包括:

  • isFull():如果队列已满,则为 true,否则为 false。
  • isEmpty():如果队列为空,则为 true,否则为 false。
  • peek():查看队列最前面的内容,而不“删除”它。
  • 等等..

许多其他实现不会存储当前大小,而是通过简单地比较头部和尾部来确定 isFull()和 isEmpty()。我认为存储大小可以更容易地跟踪正在发生的事情。

实施情况

您可以看到 C 实现与 Python 实现非常相似,只是增加了有趣的 C 元素,如结构和内存分配。这里我们还需要一个 create_queue()函数,因为我们使用了 structs。我们还使用了一些我们之前讨论过的辅助函数,比如 isFull()、isEmpty()等..

思考者

  • 有哪些边界情况?
  • 我们在做什么假设?
  • 我们如何实现循环队列来动态改变容量呢?这将如何影响循环队列的优点和缺点?
  • 如果队列已满,这两种实现都不允许您将新项目加入队列。你能想到循环队列的一些应用程序中这可能是不好的吗?我们如何改变实现以允许重写?

结论

我鼓励阅读这篇文章的人看看 web 上的其他实现,比较它们,并思考循环队列的不同应用。我自己还是个学生,还有很多东西要学。然而,我希望这可能对第一次学习循环队列的人有所帮助。感谢阅读!

Python 中的分类和阈值处理

原文:https://towardsdatascience.com/clahe-and-thresholding-in-python-3bf690303e40?source=collection_archive---------5-----------------------

Python 中使用 OpenCV 的对比度受限的自适应直方图均衡化和阈值化

照片由菲利普·莱昂Unsplash 上拍摄

介绍

在本文中,我们来谈谈直方图均衡化和图像阈值。直方图均衡化是我们用于图像预处理的工具之一,它使图像阈值化或分割任务变得更容易。

我们需要直方图均衡化的原因是,当我们收集褪色的图像或低对比度的图像时,我们可以拉伸直方图以跨越整个范围。

让我们看一个例子,图像是用电子显微镜采集的。

测试图像

在上面的图像中,我们可以看到分离,但它并不清楚。因此,让我们看看直方图,并使用均衡来拉伸直方图,以设定阈值。

import cv2
import numpy as np
from matplotlib import pyplot as plt img = cv2.imread("test.jpg", 0)
equ = cv2.equalizeHist(img)

首先,我将我的图像读取为灰度,并将其赋给变量img。为了执行直方图均衡化,我们可以运行cv2.equalizeHist(img)

让我们看看测试图像的直方图。你可以看到它向右侧倾斜。

plt.hist(img.flat, bins=100, range=(0, 255))

均衡前

让我们看看均衡图像的直方图。你可以看到直方图一直延伸到 255。

plt.hist(equ.flat, bins=100, range=(0, 255))

均衡后

下面是直方图均衡化图像的结果,

均衡图像

正如你所看到的,上面的图像中有很多噪声,因为它考虑了图像的全局对比度,而不仅仅是局部对比度。因此,执行全局均衡可能无法很好地处理您的图像,在这种情况下,我们可以使用自适应直方图均衡或称为 CLAHE(对比度限制自适应直方图均衡)

对比度限制自适应直方图均衡化(CLAHE)

对比度受限的 AHE ( CLAHE )是自适应直方图均衡化的变体,其中对比度放大是受限的,以便减少噪声放大的问题。简而言之,CLAHE 以高精度和对比度限制在小块或小块中进行直方图均衡化。

现在我们知道了 CLAHE 是什么,让我们看看如何设置它。

clahe = cv2.createCLAHE(clipLimit =2.0, tileGridSize=(8,8))
cl_img = clahe.apply(img)

CLAHE 图像

正如你从上面的图片中看到的,CLAHE 给出了比普通均衡图像更好的结果。但它仍然有很多噪声,让我们看看如何阈值工作,以获得更好的结果。

为了获得更好的图像效果,使用 **.tiff** 文件格式,而不是 **.jpeg** 文件格式

在开始阈值处理之前,我们需要看看 CLAHE 图像的直方图。

plt.hist(cl_img.flat, bins=100, range=(100, 255))

CLAHE 图像直方图

从上面的直方图可以看出,在 160–200 之间有一个倾角,我们可以确定一个接近的数字来分隔这两个峰值。在我们决定一个接近的数字后,我们可以用它来做阈值(我选择了 190)

ret, thresh1 = cv2.threshold(cl_img, 190, 150, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(cl_img, 190, 255, cv2.THRESH_BINARY_INV)

忽略第一个参数ret,我们可以得到阈值图像的变量thresh1thresh2。在上面的代码部分中,第一个参数是图像,其次是我们选择的阈值,第三,我们需要给所有被阈值化的像素赋予一个值,最后,我们需要给出一个方法。我给了THRESH_BINARYTHRESH_BINARY_INV来分开变量。

左阈值 2 和右阈值 1

在第一阈值图像(thresh1)中,灰度值为 150,第二阈值图像(thresh2)的灰度值为 255。这只是基于直方图的阈值处理。

在上面的例子中,我们通过参考直方图发现值 190 是最佳值。但是使用 OTSU 有一种更简单的方法来找到最佳值。

ret, thresh3 = cv2.threshold(cl_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

使用 OTSU,我们可以自动分割它。

阈值 3 — OTSU

如果使用二进制阈值,OTSU 是找到最佳值的最佳方法。如果有必要,你甚至可以使用 K-means。

文章到此为止。如果你的图像有噪声,不要忘记先去噪。然后你可以做所有这些练习。

结论

总结一下,CLAHE 在大多数情况下都很有效。然后,您可以使用直方图将图像分为这两个阶段,但如果您不想绘制直方图来识别分离,则可以使用 OTSU。

资源

[## Sreeni 为显微镜专家开发的 Python

本频道将带您了解学习 Python 编码的整个过程;从基础到高级…

www.youtube.com](https://www.youtube.com/channel/UC34rW-HtPJulxr5wp2Xa04w)

类激活映射

原文:https://towardsdatascience.com/class-activation-mapping-using-transfer-learning-of-resnet50-e8ca7cfd657e?source=collection_archive---------11-----------------------

一种强有力的弱监督目标定位和调试方法

Ales NesetrilUnsplash 上拍摄的照片

介绍

在这篇文章中,我想与你分享一个非常强大和有趣的技术。这种技术被称为类别激活图(CAMs),是由麻省理工学院的研究人员在论文“学习深度特征进行区分定位”中首次引入的。CAMs 的使用使你不仅可以看到网络预测的类别,还可以看到网络特别感兴趣的图像部分。这有助于更深入地了解网络的学习,并且也简化了调试,因为用户不必显式地标记该对象的边界框就可以获得预测类的对象定位。在章节方法论中,我想浏览一下使用的数据,以及在哪里可以找到本文使用的代码。章节模型描述了所使用的模型及其训练。章节类激活映射描述了 CAMs 的概念以及如何计算它。第章结论应该是总结调查结果。

方法学

网络的训练过程和凸轮的计算是用 jupyter 笔记本和 tensorflow 完成的。使用来自 Kaggle 的 360°水果挑战赛的数据集。它包含 90483 幅水果和蔬菜的图像,共有 131 个不同的类别。图 1 显示了一个以地面实况标签为标题的示例图像。相应的笔记本可以在我的 Github 资源库中找到。

图 1:来自 Kaggle 数据集的示例图像

模型

作为模型,我决定使用已经训练好的 ResNet50 [4]进行迁移学习(TL)。该模型在包含 1000 个不同类的 ImageNet 挑战上被训练。TL 对于快速训练一个大而深的网络非常有用,因为网络不用从头开始训练。通常,你越深入,过滤器在你的网络中学习的特征就越复杂。第一层的过滤器仅学习非常低级的特征,如边缘。这是因为第一层的滤光器只能看到输入图像的一小部分。在第二层,这部分(也称为感受野)已经更大,因此过滤器可以学习更复杂的特征。并且在最后的卷积层上,过滤器已经可以检测完整的对象。当使用 TL 时,预训练的模型被加载,分类层被删除。之后,除了新添加的分类层之外,整个 CNN 被冻结和训练,直到损失收敛。这避免了由于初始潜在的大梯度而破坏已经学习的特征。或者,您可以随后解冻 CNN 的剩余部分或只解冻最后的层,并微调它们的权重以适应您当前的任务。对于这项任务,我决定只重新训练分类层,以便专注于计算凸轮。因此,我在最后删除了 ResNet50 中的所有密集层,并添加了一个全局平均池层(请参见下一章为什么添加此层)以及 softmax 层,该层具有与要分类的类一样多的神经元。该架构将在下一章中详细描述。然后,该模型被训练五个时期,最终得到 99%的验证准确度。

类激活映射

CAM 是为每个图像生成的加权激活图[1]。它有助于识别 CNN 在对图像进行分类时正在查看的区域。摄像机不是在监督下训练的,而是以一种弱监督的方式。这意味着对象不必手动标记,本地化是“免费”学习的。在架构上唯一需要改变的是去掉末端完全连接的密集层,以保持最后一个卷积层输出中包含的空间信息。此外,之后还会添加一个全局平均池层。这一层通常用于正则化,以防止网络过拟合[2]。最后,添加输出 softmax 层,其神经元数量与要分类的类数量一样多(在我们的示例中为 131)。图 2 总结了所需的架构,并展示了如何计算 CAM。

图 2: CAM 架构和程序[1]

在我们的例子中,架构变化和训练已经完成(参见章节模型),所以我们可以直接从计算 CAM 开始。作为第一步,我们向网络输入一幅图像,并计算网络的分类输出。下一步,我们获取连接到“获胜”神经元的权重。此外,我们存储最终卷积层的输出。然后,我们通过将来自最终卷积层的输出的每个深度乘以连接到“获胜”神经元的相应权重来计算 CAM(即,w1 将乘以最终卷积层输出的深度 1,w2 乘以深度 2,…),并将它们全部相加。最后,我们使用双线性上采样来扩展 CAM 的大小以匹配输入图像的大小。图 3 显示了我的 github 页面上 jupyter 笔记本的功能。

图 3:计算 CAM 的函数(代码来自[3])

图 4 显示了六个示例 cam。每个 CAM 的标题显示了网络的预测标签。

图 CAM 的示例输出和网络预测

结论

可以看出,只需对网络架构稍作调整,就可以轻松计算 CAM,而且是免费的,因此没有人需要为数据贴上昂贵的标签。此外,CAM 还可以用于调试,因为可以看到网络聚焦在图像的哪个区域。例如,如果网络应该对图像中港口的存在进行分类,并且通过绘制 CAM 可以清楚地看出网络关注的是天空而不是港口本身,那么这可能是有帮助的。然后,用户可以调整数据集,使其也包含没有可见天空的港口的图像,从而避免这种错误的关联。

资源

[1]:周,Aditya Khosla,Agata Lapedriza,Aude Oliva,Antonio Torralba,学习深度特征进行区分性本地化 (2015),MIT
[2]:,,和水城颜, Network In Network (2013),新加坡国立大学
[3]: Alexis Cook,全球平均池 (2017),Github Blogpost
[4]:何,,,任

分类中的阶级不平衡问题

原文:https://towardsdatascience.com/class-imbalance-problem-in-classification-a2ddaba98f4a?source=collection_archive---------19-----------------------

如果 SMOTE 和 TOMEK 没有改善你的模型怎么办?

当我们在处理分类的时候,我们会面临很多问题。其中之一是阶层失衡:一个阶层代表过多,另一个阶层代表严重不足。这个问题出现在许多研究领域,例如,当我们试图诊断一种罕见的疾病或检测欺诈交易时。在这篇文章中,我想谈谈在我的一个分类项目中,我是如何处理班级失衡问题的。

通常,当我们的阶级比例低于 10/90 时,我们可以说我们面临着阶级失衡。在某些情况下,甚至会更严重。我曾经做过一个分类项目,试图预测丝芙兰出售的哪种美容产品会赢得声望倾城之美奖。在检查了我的数据后,我意识到我有 1920 件产品没有获奖,只有 81 件获奖。注意:有更多的获奖产品,但只有 81 个在丝芙兰售出,我只是在处理他们的数据。

传统方法

为了创建一个二元分类模型,我决定先采用一种简单的方法:不加任何处理地运行逻辑回归。结果是预期的:模型执行的准确率为 96%,但不存在召回。这意味着,这种方法将所有未被充分代表的类别视为背景噪音,或者简单地说,只是假设所有产品都不是赢家,并且在 96%的情况下都是正确的。

如果我们谈论的是赢得奖项的美容产品,这不是世界末日,但如果我们试图诊断一种致命的疾病呢?我们需要消除第二类错误。

有两种著名的处理类不平衡问题的传统方法:使用 TOMEK 链接的欠采样和使用 SMOTE 的过采样。

在第一种情况下,我们检测两个不同类的实例之间的链接,这两个类彼此靠近并且混淆了模型。在我的项目中,可能有两个非常相似的产品(相同的价格,相似的评级,等等。)但是其中一个得了奖,另一个没有。我们在这些实例之间创建一个链接并删除它们,尽可能地将两个类分开。

对于 SMOTE(合成少数过采样技术),我们采用不同的方法。我们不是减少数据点的数量,而是创建代表性不足的类的合成实例。同样,在我的例子中,我们只是分析价格、评级和其他代表诱惑赢家的预测因素,并创建更多具有这些特征的实例。

在从事我的项目时,我尝试了这两种方法,但我建立的模型(逻辑回归、朴素贝叶斯、XGBoost)都没有超过 78%的准确率,也没有提高召回率。

我反而做了什么

经过慎重考虑,我决定采取循序渐进的方法。

首先,我需要创建两个独立的数据框架,赢家和非赢家(为了简单起见,让我们称他们为输家,尽管这听起来可能不太合适)

df_lose = df[df[‘Allure’] == 0]
df_win = df[df[‘Allure’] == 1]

接下来,为了确保我的欠采样是无偏的,我们需要打乱非获胜数据帧 df_lose 的行:

df_lose = shuffle(df_lose)

接下来,我们需要截断这个数据帧,以匹配 df_win 的维度(记住,我们只有 81 个获胜者):

df_lose_81 = df_lose[:81]

最后,我们将它们连接在一起,再次洗牌,以防万一:

twodf = [df_win, df_lose_81]
edf = pd.concat(twodf, ignore_index=True)edf = shuffle(edf)

现在,我们可以查看新数据框的数字,并直观地检查这些类在其预测列中是否不同。事实证明,确实如此,尤其是在“心”这个类别(有多少人“喜欢”这个产品)

最后,我们可以运行我们的分类模型。我最好的模型是 XGBoost,验证准确率为 96.97%,召回率为 0.93。在得到这些有希望的结果后,我有点怀疑,如果我只是碰巧选择了两个类中最不同的实例呢?我重复了这个过程,将行重新排列了四次,每次模型的性能都保持不变。

请随意叉克隆我的 GitHub repo ,希望我的小小研究有所帮助!

等级不平衡,SMOTE,临界 SMOTE,ADASYN

原文:https://towardsdatascience.com/class-imbalance-smote-borderline-smote-adasyn-6e36c78d804?source=collection_archive---------15-----------------------

类别不平衡会使我们的算法失去平衡

图像来源

那是在 20 世纪 90 年代末,当时南佛罗里达大学的一名研究生 Niesh V . Chawla(SMOTE 背后的主脑)正在研究一个二元分类问题。他正在处理乳房 x 光摄影图像,他的任务是建立一个分类器,该分类器将像素作为输入,并将它分类为正常像素或癌变像素。当他达到 97%的分类准确率时,他相当高兴。当他看到 97.6%的像素正常时,他的快乐是短暂的。

你可能在想,这有什么问题?有两个问题

  • 假设在一个 100 个像素的样本中,98 个是正常的,2 个是癌性的,如果我们写一个程序,它可以预测任何正常的东西。分类准确率会是多少?高达 98%。程序学会了吗?一点也不。
  • 还有另一个问题。分类器努力在训练数据中获得良好的性能,并且随着正常观察值越来越多,它们将更加专注于学习“正常”类的模式。这就像任何学生知道 98%的问题来自代数,2%来自三角学时会做的一样。他们会安全地忽略三角测量

那么,为什么这个问题会表现出来呢?这是因为上课的频率和次数之间有很大的差异。我们称这样的数据集为展示类不平衡。正常阶层被称为多数阶层,罕见阶层被称为少数阶层。

作为少数派的海鸥(https://unsplash.com/photos/SQBtDa6cKDA)

现实应用中存在这种情况吗?以垃圾邮件检测、假新闻检测、欺诈检测、可疑活动检测、入侵检测等为例,其中表现出了类别不平衡问题。

实现某种平衡的解决方案:

基本的方法被称为重采样技术。有两种基本方法。

欠采样:-

欠采样或欠采样多数类(图像源作者)

我们从多数类中随机选取样本,并使其等于少数类计数。这被称为欠采样或多数类的下采样。

问题:忽略或放弃这么多原始数据并不是一个好主意。

过采样:-

对少数类进行过采样或上采样(图片来源作者)

这里,替换抽样应用于少数类,以创建与多数类一样多的观察值,并且这两个类是平衡的。这被称为过采样或少数类上采样。

问题:相同少数类数据的重复导致过度拟合。

重击:

SMOTE 的完整形式,综合技术。这里的综合观察是从少数类中产生的

SMOTE,合成少数观察生成过程(来源:作者)

假设有来自少数类的两个观察值(x1,y1)和(x2,y2)。作为第一步,创建一个介于 0 和 1 之间的随机数,我们称之为 r。合成点将是(x1 + r(x2 -x1),y1 + r(y2 -y1))。下面的例子进一步说明了这一点。

从少数类生成的合成点(图片来源:作者)

【SMOTE 的一个问题:

左侧:原始数据右侧:应用 SMOTE 后的数据(图片来源:作者)

如果少数类中的观察值是外围的并且出现在多数类中,则通过创建与多数类的线桥,会给 SMOTE 带来问题。

临界击打:-

这解决了上述问题。

边界线 SMOTE:(图片来源作者)

该算法首先对少数类观测值进行分类。如果所有邻居都是多数类,则它会将任何少数观察分类为噪声点,并且在创建合成数据时会忽略此类观察(类似于 DBSCAN)。此外,它将几个点分类为具有多数和少数类作为邻域的边界点,并完全从这些点重新采样(支持向量通常会关注的极端观察)。

问题:结束对这些极端观察的更多关注。

阿达辛:

ADASYN 是一个更通用的框架,对于每个少数观察值,它首先通过取邻域中多数观察值与 k 的比值来找到邻域的杂质。

阿达辛杂质比率

现在,首先,通过使总和为 1,将该杂质比转换成概率分布。那么该比率越高,为该特定点生成的合成点就越多。因此,为 Obs 3 创建的合成观测数据的数量将是 Obs 2 的两倍。因此,它不像边界平滑那样极端,噪声点、边界点和常规少数点之间的边界要柔和得多。(不是硬性边界)。因此得名自适应。

这个在下面的视频教程里也有讲解,请给它一个

尾注:

阶层失衡是一个非常现实的问题。基于重采样的方法没有前途,这促使研究人员开发 SMOTE,并通过 borderline SMOTE、ADASYN 等逐渐改进。要了解更多的变体,参考文献 2 是一个很好的读物。

参考

[1]舒拉 NV,鲍耶 KW,霍尔 LO,凯格尔迈耶 WP。SMOTE:合成少数过采样技术。人工智能研究杂志。2002 年 6 月 1 日;16:321–57.

[2]费尔南德斯 A、加西亚 S、埃雷拉 F、舒拉 NV。SMOTE 从不平衡数据中学习:进步与挑战,15 周年纪念。人工智能研究杂志。2018 年 4 月 20 日;61:863–905.

Python 中的类实例

原文:https://towardsdatascience.com/class-instances-in-python-d89ebf545ba4?source=collection_archive---------38-----------------------

类实例的字符串表示

来源

自定义类实例的表示方式是简化调试和实例输出的好方法。在这篇文章中,我们将讨论如何通过定义“repr”和“str”方法来改变实例的字符串表示。

我们开始吧!

首先,让我们定义一个描述 YouTube 频道的类。该类将包含特定于 Youtube 频道的属性(数据),如频道名称、订户和验证状态:

class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

让我们创建一个 YouTube 类的实例。提醒一下,实例是一个类对象的具体实例。对于我们的实例,让我们设置对应于我最喜欢的 YouTube 频道之一的属性,:

*sentdex = YouTube('Sentdex', 847000, True)*

现在我们已经创建了实例,让我们打印出实例:

*print(sentdex)*

我们看到在指定的内存地址中有一个类型为“YouTube”的对象。虽然这符合我们的预期,但它并不是我们的实例可读性最好的表示。如果我们想改变这个对象的表示方式,我们可以定义' repr '和' str '方法。首先,让我们定义' repr '方法:

*class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

    def __repr__(self):
        return 'YouTube({0.channel_name!r}, {0.subscribers!r}, {0.verification!r})'.format(self)*

让我们重新定义我们的对象' sentdex ',并打印结果:

*sentdex = YouTube('Sentdex', 847000, True)
print(sentdex)*

我们看到' repr '方法返回了我们实例的代码表示。它只是对应于我们为创建实例而键入的代码。

现在,让我们定义' str '方法:

*class YouTube:
    def __init__(self, channel_name, subscribers, verification):
        self.channel_name = channel_name
        self.subscribers = subscribers
        self.verification = verification

    def __repr__(self):
        return 'YouTube({0.channel_name!r}, {0.subscribers!r}, {0.verification!r})'.format(self) def __str__(self):
        return '({0.channel_name!s}, {0.subscribers!s}, {0.verification!s})'.format(self)*

让我们再次定义我们的实例并打印结果:

*sentdex = YouTube('Sentdex', 847000, True)
print(sentdex)*

我们看到我们现在有了实例的字符串表示。如果我们想要打印出代码表示,使用我们当前的类实现,我们可以使用内置的“repr()”方法:

*sentdex = YouTube('Sentdex', 847000, True)
print(repr(sentdex))*

我还想指出' repr()'和' str()'在文本格式上的区别。特别的!“r”格式代码指示应使用“repr()”的输出,而不是默认的“str()”。例如,如果我们包括!我们字符串中的“r ”:

*sentdex = YouTube('Sentdex', 847000, True)
print('sentdex is {0!r}'.format(sentdex))*

我们得到了代码表示。如果我们省略掉!r '代码,字符串表示用作默认值:

*sentdex = YouTube('Sentdex', 847000, True)
print('sentdex is {0}'.format(sentdex))*

定义“repr()”和“str()”方法通常是很好的做法,因为它可以使类实例更容易解释和调试。例如,记录实例的自定义字符串表示可以为程序员提供更多关于实例内容的有用信息。我就讲到这里,但是我鼓励你自己去研究代码。如果你有兴趣学习更多与 python 中的类定义相关的编程模式,我鼓励你去看看 Python 食谱

结论

总之,在这篇文章中,我们讨论了类实例的字符串表示。我们展示了如何定义“repr()”和“str()”方法,这允许我们显示实例的代码表示和字符串表示。这种做法可以使类实例的内容透明,如果做得好,可以大大简化调试。我希望你觉得这篇文章有用/有趣。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的类

原文:https://towardsdatascience.com/classes-in-python-e31c21120c3d?source=collection_archive---------17-----------------------

理解面向对象编程

来源

类允许我们以某种方式组织数据和函数,使它们在将来易于重用和扩展。在这篇文章中,我们将讨论用 python 构建类的基础。

我们开始吧!

首先,让我们创建一个表示 Spotify 用户的简单类,没有数据(也称为属性)或函数(也称为方法):

class Spotify_User:
    pass

现在,让我们花些时间来区分类和类的实例。类基本上是创建实例的蓝图。我们创建的每个唯一用户都将是 Spotify_User 类的一个实例。例如,我可以定义两个 Spotify 用户实例,user_1 和 user_2:

user_1 = Spotify_User()
user_2 = Spotify_User()

这些用户中的每一个都将是他们自己的 Spotify_User 类的唯一实例。我们可以打印这两个对象:

print(user_1)
print(user_2)

我们看到这两个都是内存地址不同的 Spotify_User 对象。我们可以做的另一件事是创建实例变量,这些变量对于每个实例都是唯一的。让我们定义保存每个用户姓名的实例变量:

user_1.name = 'Sarah Phillips'
user_2.name = 'Todd Grant'

让我们给每个实例发一封电子邮件:

user_1.email = 'sphillips@gmail.com'
user_2.email = 'tgrant@gmail.com'

最后,让我们定义实例变量,告诉我们每个用户是否是 Spotify 的高级会员:

user_1.premium = True
user_2.premium = False

现在,这些实例中的每一个都具有每个实例独有的属性。让我们打印每个用户的姓名:

print(user_1.name)
print(user_2.name)

理想情况下,我们希望为每个用户自动设置所有这些信息,而不是手动设置这些值。为了获得类的全部好处,我们应该定义一个方法,允许我们用手动定义的值初始化每个用户实例。初始化方法基本上是一个构造函数,将被称为“init ”:

class Spotify_User:
    def __init__(self, name, email, premium):
        self.name = name
        self.email = email
        self.premium = premium

这里,“self”参数是实例,它允许我们在实例中共享属性信息。例如,当我们写下:

user_1 = Spotify_User('Sarah Phillips', 'sphillips@gmail.com', True)
user_2 = Spotify_User('Todd Grant', 'tgrant@gmail.com', False)

每种情况下的“self”参数分别是 user_1 和 user_2 对象。如果我们打印电子邮件,我们会看到:

print(user_1.email)
print(user_2.email)

这允许我们用比手工定义属性少得多的代码来定义属性。现在假设我们想要对每个用户的属性执行一些操作。例如,我们可以定义一个方法来告诉我们用户是否拥有高级会员资格。在我们的方法中,如果“self.premium”为真,我们打印“用户是 Spotify 高级用户”,否则,我们打印“用户不是 Spotify 高级用户”:

def isPremium(self):
        if self.premium:
            print("{} is a Premium User".format(self.name))
        else:
            print("{} is not a Premium User".format(self.name))

让我们使用 user_1 实例调用该方法:

user_1.isPremium()

并且在用户 2 上:

user_2.isPremium()

如您所见,由于“self”参数被传递给“init”和“isPremium”,因此在初始化时,“isPremium”方法可以完全访问相应实例的属性。

我将在这里停下来,但是您可以随意摆弄代码。例如,您可以尝试定义 Spotify_User 类的几个额外的用户实例。在那里,您可以练习提取实例属性并使用类方法“isPremium”。一旦你觉得舒服了,我鼓励你定义额外的类方法。一个有趣的方法是为每个用户显示定制的播放列表。

结论

总之,在这篇文章中,我们讨论了用 python 定义类的基础。我们展示了如何定义类的实例、初始化实例、访问实例属性以及用方法操作属性。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

Python 中的类:数据科学家的基础

原文:https://towardsdatascience.com/classes-in-python-fundamentals-for-data-scientists-fb7deb4fcda1?source=collection_archive---------26-----------------------

用一个具体的例子来理解基础!

图片由 Unsplash 上的 Alexandru Acea 拍摄

类通过将数据和函数封装在一个实体中来帮助我们整理代码。此外,它们增加了代码的可重用性和可伸缩性,简化了调试过程。

一旦我们定义了一个类,我们就可以使用这个类的实例来处理特定的任务。在这方面,它们是我们在代码中使用的对象的蓝图。

让我们用一个具体的例子来了解一下基础知识。

定义类别

在我们的例子中,我将使用 Pandas ,这是一个流行的 Python 数据操作库,以及几个包含表格数据的 CSV 文件

在 Python 中,基本类定义具有以下格式:

classClassName():
 # Comments / Notes
 ...
 # Initializer / Instance Attributes
 ...
 # Methods
 ...

首先,让我们创建一个简单的类,帮助我们显示 CSV 文件中包含的表格数据的摘要信息。

*class* CSVGetInfo:
**""" This class displays the summary of the tabular data contained in a CSV file """***def* **__init__**(*self*, *path*, *file_name*):
 self.path = path
 self.file_name = file_name*def* **display_summary**(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.info())

在 Python 中,一个简单的类定义以下面的符号开始:

*class* ClassName:

在我们的例子中,我们的类名是“CSV getinfo”。请注意 Python 中的类名遵循 UpperCaseCamelCase 命名约定。虽然这不是强制性的,但是通常将类存储在一个单独的文件中,并在以后需要时导入它们。

增加一个评论区让其他人知道我们的类是做什么的,这是一个很好的做法。我们可以通过在三重双引号内提供注释来做到这一点。

*class* CSVGetInfo:
**""" This class displays the summary of the tabular data contained in a CSV file """**

初始化实例变量(属性)

在这些最初的步骤之后,现在是时候定义我们的类所涉及的数据了。在我们的例子中,我们需要知道想要读取的 CSV 文件的路径和文件名信息。

所以,我们的类有‘path’‘file _ name’变量。它们将为我们的 CSVGetInfo 类的每个实例初始化,它们被称为我们类的实例变量或属性。

**# Initializer / Instance Attributes** 
 *def* __init__(*self*, *path*, *file_name*):
  self.path = path
  self.file_name = file_name

init 方法指出当我们创建类的新实例时必须提供什么数据。

本地变量提供的数据存储在 self.pathself.file_name 中。 在这里, self 代表实例本身。

在创建实例时,变量初始化是一个强制性的过程,这个特殊的 init 方法保证了它总是发生。

Tra TranUnsplash 上拍摄

添加实例函数(方法)

现在,我们可以定义使用这些数据来处理特定任务的函数。类结构中的函数称为方法或实例函数,因为它们与类的每个实例都有联系。我们将在我们的 CSVGetInfo 类结构中定义 "display_summary" 方法,它显示包含在 CSV 文件中的表格数据的摘要信息。

**# M****ethods***def* **display_summary**(*self*):
 data = pd.read_csv(self.path + self.file_name)
 print(self.file_name)
 print(data.info())

注意,我们在方法中再次使用了 self 作为参数。这是访问我们正在处理的实例中包含的数据所需要的。

为了访问 "display_summary" 方法中的实例变量,我们使用 self.path 和 self.file_name 符号。

创建类(对象)的实例

由于类本身是对象的蓝图,我们需要创建类(对象)的实例,以使用类定义中可用的方法来处理任务。

在我们的类中,我们有“display _ summary”方法。

因此,让我们创建两个 CSVGetInfo 的实例,并使用“display _ summary”方法来查看 CSV 文件中的内容。

为了创建一个类的实例/对象,我们使用类名并将值传递给该类所需的参数。

data_by_artists = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_artists.csv")data_by_genres = CSVGetInfo("/Users/erdemisbilen/Lessons/", "data_by_genres.csv")

现在,变量 data_by_artist 保存了对我们的 CSVGetInfo 类的第一个实例的引用。它是 CSVGetInfo 类的对象/实例,将“data _ by _ artists . CSV”的值存储在 file_name (实例变量)中。其他变量data _ by _ 流派保存了对我们类的第二个实例的引用,该实例的“data _ by _ 流派. CSV”值存储在文件名中。尽管它们是用相同的类定义创建的,但是它们在实例变量(属性)中存储了不同的值。

print(data_by_artists)
print(data_by_genres)**#Output**
<__main__.CSVGetInfo instance at 0x10b84f248>
<__main__.CSVGetInfo instance at 0x114eb58c0>

当我们打印实例时,我们可以看到它们存储在内存的不同位置。

彼得·德·卢奇亚在 Unsplash 上的照片

让我们用【展示 _ 总结】的方法。

data_by_artists.display_summary()
data_by_genres.display_summary()**#Output
data_by_artists.csv**
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 27606 entries, 0 to 27605
Data columns (total 15 columns):
artists             27606 non-null object
acousticness        27606 non-null float64
danceability        27606 non-null float64
duration_ms         27606 non-null float64
energy              27606 non-null float64
instrumentalness    27606 non-null float64
liveness            27606 non-null float64
loudness            27606 non-null float64
speechiness         27606 non-null float64
tempo               27606 non-null float64
valence             27606 non-null float64
popularity          27606 non-null float64
key                 27606 non-null int64
mode                27606 non-null int64
count               27606 non-null int64
dtypes: float64(11), int64(3), object(1)
memory usage: 3.2+ MB
None**data_by_genres.csv**
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2617 entries, 0 to 2616
Data columns (total 14 columns):
genres              2617 non-null object
acousticness        2617 non-null float64
danceability        2617 non-null float64
duration_ms         2617 non-null float64
energy              2617 non-null float64
instrumentalness    2617 non-null float64
liveness            2617 non-null float64
loudness            2617 non-null float64
speechiness         2617 non-null float64
tempo               2617 non-null float64
valence             2617 non-null float64
popularity          2617 non-null float64
key                 2617 non-null int64
mode                2617 non-null int64
dtypes: float64(11), int64(2), object(1)
memory usage: 286.3+ KB
None

结论

在这篇文章中,我解释了 Python 中类的基础知识。

这篇文章中的代码和使用的 CSV 文件可以在 my GitHub repository 中找到。

我希望这篇文章对你有用。

感谢您的阅读!

经典概率问题#1:折断的棍子、三角形和概率

原文:https://towardsdatascience.com/classic-interview-question-1-broken-sticks-triangles-and-probability-98b0b1974fd8?source=collection_archive---------27-----------------------

数据科学和机器学习面试

以下是概率论中的经典玩具问题,作为数据科学和机器学习角色的精彩技术面试问题。问题如下:

问题:你有一根任意长度的棍子。你沿着棍子的长度在两个地方均匀地随机折断它,给你留下三个不同的碎片。你能用产生的三块组成一个三角形的概率是多少?

我们将首先解析地解决这个问题,然后通过计算模拟这个问题来验证我们的发现。

解决方案:注意我们的棍子是任意长度的。为了从数学上界定这个问题,让我们选择一个易于管理的长度。假设这根棍子的单位长度为 1。

现在,我们沿着棍子的长度在两个地方随机均匀地折断它,这样我们就有三段了。注意,因为我们已经将总长度定义为“单位长度 1”,所以只需要两个变量 ab 来完全指定产生的三个片段的长度。第一段长度为 a ,第二段长度为 b ,第三段长度为 1-a-b :

请注意,每个片段的长度范围可以从 0 到 1,条件是三个片段的总和为 1。让我们以图形方式将总概率空间映射为 ab 的函数:

现在问题来了,我们的三块拼成三角形了吗?让我们回忆一下所有三角形所要求的几何条件:三角形的每条边都严格小于其他两条边之和。因此,我们可以指定从三个部分形成三角形所需的三个不同的边界条件:

让我们将上述三个边界条件叠加在我们的概率空间上,以确定 ab 的值,我们可以形成一个三角形:

从上图我们可以看到,边界条件指定了总概率空间的 1/4。因此,我们可以得出结论,这三个碎片有 1/4 的概率形成一个三角形。

现在让我们用 python 通过计算模拟这个问题,以确认我们的解析解:

######################
## import libraries ##
######################
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt## number of iterations 
iterations = 10000
results = pd.DataFrame()
results['iteration'] = list(range(1,iterations+1))
percentage = iterations*[None]np.random.seed(10815657)
count = 0
for i in range(0, iterations):
    random_draws = np.random.uniform(low=0, high=1, size=2)
    a = min(random_draws)
    b = abs(random_draws[0] - random_draws[1])
    if((a<0.5) and (b<0.5) and (0.5 < a+b)):
        count=count+1
    percentage[i] = count / (i+1)results['percentage'] = percentageplt.plot(results['iteration'], results['percentage'], color='blue')
plt.xlabel('Number of trials') 
plt.ylabel('Percentage of simulations where pieces can form a triangle')percentage[iterations-1]

如上所示,经过 10,000 次模拟,结果收敛到三个碎片可以形成三角形的概率为 1/4(即 25%)。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在【LinkedIn】上与我联系,并在 Medium 上关注我的更新!

经典概率问题#2:优惠券问题

原文:https://towardsdatascience.com/classic-probability-problem-2-the-coupon-problem-7acd7febaabd?source=collection_archive---------28-----------------------

数据科学和机器学习面试

freeimages.com

这是我第二次进入概率论中的经典玩具问题。“息票问题”是一个需要注意的大问题;它出现在许多应用场合。从技术面试的角度来看,通过在最后添加一个小的计算组件,它可以作为对一般概率和编码知识的可靠测试。问题如下:

问题:

有一种品牌的麦片,每买一盒都有一张优惠券。有 5 种不同类型的优惠券。每购买一盒麦片,获得 5 张优惠券中任何一张的概率是一致的。目标是收集所有 5 种独特的优惠券类型。

现在问题来了,你需要购买多少盒麦片才能收集到所有 5 张独特的优惠券?

我们将首先解析地解决这个问题,然后通过计算模拟这个问题来验证我们的发现。

分析解决方案:

让我们从一些观察开始:

  1. 购买的每一盒麦片都独立于最后购买的一盒(或多盒)。
  2. 在给定的盒子中获得 5 种优惠券类型中的任何一种的概率是相同的。

我们需要某种数学方法来界定这个问题。也许我们可以使用一些参数工具?让我们快速绕道,讨论几何随机变量。

几何随机变量:

几何随机变量是具有单参数分布的离散随机变量,具体如下:

请注意,我们可以将我们的优惠券收集问题视为五个几何随机变量的期望值之和,每个变量具有不同的成功参数 p :

注意,几何随机变量的期望值是 1/p:

几何 RV 期望值的证明(可选部分):

对于那些对几何随机变量的期望值的推导感兴趣的人,下面我包括了两个推导(一个直接使用 PMF,另一个使用 MGF)。如果您对这些证明不感兴趣,可以跳过这一部分:

解决问题:

现在我们简单地将五个指定的随机变量的期望值相加:

因此,四舍五入到最接近的整数,我们需要购买的收集所有 5 个独特优惠券的预期盒数是 12 盒。

计算模拟:

现在让我们用 python 模拟这个场景,计算 10,000 次以上的迭代,以证实我们上面的分析结果:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt## specify number of coupons, and the probability of getting a coupon
num_coupons=5
expected_number_of_trials = 0
for i in range(num_coupons, 0, -1):
    expected_number_of_trials = expected_number_of_trials + (1/(i/num_coupons))iterations = 10000
df = pd.DataFrame()
df['iteration'] = range(1,iterations+1)
df['average_num_trials_required'] = Nonefor i in range(0, iterations):
    full_set = set(range(0,num_coupons))
    current_set = set([])
    total_number_of_coupons_collected = 0
    while(current_set != full_set):
        total_number_of_coupons_collected = total_number_of_coupons_collected+1
        random_coupon = np.asscalar(np.random.randint(low=0, high=num_coupons, size=1))
        update_set = list(current_set)
        update_set.append(random_coupon)
        current_set = set(update_set)
        del random_coupon, update_set

    if(i+1 == 1):
        df.loc[df['iteration']==i+1, 'average_num_trials_required'] = total_number_of_coupons_collected
    else:
        df.loc[df['iteration']==i+1, 'average_num_trials_required'] = float(((df.loc[df['iteration']==i, 'average_num_trials_required']*i) + total_number_of_coupons_collected)/(i+1))print(df['average_num_trials_required'][i])

如上所示,在该场景的 10,000 次迭代中,收集所有 5 个唯一优惠券所需购买的盒子数量的样本平均值约为 11.431。这个结果与我们上面的解析解一致。

最后的想法——我们为什么要关心这个问题,或者任何其他玩具问题??

正如技术领域中大多数众所周知的玩具问题一样,这个“优惠券问题”和关于谷物和优惠券收集的傻孩子般的场景有一个重要的目的。这个问题(以及它的微小变化)在应用实践中不断出现;关于离散等待时间的期望值的问题,或者在某事发生之前可能需要发生的事件的数量的问题。这些问题通常可以归结为优惠券问题的某种变体。因此,拥有良好的基础知识和关于玩具问题的理论基础知识,比如这里讨论的,对你的应用实践有很大的帮助。

此外,值得一提的是,我们为 5 独特优惠券解决了这个问题。但是我们可以选择任何大于零的任意常数 n 唯一优惠券。这里使用的方法仍然适用。

最后,我想留给你一个挥之不去的问题。在我们上面的问题中,假设你已经收集了 4 个独特的优惠券,现在正在收集第 5 个也是最后一个独特的优惠券。张贴您收集的第四张独特优惠券,您已经购买了 50 多盒麦片,但所有都包含更多您已经拥有的 4 张独特优惠券。从那时起,您需要购买多少盒才能获得第五张优惠券?我给你一个提示,几何分布是指数分布的离散对应物,它有一个关于等待时间的独特性质。欢迎在评论中加入你的想法,以及我上面的谜语的可能答案。

希望以上有见地。正如我在以前的一些文章中提到的,我认为没有足够的人花时间去做这些类型的练习。对我来说,这种基于理论的洞察力让我在实践中更容易使用方法。我个人的目标是鼓励该领域的其他人采取类似的方法。我打算在未来写一些基础作品,所以请随时在 LinkedIn 上与我联系,并在 Medium 上 关注我的更新!

经典分类器组合技术:投票方法、Borda 计数和行为知识空间

原文:https://towardsdatascience.com/classical-classifier-combination-techniques-voting-approaches-borda-counts-and-5b047faaffbc?source=collection_archive---------40-----------------------

在本文中,我们回顾了经典的分类器组合技术,这些技术通常被用作新提出的方法的基准。

在本文的其余部分,我们用ôᵏ( x 表示 kᵗʰ分类器关于测试样本的决策 x ,用 K 表示决策将被组合的小组中分类器的数量。类别标签的总数为 m.

投票方式

一个显而易见的方法是通过投票系统来协调一系列的决定。投票方案的几种变体可以用于分类器融合,并且其中一些可以集成上下文信息,例如单个分类器的准确度。投票原则背后的想法是基于直觉,即小组中分类器(专家)的数量越多,就越有可能做出正确的最终决定。

常见的投票方案如下:

  • 一致投票是这样一种系统,其中如果所有个体分类器决策都是 cᵢ,则组合决策是标签 cᵢ,否则组合分类器拒绝输入 x :

  • 修改一致投票是这样一种系统,其中如果所有个体分类器决策是 cᵢ或 cᵣₑ,则组合决策是标签 cᵢ,否则组合分类器拒绝输入x。换句话说,没有分类器应该预测不同于 cᵢ的分类标签

  • 多数表决是一种系统,其中如果预测 cᵢ的分类器的数量最大,则组合决策是标签 cᵢ

博尔达和 w 博尔达计数

Borda counts 是一种基于等级的组合方案,其中每个分类器根据成为正确(真实)类别的机会对类别(候选)进行分级。每个等级与一个分数相关联,从第一个等级的 m-1 到最后一个等级的 0,其中 m 是等级的总数。第二次,计算每个班级获得的分数的总和,获得最高累积分数的班级标签是小组的最终决定。可能存在平局,即几个类别标签使累积分数最大化,在这种情况下,需要额外的算法步骤来解决平局。基线策略包括随机挑选一个具有最大累积分数的标签。博尔达法是一位名叫让-克洛德·博尔达的法国政治家在寻求真正民主的选举制度时发明的。瑙鲁共和国和斯洛文尼亚共和国目前使用这种方式选举议员。

  • 示例 1:假设有四个候选类别标签ω= {c₁,c₂,c₃,c₄}.对于决策函数为{ 0,0 和 0 }的三个分类器,Borda 计数工作如下:每个分类器ôᵏ对标签进行排序(表 1):
+---------------+------------------+
| Classifiers   | Labels ranking   |
+---------------+------------------+
|       ô¹      |c₂ - c₃ - c₁ - c₄ |
|       ô²      |c₃ - c₁ - c₂ - c₄ |
|       ô³      |c₃ - c₂ - c₁ - c₄ |
+---------------+------------------+
Table 1: Ranks of the four candidates (labels)

然后计算每个标签的累积分数(表 2):

+---------------+------------------+
| Candidate     |      Score       | 
+---------------+------------------+
|      c₁       | 1 + 2 + 1 = 4    |
|      c₂       | 3 + 1 + 2 = 6    |
|      c₃       | 3 + 3 + 2 = 8    |
|      c₄       | 0 + 0 + 0 = 0    |
+---------------+------------------+
Table 2: Candidates and their accumulated points

Borda 计数被认为是最简单的非线性组合算法之一。在某些情况下(主要是当分类器的数量很大时),可以观察到多数人的意见和由 Borda 计数推导出的决定之间的冲突。这个问题是帕克[0]提出来的。在博尔达计数中,

由同一分类器排序的每两个连续候选之间的分数差为 1,使得所有候选等距并且以均匀的方式分布在同一轴上

这种假设并不总是有道理的。

例如,概率分类器可以为两个标签分配非常高的概率,而为第三个标签分配低概率值(例如,对于三类分类问题,后验概率为 49%、48%、3%;显然,当应用 Borda 计数组合方法时,每个候选之间有一个单位差异并不能反映现实情况和分类器的置信度水平)。

帕克主张,对排名进行加权可能会有助于减少偏见。Fishburn [1]认为,来自混淆矩阵的上下文知识可以用来估计这些权重。将这样的权重分配给候选标签被认为是统一 Borda 计数的推广,通常称为 w Borda

  • 示例 2:考虑到 m 类标签,当应用统一性时,等级为 r 的项目将被分配等于 (m-r) 的分数,但是在 w Borda 中,它可以被分配等于 (m-r)w* ᵖ的分数,其中 p =( r-1)w 是权重。下图说明了 Borda 和 wBorda 之间的区别

作者图片

行为知识空间

黄和孙[2,3]提出的行为-知识空间(BKS)方法的优点是不依赖于前提假设,如分类器输出之间的统计独立性。

根据定义,BKS 是一个 K 维空间,其中 k ᵗʰ维与 k ᵗʰ分类器相关。在每个维度 km 上,可以做出对应于ω中所有可能标签的决定。对于每个测试样本 x,我们获得一个决策向量[ôᵏ(x]//k:{ 1,..,K} 对应于 BKS 中的一个点。

对于 mᵏ 个可能点中的每个点,我们跟踪映射到该点的训练样本的数量以及它们的类别标签。

BKS 是在训练时建立的,它有个 mᵏ 个节点需要学习。因此,该方法在面板中分类器的数量或类别的数量方面都不能很好地扩展,因为可能有一些配置从未被访问过。为了决定测试样本的类别,输出[ôᵏ(x]//k:{ 1,..,K} 并映射到相应的 BKS 节点。预测标签是在该节点中出现次数最多的标签。

作者图片

结论

在本文中,我们看到了三种经典的分类器组合方法:投票系统、Borda 计数和 BKS。这些技术在许多应用中表现出良好的性能。

这篇文章是我第一篇题为“关于量词组合的见解”的文章的延续。这是从我的博士论文中摘录的,你可以在这个链接中找到。

参考

[0]j . r .帕克(2001 年)。来自混淆矩阵数据的等级和响应组合。信息融合2 (2),113–120。

[1]菲什伯恩,P. (1999 年)。偏好结构及其数字表示。理论计算机科学217 (2),359–383。

[2]黄友生、孙春英(1993 年 6 月)。多分类器组合的行为-知识空间方法。IEEE 计算机学会关于计算机视觉和模式识别的会议(第 347-347 页)。电气工程师协会。

[3]黄友生、孙春英(1995)。一种多专家联合识别无约束手写数字的方法。 IEEE 模式分析与机器智能汇刊17 (1),90–94。

用 Python 实现定量光谱分析的经典最小二乘法

原文:https://towardsdatascience.com/classical-least-squares-method-for-quantitative-spectral-analysis-with-python-1926473a802c?source=collection_archive---------19-----------------------

用经典最小二乘法寻找光谱成分

摘要。在这个简短的教程中,将解释计算光谱之间相似性的经典最小二乘法。这种方法也称为比尔法,可用于估算未知光谱中不同组分的浓度。首先,将介绍物理背景和朗伯-比尔定律,然后是经典的最小二乘理论方法和正规方程的推导。最后,将使用 Python 实现来展示一个应用程序示例,说明如何计算样品光谱中不同组分的浓度。

介绍

光谱学是研究固体、液体或气体发射、反射或散射光与波长的函数关系[1]。大多数光谱学方法因此被分类为吸收、发射或散射光谱学。一些例子是吸收、X 射线、红外和拉曼光谱等。

有时,光谱研究中的物质是未知的。如果需要知道这种物质的成分,可以将其测量光谱(查询光谱)与已知物质(成分)的光谱库进行比较,以便进行识别。为此,使用搜索算法来搜索未知光谱,该算法基于相似性度量来计算分数,从而提供最接近匹配或浓度的列表。相似性度量是量化两个对象之间的相似性的函数。在某种意义上,这种度量与距离度量相反:对于相似的对象,它们返回一个大值,而对于不相似的对象,则返回零或负值。规范化后,相似度的范围在 1(完全相似,表示对象相等)和 0(完全不相似)之间。相似性度量也是推荐系统、聚类、分类或异常检测等其他活动的非常基本的构件。
关于光谱学,有几种基于不同相似性度量的标准光谱搜索算法【2】。在下文中,经典的最小二乘法将用于识别未知物质的光谱,并获得混合物中已知物质的浓度。这种方法也称为直接最小二乘法、K 矩阵校准算法或比尔法,因为它是基于比尔-朗伯定律。

物理背景与经典最小二乘法——比尔法

比尔-朗伯定律将光的衰减与光穿过的材料的性质联系起来。它通常应用于物理和化学分析测量,并用于理解物理光学中的光衰减。比尔-朗伯定律表明,在任何给定的波长 I 下,吸光度( A )与所选波长 I 下纯物质(k)的吸光度系数和纯物质(c)的浓度成正比:

其中吸收系数(kᵢ = aᵢL)是光通过材料的路径长度(l)与纯物质在选定波长 I 下的摩尔衰减系数或吸收率(a)的乘积,这是构成这种分子“光谱”的分子特性。

Aᵢ = kᵢc 公式适用于样品中的单一纯物质或成分。当有多种吸收成分时,任何波长下的总吸光度是混合物中所有成分在该波长下的吸光度之和:

如果我们记录的不是给定波长 I 的单个值 A,而是具有 w 个点的整个吸收光谱,则最好用矩阵符号表示:

或者以更紧凑的方式

在哪里

因此,A 是我们记录的吸收光谱(也称为查询光谱,或未知光谱,因为我们还不知道它包含什么),K 是纯组分光谱的矩阵(其中这些组分的光谱值排列在列中),c 是 n 种纯物质浓度的向量。

因此,有了我们测得的未知光谱 Aᵢ的值,并知道组成混合物的纯组分光谱 Kᵢⱼ的值,我们可以找到最佳确定混合物吸光度的浓度 cⱼa。然而,因为测得的光谱和纯物质光谱包含噪声,所以一般来说,方程 A = Kc 没有精确解。但是我们仍然可以找到 c,使得乘积 Kc 尽可能接近 A,如欧几里德范数所测量的:

换句话说,我们希望找到 c,使得误差 A-Kc 的平方和最小。误差定义为测得的光谱 A 与通过乘以 K 和 c 计算的光谱之间的差值,c 将是等式 A = Kc 的最佳最小二乘解。

利用这个事实

我们误差的欧几里德范数是

为了找到此类函数的最小值,我们只需对其进行推导,将结果表达式设置为零,并求解 c。为此,我们将利用属性

其中 x 是向量,M 是对称矩阵[4]。

所以,

将该表达式设置为 0,我们得到正规方程:

其可以被求解以最终获得测量光谱和库中已知光谱之间的相似性分数,或者同样地,未知混合物中纯物质的浓度:

请注意,A-Kc 的平方和的二阶导数是一个半正定矩阵,这意味着解 c 是全局最小值(而不是最大值或鞍点)。

关于这种方法的更详细的信息可以在《用于定量分析的化学计量技术》一书中找到[5]或者在 spectroscopyonline 网页上关于 CLS 的专栏[6]。

用 Python 实现的代码和示例

首先,加载所需的 Python 包:

import numpy as np
import matplotlib.pyplot as plt
from numpy.linalg import inv

获得未知混合物中纯物质浓度的最小二乘公式定义为:

def least_sq(sample_spectrum, components): # sample_spectrum (unknown spectrum): array of w values.
   # components (known spectra): array of n (number of components) columns with w values.
   # This def returns an array of n values. Each value is the similarity score for the sample_spectrum and a component spectrum. similarity = np.dot(inv(np.dot(components, components.T)) , np.dot(components, sample_spectrum)) return similarity

接下来,我们制作了一些光谱。这些光谱将由高斯峰组成。因此高斯函数被定义为:

def Gauss(x, mu, sigma, intensity = 1):# x is an array
# mu is the expected value
# sigma is the square root of the variance
# intensity is a multiplication factor
# This def returns the Gaussian function of x return intensity/(sigma * np.sqrt(2*np.pi)) * np.exp(-0.5*((x-mu)/sigma)**2

并用它来创建三个不同的组件:

# X-axis (Wavelengths)
x_range =  np.linspace(100, 200, 1000)# Let's create three different components# Component A
mu_a1 = 120
sigma_a1 = 2
intensity_a1 = 1mu_a2 = 185
sigma_a2 = 2
intensity_a2 = 0.2gauss_a =  Gauss(x_range, mu_a1, sigma_a1, intensity_a1) + Gauss(x_range, mu_a2, sigma_a2, intensity_a2)# Component B
mu_b = 150
sigma_b = 15
intensity_b = 1
gauss_b = Gauss(x_range, mu_b, sigma_b, intensity_b)# Component C
mu_c1 = 110
sigma_c1 = 2
intensity_c1 = 0.05mu_c2 = 160
sigma_c2 = 10
intensity_c2 = 1gauss_c = Gauss(x_range, mu_c1, sigma_c1, intensity_c1) + Gauss(x_range, mu_c2, sigma_c2, intensity_c2)# Spectra normalization:
component_a = gauss_a/np.max(gauss_a)
component_b = gauss_b/np.max(gauss_b)
component_c = gauss_c/np.max(gauss_c)# How do they look?
plt.plot(x_range, component_a, label = 'Component 1')
plt.plot(x_range, component_b, label = 'Component 2')
plt.plot(x_range, component_c, label = 'Component 3')
plt.title('Known components in our mixture', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Normalized intensity', fontsize = 15)
plt.legend()
plt.show()

这导致接下来的三个不同的组件:

这三个光谱将构成我们的分量矩阵或 K 矩阵,其中光谱按行排列。

为了生成查询谱,这三个分量将被乘以一个浓度并加在一起。为了让它更真实一点,将会添加一些噪声。

# What concentrations we want them to have in our mixture:
c_a = 0.5
c_b = 0.3
c_c = 0.2# Let's build the spectrum to be studied: The mixture spectrum
query_spectra = c_a * component_a + c_b * component_b + c_c *component_c
# Let's add it some noise for a bit of realism:
query_spectra = query_spectra +  np.random.normal(0, 0.02, len(x_range))plt.plot(x_range, query_spectra, color = 'black', label = 'Mixture spectrum with noise')
plt.title('Mixture spectrum', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Intensity',  fontsize = 15)
plt.show()

得到的混合光谱看起来像:

我们的查询谱由三个已知成分(n=3)组成。因此,对于这个例子,矩阵形式的方程组看起来像:

其中 w = 1000(波长轴有 1000 个值)。因此,A 是由 1000 个值组成的向量,c 是由 3 个值(三种成分浓度)组成的向量,K 是 3×1000 矩阵。

已知 A 和 K,现在可以重新计算“未知”混合物中 3 种成分的浓度:

# Generate the components matrix or K matrix
components = np.array([component_a, component_b, component_c])# Apply Least squares
cs = least_sq(query_spectra, components)# And plot the result:plt.plot(x_range, query_spectra, color = 'black', label = 'Mix spectrum' ) # Plot the unknown spectrumplt.plot(x_range, np.dot(cs,components), color = 'red', linewidth = 2, label = 'Calculation') # Plot the calculated spectrumfor i in np.arange(len(cs)):
    plt.plot(x_range, cs[i]*components[i], label = 'c' + str(i)+ ' =               ' + str(np.round(cs[i], 3)))plt.title('Mixture spectrum and calculated components', fontsize = 15)
plt.xlabel('Wavelength', fontsize = 15)
plt.ylabel('Intensity', fontsize = 15)
plt.legend()
plt.show()

图:混合光谱(黑色)、计算光谱(红色)和计算成分光谱(蓝色、橙色和绿色)

图中图例所示的计算浓度与设定值完全一致。
注意混合物光谱没有归一化。在混合物光谱被归一化的情况下,这种归一化常数的倒数应该应用于所获得的浓度,以便具有正确的值。

下图显示了另外三个例子,其中计算的浓度与之前设定的值一致(参见图的标题)。

再举三个例子。查询光谱是使用第一光谱的浓度= (0,0.5,0.5)、第二光谱的浓度 c = (0.1,0.5,0.4)和第三光谱的浓度 c = (0.2,0.2,0.6)生成的。用最小二乘法计算的曲线以蓝色、橙色和绿色显示,其计算的浓度写在图例框中。

使用 Python 库的最小二乘法:SciPy 和 Skit-learn

或者,最小二乘问题也可以使用一些 Python 的库来解决。

以 SciPy 为例:

import scipy.optimize as optimizationx0 = np.array([1,1,1])def func(params, xdata, ydata):
    return (ydata - np.dot(xdata.T, params))**2optimization.leastsq(func, x0, args=(components, query_spectra))[0]

或使用 Scikit-learn:

import sklearn.linear_model as linear_modellinear_model.LinearRegression().fit(components.T, query_spectra).coef_

导致组分 A、B 和 C 的浓度分别为 0.48、0.30、0.20。

总结和进一步的考虑

在这个简短的教程中,使用了一种经典的最小二乘法来计算光谱之间的相似性,并展示了这种方法如何用于估算吸收光谱中不同组分的浓度(比尔法)。给出了用 Python 实现这一点的三种不同方法(基于正规方程并使用 SciPy 和 Scikit-learn 包)。重要的是,这种方法不仅可以应用于吸收光谱,还可以应用于任何种类的光谱数据,例如拉曼光谱、红外光谱等。然而,由于某些伪像和副作用的存在,在应用任何相似性度量之前,需要几个光谱预处理步骤来清理光谱[2,7]。这些步骤包括光谱的裁剪和插值、尖峰去除(见我以前的帖子)、基线扣除、平滑和光谱归一化,这些在处理弱信号(例如拉曼光谱)时特别重要。但这将是另一篇文章的主题。

Jupyter 的原版笔记本可以在 GitHub 上找到。

致谢。我要感谢豪尔赫·路易斯·希塔博士阿维纳什·米什拉安娜·索拉古伦-比斯科博士花时间校对这些笔记。

参考资料:

[1]光谱学。维基百科。https://en.wikipedia.org/wiki/Spectroscopy

[2] Khan,S. S .,& Madden,M. G. (2012 年)。拉曼光谱的新相似性度量。化学计量学和智能实验室系统114 ,99–108。

[3]在 Python 中实现五个最流行的相似性度量。https://data aspirant . com/2015/04/11/five-most-popular-similarity-measures-implementation-in-python/

[4]济科·科尔特,Chuong Do(2015 年 9 月 30 日)。线性代数复习和参考笔记。http://cs229.stanford.edu/section/cs229-linalg.pdf

[5] Kramer,R. (1998 年)。定量分析的化学计量学技术。CRC 出版社。

[6]沃克曼和马克(2010 年)。光谱学中的化学计量学:经典最小二乘法,第一部分:数学理论
http://www . spectroscopyonline . com/classic-Least-Squares-Part-I-Mathematical-Theory?id =&pageID = 1&sk =&date =

[7] Bocklitz,T. W .,Guo,s .,Ryabchykov,o .,n .,& Popp,J. (2016)。基于拉曼的分子成像和分析:生物医学应用的灵丹妙药!?。分析化学88 (1),133–151。

经典神经网络:为什么/哪些激活功能?

原文:https://towardsdatascience.com/classical-neural-net-why-which-activations-functions-401159ba01c4?source=collection_archive---------32-----------------------

权利:自有形象

今天我将教你不同的可能的激活函数以及它们在经典神经网络中的用途。

激活函数是一族函数,其目的是在层计算之后引入非线性。

事实上,如果没有激活函数,无论进行多少增强或训练,都不会出现良好的拟合(该模型不够复杂):

不合适(权利:自有图像)

这可能是该决策的界限(该模型足够复杂):

良好的拟合(权利:自有图像)

上面解释的原因只是给出了一个经验上的见解,在我写的关于神经网络层的文章中给出了更深入的解释,其中我谈到了具有一个隐藏层的连续函数的近似。

希望你相信,让我们继续前进!

Sigmoid 函数:

  • Sigmoid 是逼近阶跃函数的第一个直观的连续函数
  • 通过高梯度值,增加系数允许更清晰的近似

Sigmoid 情节(权利:自有形象)

双曲正切函数:

  • Tanh 与 Sigmoid 非常相似,但当用作输出图层的激活函数时,它允许负值
  • 它还在 0 附近具有更尖锐的过渡(即更高的梯度),而不必增加权重值

Tanh 情节(权利:自有形象)

校正线性单位函数:

  • 与 Tanh 和 Sigmoid 不同,ReLU 在权重的正值方面没有消失梯度问题
  • 它的简单性也受到高度赞扬

热卢情节(权利:自有形象)

泄漏整流线性单位函数:

  • 类似于 ReLU,但是在权重值被转移到负值的情况下,我们允许一些空间来避免渐变消失
  • 我们定义负值的方式可能存在差异(例如:指数线性单位,swish →非常有趣)

漏雷鲁情节(权利:自有形象)

显然,这些函数是常见的,列表并不详尽,但是您很少会看到其他函数,也很少会发现其他函数有用。

总结一下隐藏层中的激活函数:

  • 由于消失梯度问题,Sigmoids 和 tanh 函数有时会被避免,但它们有助于避免权重值激增。
  • 再次为了避免一些更棘手的消失梯度,漏 ReLU 有时可以用来代替 ReLU
  • 通常的做法是对所有隐藏层使用 ReLU

对于输出层中的激活功能:

  • 对于分类,例如,逻辑回归,您应该使用 sigmoid,这样您就有了增强逻辑回归的效果。
  • 如果你知道你想要接近的函数(有一个粗略的想法), ReLU 可以用作输出层激活函数,例如当你可以保证积极性并且可以只留下你的最后一个线性组合作为你的输出时。

感谢您的阅读,敬请关注,因为更多内容即将到来:经典神经网络的解释和非常好的每日文章!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

经典神经网络:什么是真正的节点和层?

原文:https://towardsdatascience.com/classical-neural-network-what-really-are-nodes-and-layers-ec51c6122e09?source=collection_archive---------10-----------------------

权利:来源

一个节点和一个层在数学上代表什么?简单易懂的幕后概念介绍。

我们之前已经讨论过激活函数,正如承诺的那样,我们将解释它与神经网络架构中的层和节点的联系。

注意,这是对经典神经网络的解释,而不是对专门神经网络的解释。尽管如此,这些知识在研究特定的神经网络时还是有用的。

好吧,说了这么多,我们开始吧。

首先,我们将以下面非常简单的神经网络(NN)结构为例。(图 1)

图一(右图:来源

  • 输入层:节点 1 → X |激活:sigmoid
  • 隐藏层:节点 1 →N1 和节点 2 → N2(从上到下)|激活:sigmoid
  • 输出层:节点 1 → M |激活
#This code is the keras implementation of the above described NNdef simple_nn():
    model = Sequential()
    model.add(Dense(2, input_dim=1, activation='sigmoid'))
    model.add(Dense(1, activation='sigmoid'))
    model.compile(loss='mean_squared_error', optimizer='sgd')
    return model

这个神经网络代表哪种功能?

给定上面的符号,我们得到下面的函数(图 2):

图 2(权利:自己的形象)

这里需要注意多种情况:

  • 神经网络的输出将总是属于[0,1]。正如我们在激活功能文章中提到的,输出层激活功能非常重要,它定义了你想要实现的模型类型(例如分类/回归等)
  • 由于只有一个由两个节点组成的隐藏层,我们最终得到一个维数为 7 的权重向量。这使得当节点数量增加时,训练变得困难。
  • 除了激活函数,操作都是线性组合。再次,激活函数引入了非线性。

为什么我们要使用线性组合和这些类型的激活函数?

首先,尽管深度学习(多层神经网络的研究)本身是一种研究,但它与经典的机器学习有着相同的目标:“从数据点(大部分时间)接近特定的底层模型/分布”。因此,神经网络的目标也是逼近一个分布,即一个函数,但如何实现呢?这里介入一些关于分析的基础知识,振作起来!

为了简单起见(如果你有兴趣知道更一般的解释,可以联系我),我们将改为下面的架构。下面是它的功能(图 3):

图 3(权利:自己的形象)

我们先从一个从实数到实数的连续函数开始。让我们为自己设定一个接近这样一个函数的目标。开始的标准方法是首先画出我们的神经网络所代表的函数(图 3)。由于我们不需要任何具体的数据来解释这个想法,我们将不训练神经网络,而只是简单地任意分配权重(图 4)。

图 4(权利:自己的形象)

下面是曲线图(图 5):

图 5(权利:自己的形象)

惊喜!这是什么形状?一个长方形!!!

所以我们的神经网络实际上是在模仿一个矩形的分布(或多或少)。对于一些人来说,这似乎并不特别,但对于其他一些听说过黎曼积分和阶梯函数的人来说,他们或多或少会明白我的意思。确切地说,是像神经网络这样的阶跃函数对连续函数的近似(不完全是阶跃函数,但是求和完成了这项工作)。

还有几件事需要注意:

  • 矩形边缘的锐度由 X 前面的标量定义,高值导数的位置由加到乘积上的标量定义。
  • 两个节点足以构成一个矩形,因此要实现连续函数,我们只需添加节点!(在奇数个节点的情况下,我们将简单地使用矩形和阶梯函数)

尽管这很难描述,但在更高维度中,连续函数的近似值几乎是一样的(除了我们重新调整值的那一步)。

既然我们已经看到了这样的近似,我们可以对神经网络逼近分布(即使是非连续的)的能力充满信心。但这种解释仍然缺乏一些东西,我们任意地给我们的神经网络一些准确的权重,但不幸的是,我们无法在一般的数据集这样做,因为我们忽略了分布。这里介入了优化技术,如著名的 SGD(随机梯度下降)或批处理 GD(等等)。假设这些优化确实让我们得到了一个足够接近的解决方案,这将意味着我们超出了我们给出的原始权重(对于矩形)。显示上面的例子(矩形)在某种程度上给出了精确度的下限,即使提到的技术看起来是最佳的,权重的优化可能不一定收敛于该技术的最佳值,但会再次超过它。

感谢您的阅读,敬请关注后续文章。此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

经典神经网络:损失函数景观看起来像什么?

原文:https://towardsdatascience.com/classical-neural-networks-what-does-a-loss-function-landscape-look-like-f69518270223?source=collection_archive---------29-----------------------

(权利:来源)

有没有想过我们在什么样的拓扑结构上优化我们的神经网络?现在你知道了!

每个神经网络的目标/损失函数都要最小化!但是这个损失函数到底是什么样子的呢?今天,我们将展示两个不同神经网络的损失函数(N1,N2:图 1)。

图 1(权利:自己的形象)

我们在训练时将损失函数的族是 MSE(均方误差)。尽管其他损失函数族可能会很有趣,但为了便于说明,我们将坚持使用这一个。

对于特别好奇的人来说,我们将训练 N2 神经网络(训练部分不是很有趣,因为我们想要的是一个风景图)这个分布(图 2:是的,我懒得添加噪声)

图 2(权利:自己的形象)

和 N1 神经网络(图 3):

图 3(权利:自己的形象)

作为输入函数的损失函数值(N2)

让我们先简单地画出损失函数本身(图 4)。

图 4(权利:自己的形象)

要做的说明:

  • 我们看到,在[-1,1]中,x=-2 和 y 附近的误差值特别高。
  • 除了看到损失函数是什么样子,拥有这样的插图对于想要有目的地攻击这样的神经网络的人来说是有用的!对于对手来说,这可能是试探性的第一步。

作为权重函数的损失函数值(N1)

能够将损失函数视为输入的函数固然很好,但这并不是人们感兴趣的。看到风景进行优化肯定更适合制作建筑!正如我在之前的文章中提到的,N1 有 7 个权重标量需要优化。绘制一个 7 维空间对于我们的理解来说只有很小的意义,所以我们将任意地投射到 2 维空间。请注意,我们固定了输入,因此变量只有两个权重。(图 5)

图 5(权利:自己的形象)

这是一个数据点的情况。需要注意以下几点:

  • 如果我们在该图上优化(最小),任意选取两个权重,那么一个数据点的损失将明显减少。
  • 现在,为了最小化这样一个函数,任何简单的梯度搜索就足够了,甚至不需要 SGD,因为它是一个严格的凸分布,但因为它有一个平台,我们需要一些动量下降而不是一般下降来获得足够大的梯度方向。

当使用 MSE 作为损失度量时,可以对多个数据点进行这样的绘图。由于权重的数量,能够描绘一般神经网络中的损失更加困难,但这可以是一种在训练时不随机尝试优化算法的方法,而是理解您想要接近的底层数据模型。我再次希望这有助于人们理解机器学习不是黑魔法,而是真正需要分析!超参数发现不一定是随机试验。

感谢阅读!敬请关注更多文章!此外,点击这个链接(指向联盟计划)真的会帮我解决问题!您只需完成一些快速任务(只需等待和激活通知),所有这些将真正帮助我了解更多未来的硬件相关内容!

分类、异常检测和预测

原文:https://towardsdatascience.com/classification-anomaly-detection-and-prediction-68b046d9c436?source=collection_archive---------40-----------------------

为了准确识别各种网络攻击,必须仔细分析底层系统的行为和生成的数据。

因此,有必要分析和研究现有的和新开发的网络安全系统,以确定其弱点,并通过整合机器学习算法提出可能的改进措施。现有的基于特征的检测和行为分析系统为攻击者和入侵者的工作提供了便利。他们可以通过隐藏的门进入系统。

基于网络入侵和检测的异常在受保护网络中起着至关重要的作用。

机器学习和数据挖掘算法可以通过代表性的学习算法对数据进行进一步分类。这使得系统能够自动识别从原始数据中识别和分类特征所需的表示。它们用于处理和分析生成的大数据、检测异常、检测威胁、对特征进行分类等等。例如,可以使用代表性的学习算法对熟悉和未知的单元进行分类。这种方法需要一个包含正常和异常样本的已标记数据集来构建用于分类未来数据点的预测模型。当涉及到检测异常时,SVM(支持向量机)算法可以在学习区域捆绑正常的数据行为。

支持向量机(维基百科)

这些方法对于实时系统是有用的,但是具有非常高的错误警报百分比,并且会破坏底层系统的性能。

还有其他使用空间和时间特征的方法,这些空间和时间特征是通过非侵入式传感器模态的正常活动来学习的,然后被输入特征。DeepFall 框架是一种使用自动编码器学习深度函数的方法。有一个基于 RNN(递归神经网络)的时间序列异常检测器,它由一系列时间序列和每个异常的一组时间和空间特征组成。这类似于使用非侵入式传感器模态从正常活动中学习空间或时间特征,然后将特征输入神经网络的另一种方法。

对于我个人的研究,我试图建立一个 LSTM(长短期记忆——一种特殊的 RNN,能够学习长期依赖关系)自动编码器,在许多信号中找到异常并进行分类。我认为分析博客异常将是这个实验的良好开端,所以我在网络服务器的帮助下做了这件事。如果信号与其过去和未来之间的偏差很大,则事件会影响其发生的概率。为此,最常用的算法是支持多种数据类型的受监控神经网络(受监控神经网络)。

视觉发现异常检测也可以通过视觉发现来实现。检测视频异常的方法基于模型的类型和检测的标准进行检查,并分为两类:基于深度学习的方法和不基于深度学习的方法。异常检测系统通过考虑各种数据类型(如视频、音频、文本、图像等)来检测计算机和工作中的问题。

另一个例子是变分自动编码器(UAE)来检测时间序列中的异常。一旦安装,模型的编码器部分可用于编码和压缩数据序列,这又可用作预测新类别预测模型(例如,时间序列的预测模型)的基础。

根据我的个人经验,在预测异常检测模型和支持人为干预以获得真实和准确结果所需的解释之间架起一座桥梁。

引用来源

分类基础:Iris 数据集演练

原文:https://towardsdatascience.com/classification-basics-walk-through-with-the-iris-data-set-d46b0331bf82?source=collection_archive---------11-----------------------

从 iris 数据集中学习使用引导代码进行分类的基础知识

桑迪·米勒在 Unsplash 上拍摄的照片

当我第一次学习如何编码时,我会在不同的数据集上练习我的数据技能,以创建迷你 Jupyter 笔记本参考指南。由于我发现这是一个非常有用的工具,我想我应该开始分享代码走查。希望这对那些学习使用 Python 进行数据科学的人来说是一个积极的资源,并且可以在未来的项目中参考。完整代码可在 Github 上获得。

正在设置

第一步是从 scikit-learn python 库中导入预加载的数据集。更多关于“玩具”数据集的信息可以在这里找到。数据描述还将提供关于特性、统计数据和来源的更多信息。

from sklearn.datasets import load_iris#save data information as variable
iris = load_iris()#view data description and information
print(iris.DESCR)

数据将预先保存为带有“数据”和“目标”的字典,每个键都与一个列表数组配对,作为。最初,信息将像这样输出:

{'data': array([[5.1, 3.5, 1.4, 0.2],
        [4.9, 3\. , 1.4, 0.2],
        [4.7, 3.2, 1.3, 0.2],
        [4.6, 3.1, 1.5, 0.2],
        [5\. , 3.6, 1.4, 0.2],
        [5.4, 3.9, 1.7, 0.4],
        [4.6, 3.4, 1.4, 0.3] ...
'target': array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ...}

将数据放入数据框

特征数据

为了更容易地查看数据,我们可以使用 Pandas 库将这些信息放入数据框中。让我们首先创建一个数据框来存储关于花的特征的数据信息。

import pandas as pd#make sure to save the data frame to a variabledata = pd.DataFrame(iris.data)
data.head()

使用 data.head()将自动输出前 5 行数据,但是如果我们还可以在括号中指定我们想要的行数,data.head(10)。

现在,我们有了一个包含虹膜数据的数据框,但是没有清楚地标记列。查看我们上面打印的数据描述,或者参考源代码可以告诉我们更多关于特性的信息。在文档中,数据特征如下:

  • 以厘米为单位的萼片长度
  • 以厘米为单位的萼片宽度
  • 以厘米为单位的花瓣长度
  • 花瓣宽度厘米

让我们重命名这些列,这样功能就清晰了。

data.columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width']#note: it is common practice to use underscores between words, and avoid spacesdata.head()

目标数据

既然与要素相关的数据已经整齐地放在数据框中,我们就可以对目标数据做同样的事情了。

#put target data into data frame
target = pd.DataFrame(iris.target)#Lets rename the column so that we know that these values refer to the target values
target = target.rename(columns = {0: 'target'})
target.head()

目标数据框只有一列,它给出了值 0、1 和 2 的列表。我们将使用来自特征数据的信息来预测一朵花属于组 0、1 还是 2。但是这些数字指的是什么呢?

  • 0 是鸢尾
  • 1 是虹膜杂色
  • 2 是北美鸢尾

探索性数据分析

为了帮助我们更好地理解我们的数据,让我们首先合并我们刚刚创建的两个数据框。这样我们可以一起看到花的特征和分类。

df = pd.concat([data, target], axis = 1)#note: it is common practice to name your data frame as "df", but you can name it anything as long as you are clear and consistent#in the code above, axis = 1 tells the data frame to add the target data frame as another column of the data data frame, axis = 0 would add the values as another row on the bottomdf.head()

现在我们可以清楚地看到单朵花的特征和它的类别之间的关系。

数据清理

检查你的数据,确保它是干净的,并开始探索特征和目标变量之间的关系,这是非常重要的。因为这是一个相对简单的数据集,所以不需要做太多的清理工作,但是让我们来完成这些步骤。

  1. 看数据类型
df.dtypes

=带小数的数字(1.678)
int =不带小数的整数或整数(1,2,3)
obj =对象、字符串或单词(' hello')
这些数据类型后的 64 是指该值占用多少位的存储空间。你会经常看到 32 或 64。

在这个数据集中,数据类型都已准备好进行建模。在某些情况下,数值将被编码为对象,因此我们必须在执行统计建模之前更改数据类型。

2.检查缺失值****

df.isnull().sum()

该数据集没有丢失任何值。虽然这使得建模容易得多,但通常情况并非如此——现实生活中的数据总是杂乱无章的。如果有缺失值,您可以删除有缺失值的数据行,或者有几个选项可以用来填充缺失的数字(使用列的平均值、前一个值……)。

3.统计概述****

df.describe()

这使我们能够快速浏览数据。我们可以通过查看每列相对于平均值的最小值和最大值来检查异常值。花点时间浏览这个图表,开始理解数据的分布。

肉眼观察

EDA 过程的下一步是开始可视化一些关系。

相关

Seaborn 库有一个很好的热图可视化工具,可以用来映射特性之间的相关性。数字越大,两个元素之间的相关性越大。高的正相关表示两个元素具有正的线性关系(一个增加,另一个也增加),低的负相关表示负的线性关系(一个增加,另一个减少)。

import seaborn as sns
sns.heatmap(df.corr(), annot = True);#annot = True adds the numbers onto the squares

花瓣长度和宽度与目标最相关,这意味着随着这些数字的增加,目标值也会增加。在这种情况下,这意味着类别 2 中的花通常比类别 0 中的花具有更长的花瓣长度和宽度。萼片宽度最不相关,表明类别 0 中的花比类别 2 中的花具有最大的萼片宽度。我们还可以看到一些特征之间的相互关系,例如花瓣的宽度和长度也高度相关。这些信息不一定是分析数据的最佳方式,但它让我们开始看到这些关系。

散点图

为了开始查看特征之间的关系,我们可以创建散点图来进一步可视化不同种类的花与萼片和花瓣数据的关系。

# The indices of the features that we are plotting (class 0 & 1)
x_index = 0
y_index = 1# this formatter will label the colorbar with the correct target names
formatter = plt.FuncFormatter(lambda i, *args: iris.target_names[int(i)])plt.figure(figsize=(5, 4))
plt.scatter(iris.data[:, x_index], iris.data[:, y_index], c=iris.target)
plt.colorbar(ticks=[0, 1, 2], format=formatter)
plt.xlabel(iris.feature_names[x_index])
plt.ylabel(iris.feature_names[y_index])plt.tight_layout()
plt.show()

三类花的萼片宽度与长度的关系。Virginica 和 versica 在萼片大小上看起来相对相似,但 setosa 在左侧创建了自己的簇。

现在让我们创建相同的散点图来比较花瓣数据点。

x_index = 2
y_index = 3# this formatter will label the colorbar with the correct target names
formatter = plt.FuncFormatter(lambda i, *args: iris.target_names[int(i)])plt.figure(figsize=(5, 4))
plt.scatter(iris.data[:, x_index], iris.data[:, y_index], c=iris.target)
plt.colorbar(ticks=[0, 1, 2], format=formatter)
plt.xlabel(iris.feature_names[x_index])
plt.ylabel(iris.feature_names[y_index])plt.tight_layout()
plt.show()

可视化花瓣长度和宽度之间的关系。我们可以看到,花开始单独成簇,与花瓣大小相关的元素可能是类的一个强有力的决定因素。

建模

既然我们已经清理和探索了数据,我们就可以开始开发模型了。我们的目标是创建一个逻辑回归分类模型,根据花瓣和萼片的大小来预测花属于哪一类。

#divide our data into predictors (X) and target values (y)
X = df.copy()
y = X.pop('target')

列车测试分离

一旦我们从目标中分离出特性,我们就可以创建一个训练和测试类。顾名思义,我们将在训练集上训练我们的模型,并在测试集上测试模型。我们将随机选择 80%的数据用于我们的培训,20%作为测试。

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=1, stratify = y)'''
by stratifying on y we assure that the different classes are represented proportionally to the amount in the total data (this makes sure that all of class 1 is not in the test group only)
'''

使标准化

随着 X 值在训练和测试之间分离,现在我们可以标准化这些值。这将数字放在一个一致的范围内,同时保持它们之间的比例关系。

from sklearn.preprocessing import StandardScalerscaler = StandardScaler()
X_train = pd.DataFrame(scaler.fit_transform(X_train), columns=X_train.columns)
X_test = pd.DataFrame(scaler.transform(X_test), columns=X_test.columns)

基线预测

基线是模型实现前预测类的概率。如果数据被平均分成两类,就有 50%的机会将一个元素随机分配给正确的类。我们模型的目标是改进这个基线,或随机预测。此外,如果存在严重的类别不平衡(如果 90%的数据在类别 1 中),那么我们可以改变每个类别的比例,以帮助模型更准确地预测。

df.target.value_counts(normalize= True)

这个模型的基线预测是 1/3

逻辑回归模型

from sklearn.linear_model import LogisticRegression#create the model instance
model = LogisticRegression()#fit the model on the training data
model.fit(X_train, y_train)#the score, or accuracy of the model
model.score(X_test, y_test)
# Output = 0.9666666666666667#the test score is already very high, but we can use the cross validated score to ensure the model's strength 
from sklearn.model_selection import cross_val_scorescores = cross_val_score(model, X_train, y_train, cv=10)
print(np.mean(scores))
# Output = 0.9499999999999998

在没有任何调整或优化的情况下,该模型已经表现得非常好,测试得分为 0.9667,交叉验证得分为 0.9499。这意味着该模型在大约 95%的时间里预测了花的正确类别。远高于 33%的基准线!

理解预测

通常会对参数进行大量的微调和实验,以找到得分最高的模型。然而,由于这个数据集是简单明了的,我们现在可以继续,开始看看模型是如何做出预测的。

系数

df_coef = pd.DataFrame(model.coef_, columns=X_train.columns)
df_coef

逻辑回归中的系数通常有点难以解释,但我们可以了解每个特征在决定一朵花是否属于该类时的影响程度。例如,花瓣长度几乎不是一朵花是否属于第一类的决定性因素,但花瓣宽度是第二类的一个强有力的预测因素。

预测值

我们还可以将模型预测的值与实际值进行比较。

predictions = model.predict(X_test)#compare predicted values with the actual scores
compare_df = pd.DataFrame({'actual': y_test, 'predicted': predictions})
compare_df = compare_df.reset_index(drop = True)
compare_df

预测几乎完美地排列在一起,只有一次模型错误地预测一朵花属于第 1 类,而它实际上属于第 2 类。

混淆矩阵

为了更仔细地观察模型做出的预测,我们可以使用混淆矩阵。在混淆矩阵中,预测值是列,实际值是行。它可以让我们看到模型在哪里做出了正确和错误的预测,如果它预测错误,我们可以看到它错误地预测了哪个类。

from sklearn.metrics import confusion_matrix
pd.DataFrame(confusion_matrix(y_test, predictions, labels=[2, 1, 0]),index=[2, 1, 0], columns=[2, 1, 0])

我们可以看到,0 类和 1 类都被正确预测了 10 次,但在一个实例中,模型错误地将 2 类标记为 1 类。

分类报告

检查模型性能的另一个好方法是查看分类报告。它显示了精确度、召回率、f1 分数和准确度分数,下面是对这些特性的简要说明。

  • 精度**:在预测的海滨鸢尾花总数(10)中,正确预测的海滨鸢尾花数(10)。预测海滨鸢尾的精度=10/10 = 1.0
  • 回忆**:在实际的黑鸢尾数量中,正确预测的黑鸢尾数量。回忆= 9/10 = .9
  • F1 得分:这是精确度和召回率的调和平均值。公式为 F1 得分= 2(精度召回)/(精度+召回)
  • ****准确性:将所有类别的所有正确预测相加,然后除以预测总数。29 个正确预测/30 个总值= 0.9667 的准确度。
from sklearn.metrics import classification_report
print(classification_report(y_test, predictions))

预测概率

使用下面的代码,我们可以查看每行数据被分配到三个类之一的概率。默认情况下,模型会将该项分配给概率最高的类。如果我们想要调整准确度或精度,我们可以通过更改阈值来实现,在将预测概率分配给该类之前,该阈值必须有多高。

在这种情况下,错误地将一朵花分配给另一个类别不会产生后果,但用于检测癌细胞的模型会调整其模型以“假设最坏的情况”,并更经常地将其分配为真正的癌细胞。这在许多情况下使用,当过度谨慎比错误地将细胞标记为安全和健康更好时。

probs = model.predict_proba(X_test)#put the probabilities into a dataframe for easier viewing
Y_pp = pd.DataFrame(model.predict_proba(X_test), 
             columns=['class_0_pp', 'class_1_pp', 'class_2_pp'])
Y_pp.head()

结论

希望这个演练有助于展示数据科学项目过程中的一些主要步骤。当然,这并不是对该数据集可以采取的步骤的详尽列表,但它旨在仔细展示分类的一些重要步骤。

这是一个经典的数据集,因为它相对简单,但这里强调的步骤可以应用于任何类型的分类项目。请关注未来更简单(和高级)的数据集演练!

寻找下一步?阅读关于回归的基础知识,一个预测汽车销售价格的数据科学项目。

不平衡数据集中的分类。

原文:https://towardsdatascience.com/classification-framework-for-imbalanced-data-9a7961354033?source=collection_archive---------10-----------------------

理解和利用不平衡数据。

介绍

C 分类是机器学习中的一种监督学习,处理将数据分类成类。监督学习意味着模型将输入与其匹配的输出相结合来训练模型,该模型稍后可以在没有输出的情况下对一组新数据做出有用的预测。分类问题的一些例子包括:邮件中的垃圾邮件检测、订阅分析、手写数字识别、生存预测等。它们都涉及利用训练数据来理解输入变量如何与输出(目标)变量相关的分类器的使用。

米切尔·施瓦茨在 Unsplash 上的照片

类别不平衡指的是分类中的一个问题,类别的分布是偏斜的。这种不平衡从轻微到极端都有。

这是一个问题,因为大多数分类算法对少数类的预测精度较低,因为它们是在假设类之间存在平衡的情况下运行的。

类别不平衡的一个例子是信用卡欺诈检测。在这种情况下,类别是欺诈非欺诈。大多数交易都是不欺诈,因此欺诈阶层是少数阶层。少数类预测的准确性低是有问题的,因为它是最重要的类。

这篇博客涵盖了处理不平衡数据集中的分类问题的步骤。包含所有代码的 Github 库可以在这里找到。

资料组

使用的数据来自 UCI 机器学习知识库。该数据与葡萄牙银行机构的营销活动相关。分类的目标是预测客户是否会订阅定期存款(变量 y )。

有效的模式有助于提高营销活动的效率,因为可以将更多的精力放在订阅机会高的客户身上。

数据示例:

可视化目标变量(y ),以观察类别不平衡:

图片作者。

圆圈的大小代表每个类的值计数。显然存在极端的阶级不平衡。这将在预处理部分处理。

预处理

预处理包括以下步骤:

输入空值

需要处理缺失值,因为它们可能会导致错误的预测,还可能导致任何给定模型的高偏差。

分类特征将用列模式估算,离散数字特征用列中位数估算,连续数字特征用列平均数估算。

处理异常值

离群值是许多机器学习算法的问题,因为它们会导致重要见解的丢失或扭曲真实结果,最终导致模型不太准确。

将使用第 10 个和第 90 个百分位数对异常值进行剪裁。

特征生成

从现有要素生成新要素增加了在模型训练期间可访问的新信息,因此提高了模型精度。

缩放数值变量

标准定标器对数字特征进行标准化,以消除不同测量单位带来的差异。

编码分类变量

大多数机器学习和神经网络算法需要数字输入,因此为了利用分类特征,我们必须重新映射它们。

应用一种热编码技术。它获取一个包含分类数据的列,然后将该列拆分成多个列。条目被 0 和 1 替换,这取决于哪一列有什么值。

对不平衡数据集进行重采样。

重采样包括创建不平衡数据集的新版本。

重采样有两种主要方法:

  • 过采样:随机复制少数类中的条目。适用于小型数据集。
  • 欠采样:从多数类中随机删除条目。适用于大型数据集。

我们的数据集有 41188 行和 21 列,因此使用过采样是安全的。

预处理类:

预处理类代码。

# calling the class and its methodsd = DataPrep()
path = '/content/bank-additional-full.csv'
data = d.read_data(path)
data = d.treat_null(data)
data = d.outlier_correcter(data)
data = d.generate_features(data)
data = d.scaler(data)
print('After scaling:', data.shape)
data = d.encoder(data)
data = d.over_sample(data)
data.head()

输出:

请注意分类和数字列中的变化。

建模

照片由亨特·哈里特Unsplash 上拍摄

从预处理到进行预测,我们首先使用训练和验证数据来训练和评估我们的模型。但首先,我们必须分离目标和预测变量,然后将它们分成训练集、验证集和测试集。测试集不是单独提供的,因此我们从数据集中检索它。

# split the data to have the predictor and predicted variables
x = data.drop(['y'], axis = 1)
y = data[['y']]# Encode labels in target df.
encoder = LabelEncoder()
y = encoder.fit_transform(y)# get the sets
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.10, random_state = 42)x_train, x_val, y_train, y_val = train_test_split(x_train ,y_train, test_size = 0.20, random_state = 42)

有待探索的算法:

  • XGBoost :

XGBoost 分类器是一种基于树的集成学习算法,是梯度推进机器的一种实现。

它针对速度和性能进行了优化。

  • 多层感知器:

多层感知器(MLP)是一类前馈人工神经网络。它至少由三层节点组成:输入层、隐藏层和输出层。

它区分不可线性分离的数据的能力是我们探索它的原因。

  • 逻辑回归:

逻辑回归是一种简单但非常有效的分类算法,它使用对数比值比来预测组成员。

它的简单性和使用对数比值比代替概率是我们探索它的原因。

交叉验证

交叉验证是一种重采样程序,用于在有限的数据样本上评估机器学习模型。

使用的技术:

  • K-fold : K-Fold CV 是将给定的数据集分成 n 个折叠,其中每个折叠在某个点用作测试集,其余的用作训练集。
  • 分层 K 折叠:分层 K 折叠将数据打乱,然后将其分成 n 个折叠,每个折叠都用作一个测试集。分层保持数据集目标之间的平衡(每个分层折叠保持目标类的相同比率)。这种策略在不平衡数据的情况下是最好的。

在这两种技术中,默认的评分标准是 准确度分数 (做出的正确预测数除以做出的预测总数)。

实施:

现在,我们使用这些技术在训练数据上观察我们的模型性能。

# using grid search to find optimal parametersregressor = LogisticRegression()
grid_values = {'penalty': ['l1','l2'], 'C': [0.001,0.01,0.1,1,10,100,1000]}model = GridSearchCV(regressor, param_grid=grid_values)
model.fit(x_train,y_train)
print(model.best_score_)
print(model.best_params_)

# using the optimal parametes printed out
regressor = LogisticRegression(C = 1000, penalty= 'l2')
regressor.fit(x_train, y_train)# using kfolds
print('Logistic Regression mean accuracy score using kfold:', overall_score(regressor, x_train))# stratified KFold
print('Logistic Regression mean accuracy score using Stratifiedkfold :', overall__stratified_score(regressor, x_train))

输出:

Logistic Regression mean accuracy score using kfold: 0.742437522099093
Logistic Regression mean accuracy score using Stratifiedkfold : 0.7420879248958712

对 XGBoost 和 MLP 重复相同的过程。

xgb = XGBClassifier(silent = True,max_depth = 6, n_estimators = 200)
xgb.fit(x_train, y_train)# using kfolds
print('xgb mean score on the original dataset (kfold):', overall_score(xgb, x_train))# stratified KFold
print('xgb mean score on the original dataset (stratified kfold):', overall__stratified_score(xgb, x_train))

mlp = MLPClassifier() # working with default parameters
mlp.fit(x_train, y_train)# using kfolds
print('mlp mean score on the original dataset (kfold):', overall_score(mlp, x_train))# stratified KFold
print('mlp mean score on the original dataset (stratified kfold):', overall__stratified_score(mlp, x_train))

在所有的 3 个模型中,K-fold 产生了最高的准确性,尽管它随分层的变化是如此之小。如前所述,分层最适合不平衡的数据,但我们已经在预处理过程中对数据进行了重新采样,使其不再有用。

进一步评估

我们可以通过验证集探索其他准确性指标。

  • ROC — ROC 曲线是针对 0.0 和 1.0 之间的多个不同候选阈值的真阳性率(y 轴)与假阳性率(x 轴)的关系图。
  • 精度和召回 精度是正确鉴定的阳性结果的数量除以所有阳性结果的数量,包括那些没有正确鉴定的阳性结果,召回是正确鉴定的阳性结果的数量除以所有本应被鉴定为阳性的样本的数量。
  • F1 分数 — F1 分数是对测试准确性的衡量。它是根据测试的精确度和召回率计算出来的。

当每类的观察值大致相等时,应使用 ROC 曲线。当存在中等到大的类别不平衡时,应该使用精确召回曲线。

由于我们对数据进行了重新采样以保持平衡,ROC 是我们的最佳选择。

ROC 图:实施:

这些图在其他模型上实现:RandomForest、CatBoost 和 LGBM,它们可以被编辑以适合任何模型。(代码可在github链接中共享)。

from sklearn.datasets import make_classification
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score#predict probabilities
ns_probs = [0 for _ in range(len(x_val))]  # no skill classifier
f_prob = forest.predict_proba(x_val)
c_prob = cat.predict_proba(x_val)
l_prob = lgbm.predict_proba(x_val)# keep probabilities for the positive outcome only
f_prob = f_prob[:, 1]
c_prob = c_prob[:, 1]
l_prob = l_prob[:, 1]# calculate scores then print them
f_auc = roc_auc_score(y_val, f_prob)
c_auc = roc_auc_score(y_val, c_prob)
l_auc = roc_auc_score(y_val, l_prob)
ns_auc = roc_auc_score(y_val, ns_probs)print('RandomForest:', f_auc)
print('CatBoost: ', c_auc)
print('LGBM:', l_auc)# calculate roc curves
f_fpr, f_tpr, _ = roc_curve(y_val, f_prob)
c_fpr, c_tpr, _ = roc_curve(y_val, c_prob)
l_fpr, l_tpr, _ = roc_curve(y_val, l_prob)
ns_fpr, ns_tpr, _ = roc_curve(y_val, ns_probs)# plot the roc curve for the model
plt.figure(figsize = (12,7))
plt.plot(f_fpr, f_tpr, marker='.', label='random forest')
plt.plot(l_fpr, l_tpr, marker='.', label='lgbm')
plt.plot(c_fpr, c_tpr, marker='.', label='catboost')
plt.plot(ns_fpr, ns_tpr, linestyle='--', label='No Skill')plt.legend()
plt.title('ROC curves for different models')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')

输出:

图片作者。

曲线下的面积越大,精确度越高。

无技能分类器是一种不能区分类别的分类器,它在所有情况下都会预测随机类别或恒定类别。(我们的基准)。

预言

使用 MLP,我们最初 3 个模型中表现最好的。

# mlp
pred = mlp.predict(x_test)
pred_df = pd.DataFrame(pred)
pred_df.columns = ['y']
pred_df.to_csv('pred_df.csv') # export to a csv file

结论

我们可以继续研究我们的分类问题,探索不同的技术,比如降维,仅仅是为了获得一个性能更好的模型。但是现在,我们知道拥有不平衡的数据并不妨碍我们进行预测,它只是召唤我们使用适当的技术来避免对少数类的糟糕预测。

附言:向我在 10academy.org 的所有同学和导师表示敬意,感谢他们无尽的支持。

参考

  1. 如何在 Python 中使用 ROC 曲线和精确召回曲线进行分类

2.了解 AUC — ROC 曲线。

3.XGBoost 算法:愿她统治长久!

4.处理不平衡数据。

  1. XGBoost 文档。

6.不平衡数据:如何处理不平衡分类问题。

7.为什么不平衡分类很难?

人们应该知道的分类度量数据

原文:https://towardsdatascience.com/classification-metrics-everyone-should-know-b67fd0044c0c?source=collection_archive---------46-----------------------

了解数据科学成功的基础!

学习分类标准可能是一个模糊的混乱。☁️:有很多衡量标准。很多听起来很像。有时同一个东西有两个名字。有时有五个。🤦‍♀️🤦‍♂️

这一系列文章旨在拨开迷雾。🌤这是一个帮助您理解、使用和记住七个最常见的分类标准的指南。

今天我们将探索每个人都需要的基础。数据科学家和统计学家必须先打好基础,然后才能进入更高级的指标。😀

我们开始吧!🚀

雾蒙蒙的。资料来源:pixabay.com

在二元分类问题中有两种可能的结果:真或假,1 或 0,买或不买,感染或不感染,等等。在本文中,我们将重点关注二进制分类,因为它很常见,而且这种东西与两个结果类就足够混淆了。😉

我们要查看的指标在 scikit-learn Python 包中。每个函数都是从 sklearn 中导入的。指标模块模块。

我们将使用一些假设的分类任务来说明这些指标是如何工作的。让我们从预测网站访问者是否会在 Jeff 的牛逼夏威夷衬衫店购买衬衫开始吧!🏝+🌺+👕+💵

混淆矩阵

混淆矩阵是构建指标的基础。它显示了你的模型的预测有多少是正确的,有多少是不正确的,由实际的积极和消极的结果组织。

矩阵的一个轴是现实生活中的结果——正面和负面的情况。在我们的例子中,如果访问者购买了一件衬衫,这是一个实际的积极因素。😀如果游客不买衬衫,这是一个实际的负面影响。☹️

 **Predicted Label**        
                Predicted Positive    Predicted Negative
  **True Label       ** Actual Positive     
Actual Negative 

另一个轴是你的模型的预测。如果你的模型预测到访问者会买一件衬衫,那就是一个积极的预测。如果你的模型预测访客不会买衬衫,那就是负面预测。

结合预测和实际结果,你会得到四个象限:

真阳性
真阴性
假阳性
假阴性

或简称 TP、TN、FP、FN 。😁

 Predicted Positive    Predicted Negative
Actual Positive            **TP**               **FN**
Actual Negative            **FP**               **TN**

让我们将这四组分解开来:

指模型预测正确的情况。指模型预测错误的情况。你希望你的模型预测准确,所以你希望更多的和更少的。👍

如果这个群体在名字中有阳性,那么这些人就是模型预测会购买的人。如果该组的名称中有负数,则这些是模型预测不会购买的人。

理解这四个群体是关键。在继续之前,确保你能用自己的话解释这四个象限。☝️

请注意,其他混淆矩阵图可能会以不同的顺序显示行和列。可惜没有标准顺序。☹️

下面是从混淆矩阵创建四个结果变量的 Python 代码(导入了 numpy 库,从 sklearn.metrics 导入了混淆矩阵):

tn, fp, fn, tp = confusion_matrix(y_test, predictions).ravel()

这段代码将基础事实( y_test )和预测传递给混淆 _ 矩阵函数,用拉平结果。ravel()然后把结果解包成四个变量。

您可以使用 scikit-learn 的新plot _ confusion _ matrix函数绘制更漂亮的混淆矩阵图。向凯文·马卡姆致敬。🧢

这里有一个混淆矩阵的例子:

下面是我用来制作这个混淆矩阵的代码(带有作为 plt 导入的 matplotlib.pyplot 和从 sklearn.metrics 导入的 plot_confusion_matrix ):

plot_confusion_matrix(
    clf, 
    X_test, 
    y_test, 
    values_format=’d’, 
    display_labels=[‘Bought’,’Didn\’t buy’], 
    cmap=plt.cm.coolwarm
);

请注意,您必须首先通过评估程序。我添加了一些额外的参数来显示标签,使情节更漂亮。如果您想更改输出值,使它们不是科学记数法格式,那么values_format参数可以解决您的问题。🎉

现在让我们看看如何使用混淆矩阵中的这四个数字来制作我们最常用的分类度量。

少雾。资料来源:pixabay.com

准确(性)

术语准确性在一般对话中通常用来表示“良好的性能”,但是在分类度量领域中它有一个特定的定义。准确度分数回答了以下问题:

你猜对了几次?

精确度的公式为:

准确度= (真阳性+真阴性)/所有观测值

或者,简称:

精度 = (TP + TN) /全部

以下是我们的模型预测游客是否会在杰夫的夏威夷衬衫店购物的假设结果。🌺👕

困惑矩阵#1:

 Predicted Positive    Predicted Negative
Actual Positive          80  (TP)            20 (FN)
Actual Negative          50  (FP)            50 (TN)

该模型预测了 130 次购买和 70 次不购买。实际上有 100 次购买和 100 次不购买。

我们来计算一下准确率得分。将真阳性真阴性相加,并除以观察总数。

(80 + 50 ) / 200

看起来模型正确预测了 200 个案例中的 130 个,准确率为 65%。听起来不可怕。😀

但是我们并不真正知道我们的模型做得有多好,直到我们把它与另一个模型的预测进行比较。最基本的替代模型是一个简单的决策规则,它预测购买的概率为 50%。我们的模型比 50%的基线做得更好,这很了不起。😉

请注意,当模型正确预测所有事情时,可能的最佳准确度分数是 1 (100%)。当模型没有正确预测时,最差的分数可能是 0。

现在让我们看看当结果类不平衡时会发生什么。

不平衡数据

假设你在一家银行工作🏦并且想要检测信用卡交易中的欺诈。你要预测 1000 笔交易。你建立了一个机器学习模型来预测哪些是欺诈性的,这是产生的混淆矩阵:

困惑矩阵#2:

 Predicted Fraud   Predicted Not-fraud
Actual Fraud               1                      8
Actual Not-fraud           2                    989

我们的四个混淆矩阵值如下所示:

TP=1
TN=989
FP=2
FN=8

该模型预测有 3 个案例是欺诈性的,而实际上有 9 个案例是欺诈性的。

准确率为(1+989)/1000 = 99%。听起来很神奇,对吧?🏆

但是等等。沉住气。少了什么?🤔

该模型将 9 个实际欺诈案例中的 8 个分类错误!我们想找的 9 样东西,我们漏掉了 8 样!那可不行。☹️

99%的准确率分数并没有反映出模型在工作中做得有多好。事实上,如果很多人只看到正确的分数,就会误导他们。许多人不知道去问这些课程是否平衡。这是人们有意或无意误导统计数据的方式之一。☝️

一些好消息是,在 scikit-learn 中不需要手工计算精度。准确性是默认的分类评分标准。此外,您可以使用函数accuracy _ score来查找任何一组预测值和实际值的精确度。🎉

结果

准确度同等地加权混淆矩阵的所有象限。当两种结果类别的数量相对相等时,这是一个很好的汇总统计。当您更关心避免误报或漏报时,您会希望使用我们将在下一篇文章中探讨的其他度量之一。

你肯定想知道术语的准确性及其被不平衡数据误导的风险。😀

概述

您已经了解了混淆矩阵和准确性,这是数据科学家需要了解的最基本的分类术语。在下一篇文章中,我们将探索你肯定想知道的三个基本指标,但这可能很难保持直线。

我希望这篇关于分类标准基础部分的介绍对您有所帮助!如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。😀

我写了关于 Python、T2、SQL、T4、Docker 和其他技术主题的文章。如果你对此感兴趣,请关注我,在这里阅读更多。👍

**

不再有雾。资料来源:pixabay.com

分类快乐!📊

解释了分类指标和阈值

原文:https://towardsdatascience.com/classification-metrics-thresholds-explained-caff18ad2747?source=collection_archive---------8-----------------------

揭开常用分类指标的神秘面纱

马库斯·温克勒在 Unsplash 上的照片

分类评估

我们用来评估分类器的度量取决于我们想要解决的问题的性质和预测误差的潜在后果。让我们检查一个非常常见的癌症诊断例子(即分类为患癌或未患癌)。我们希望我们的模型能够预测尽可能多的实际/真实癌症诊断,但我们也知道,从统计学角度来看,正确识别所有真实的癌症诊断是不可能的。我们的模型最终会在某人实际上没有患癌症时将其分类/预测为患有癌症(假阳性),并在某人实际上患有癌症时预测其没有患癌症(假阴性)。我们必须问自己的问题是“什么更糟?预测某人会得癌症,而实际上他们不会,还是预测某人不会得癌症?”。这个例子中的答案是显而易见的,因为告诉某人他们没有癌症的后果远远超过前者。让我们记住这个例子,但是让我们回顾一下常用的分类性能指标。

分类性能指标

混淆矩阵

混淆矩阵总结了模型的预测。它给出了正确预测的数量(真阳性和真阴性)和不正确预测的数量(假阳性和假阴性)。在我们的癌症例子中,如果我们的模型预测某人患有癌症,并且这个人患有癌症,这是一个真正的肯定。当我们的模型预测某人没有患癌症,而那个人没有患癌症,这是一个真正的否定。当我们的模型预测某人患有癌症,但那个人没有患癌症时,这是假阳性(即该模型错误地预测了阳性癌症诊断)。最后,当我们的模型预测某人没有患癌症,但他们确实患了,那就是假阴性(即该模型错误地预测了阴性癌症诊断)。

其余的许多性能指标都是从混淆矩阵中得出的,因此,您必须很好地理解。

准确(性)

简而言之,准确性详细说明了我们的模型正确的频率。换句话说,就是正确预测数(TP,TF)除以预测总数。准确性通常是第一个衡量标准,但如果不仔细考虑,它可能会非常误导人。例如,让我们考虑一个用于训练我们的模型的不平衡数据集。我们有 1000 个非癌症诊断和 10 个癌症诊断。模型能够正确预测 900 个非癌症诊断,1 个癌症诊断的准确率为 0.89% ((900+1)/1010=0.89)。

(TP+TN)/(TP+FP+FN+TN)

精确度(也称为特异性)

精度告诉我们预测的正类中有多少是正确的。换句话说,预测的癌症诊断中有百分之多少实际患有癌症。Precision 只关心我们的模型准确地预测了正类。我喜欢把精确度看作是衡量一个模型正确预测阳性癌症诊断的“挑剔”程度或“确定”程度的标准。一个不同的例子可能与僵尸启示录有关。即使允许一个被感染的僵尸进入你的营地,也会导致每个人都被感染。一个具有高精度的模型将确保你让进入你的营地的那些人是健康的。然而,该模型也会有很高的假阴性计数(即被认为感染的健康人)。高精度与低 FP 速率相关。当假阳性的后果很严重时首选。

TP/(TP+FP)

回忆(也称为敏感度)

召回率是我们的模型预测的实际阳性的百分比。我们的模型预测(由医生)诊断患有癌症的人有多少百分比患有癌症。回忆不太关心准确预测阳性病例,而是确保我们已经捕获了所有的阳性病例,因为当某人患有癌症时,将其归类为非癌症的后果要严重得多。我们希望我们的模型具有高召回率,以将尽可能多的实际癌症诊断分类为患有癌症。不幸的是,这意味着该模型还会将大量没有患癌症的个体归类为患有癌症(即假阳性)。高召回率与低 FN 率相关。当假阴性的后果很严重时首选。

TP/(TP+FN)

F1 分数

从数学上讲,同时拥有高精确度和高召回率是不可能的,这就是 F1 分数派上用场的地方。F1 分数是精确度和召回率的调和平均值。如果你想建立一个平衡精确度和召回率的模型,F1-score 是一个很好的选择。当数据集不平衡时,F1-score 也是一个不错的选择。一个好的 F1 分数意味着你有低 FP 和低 FN。

2(召回精度)/(召回+精度)**

ROC 曲线/AUC 得分

接收器工作特性曲线(ROC)绘制了在任何概率阈值下的真阳性率与假阳性率。阈值是将观察结果分类为 0(无癌症)或 1(有癌症)的指定临界值。

那是一口……..

这将帮助我们更好地理解什么是阈值,我们如何通过改变阈值来调整模型的预测,以及如何创建 ROC 曲线。这个例子还将引入你在上面学到的 TP、TN、FN 和 FP 的概念。

我保证,这一切都是有意义的

逻辑回归是一个二元分类器,在上面的例子中,我们试图只根据一个特征/预测因子体重来正确预测肥胖。我们有一个包含 9 个观察值的数据集,其中 4 个(绿色)观察值不肥胖,5 个(红色)观察值肥胖。基于对数回归产生的 sigmoid 函数(曲线),前 3 个绿色非肥胖观察值基于其体重被预测为肥胖的几率为 0%。最后 3 个红色肥胖观察值也有 100%的概率被预测为肥胖。第二个红色肥胖观察有大约 70%的机会被预测为肥胖。

然而,第四个绿色的非肥胖观察有大约 85%的机会根据其体重(必须非常肌肉)被预测为肥胖,但我们知道这是错误的预测。此外,第一次肥胖观察有大约 15%的机会肥胖,这再次是错误的预测。记住阈值是 0.5,因此,任何处于 51%肥胖概率的数据点将被分类为肥胖,任何低于 50%的数据点将被分类为非肥胖。

让我们假设,当某人实际上肥胖时,错误地预测他不肥胖的后果是很严重的。换句话说,我们希望调整模型,以捕捉或预测尽可能多的实际肥胖个体(即高召回)。为了完成这项任务,我们需要改变我们的门槛。随着阈值降低到 0.2,我们的模型将正确地将所有 5 个肥胖观察预测为肥胖。任何高于 0.2 阈值的数据点将被归类为肥胖,反之亦然。

然而,通过将阈值降低到 0.2,第四次非肥胖观察现在被预测为肥胖。这是我们在调整模型的阈值时所做的权衡。

让我们再一次考虑我们的癌症例子。我们可以接受阈值为 0.2 的模型,因为它可以正确预测所有实际的癌症诊断(即真阳性)并且具有非常高的召回率。然而,该模型将做出权衡,因为它最终将更多实际上没有患癌症的个体预测为患有癌症(即假阳性)。假阳性的后果没有错误地预测某人没有患癌症那么严重。

现在,阈值为 0.9 的模型会做与阈值为 0.2 相反的事情。它将确保预测所有 4 个非肥胖个体为非肥胖,然而,前两个肥胖个体最终将被预测为非肥胖。既然我们理解了阈值及其目的,让我们回到 ROC 曲线。

那么 ROC 曲线在哪里起作用呢?

这是一个简单的例子,只有 9 个数据点,阈值很容易看到和解释。如果你有一百万个观察值和一个比我们的肥胖或癌症例子更复杂的情况呢?在这种情况下,最佳阈值是多少?我们是不是要做一堆这样的图,才能找到最符合我们需求的阈值?".答案是否定的。ROC 曲线是快速总结这些数据的好方法,这样你就可以选择你的阈值。

这是一个 ROC 曲线的例子(绿线),注意 y 轴上的真实阳性率(实际肥胖和预测为肥胖)和 x 轴上的假阳性率(非肥胖但预测为肥胖)。最后,请记住 ROC 用于总结不同阈值下的 TP 比率和 FP 比率。曲线不会显示阈值,但会显示不同真阳性率下的假阳性率。

真实阳性率

真阳性率=TP/(TP+FN)

假阳性率

假阳性率=FP/(FP+TN)

让我们快速比较 ROC 曲线上的 3 个独立阈值。0.9 的阈值具有下面的混淆矩阵,从中我们可以计算出 0.6 的 TP 速率和 0 的 FP 速率。

让我们在 ROC 曲线上绘制 TP 比率和 FP 比率点。为了演示,我们还绘制了阈值为 0.6 和 0.2 时的 TP 和 FP 速率。

绿色虚线代表 ROC 曲线。单独的蓝点是 4 个单独的混淆矩阵的结果,其中阈值被调整。现在问问你自己,“如果这是一个癌症的例子,你想确保你捕捉/预测所有实际的癌症诊断,你会选择哪个阈值?”

如果你说 0.2 你就对了!在这个阈值,你的 TP 率是 100%,这意味着你捕捉/预测了所有实际的癌症诊断。你的 FP 率约为 0.33,这意味着你的模型将一些非癌症诊断错误分类为癌症,但这没关系。恐吓某人,让他们花钱去做检查,比告诉他们没有癌症的人后果要轻。

现在,ROC 简单地连接每个点,以帮助可视化阈值从非常保守到更加宽松。最后,ROC 曲线有助于显示 AUC。

那么曲线下面积(AUC)是多少呢?

你经常会看到一个 ROC 图,有许多 ROC 曲线,每条曲线是一个不同的分类器(即。对数回归、SVC、决策树等。).AUC 是一个非常简单的指标,它提供了一个从 0 到 1 的十进制数,数字越大,分类器越好。AUC 衡量所有可能阈值的模型预测质量。一般来说,AUC 代表正确分类真阳性和真阴性数据点的概率。

怎么才能调整门槛?

# Adjusting the threshold down from 0.5 to 0.25
# Any data point with a probability  of 0.25 or higher will be 
#  classified as 1\. clf = LogisticRegression()
clf.fit(X_train, y_train)
THRESHOLD = 0.25
y_pred = np.where(clf.predict_proba(X_test)[:,1] >= THRESHOLD, 1, 0)
y_pred_proba_new_threshold = (clf.predict_proba(X_test)[:,1] >= THRESHOLD).astype(int)

逻辑回归没有调整阈值的内置方法。也就是说,因为我们知道默认情况下阈值设置为 0.50,所以我们可以使用上面的代码来说明任何高于 0.25 的值都将被归类为 1。

结论

我希望我能够帮助澄清一些关于分类标准的困惑。我发现保持所有的条款(即。召回、精准、TP、TN 等。)当你用一个特定的例子来记忆它们时,你的头脑会更清楚。癌症诊断)。

请随时提供您的反馈,并感谢您的阅读。

从零开始的分类模型

原文:https://towardsdatascience.com/classification-model-from-scratch-49f24bdd0636?source=collection_archive---------37-----------------------

使用 Python 从头构建朴素贝叶斯分类模型(简单分类模型)的初学者指南。

Github 库

卡梅隆·福克斯里《旧电脑的基本编程》

在机器学习中,我们可以使用概率来进行预测。也许最广泛使用的例子是所谓的朴素贝叶斯算法。它不仅简单易懂,而且在一系列问题上取得了令人惊讶的好结果。

朴素贝叶斯算法是一种基于贝叶斯定理的分类技术。它假设一个类中的一个特性与任何其他特性的存在无关。如以下公式所示,该算法依赖于给定预测值的类的后验概率:

其中:

  • P(c|x) 是给定一个预测值的类的概率
  • P(x|c) 是给定 la 类的预测值的概率。也称为可能性
  • P(c) 是类的先验概率
  • P(x) 是预测值的先验概率。

或者用简单的英语来说,朴素贝叶斯分类器等式可以写成:

好消息是朴素贝叶斯分类器易于实现并且表现良好,即使训练数据集很小。在预测数据类别时,这是最好的快速解决方案之一。 Scikit-learn 为各种类型的问题提供不同的算法。其中之一就是高斯朴素贝叶斯。当要素为连续变量时使用,并假设要素遵循高斯分布。让我们深入挖掘,使用 Python 从头开始构建我们自己的朴素贝叶斯分类器。

1.加载所需的库

构建自己的朴素贝叶斯分类器唯一需要的库是 NumPy 。NumPy 是一个开源项目,旨在用 Python 实现数值计算,我们将使用它进行算术运算。

2.实例化该类

下一步是实例化我们的朴素贝叶斯分类器类。一个类就像一个对象构造器,或者一个创建对象的“蓝图”。在面向对象的编程语言中,几乎所有东西都是对象,包括它的属性和方法。

init”是 python 类中的保留方法。在面向对象的概念中,它被称为构造函数。当从类创建对象时调用此方法,它允许类初始化类的属性。

3.分开上课

根据贝叶斯定理,在试图预测某一特定类别之前,我们需要知道该类别的先验概率。为了计算这一点,我们必须将特征值分配给特定的类。我们可以通过分离类并将它们保存到字典中来做到这一点。

字典是 Python 对一种数据结构的实现,这种数据结构通常被称为关联数组。字典由一组键值对组成。每个键-值对都将键映射到其关联的值。

4.功能摘要(统计信息)

给定类别的可能性或预测值的概率假定为正态分布(高斯),并基于平均值和标准差(见公式)进行计算。我们将为数据集中的每个特征创建一个摘要,这样做可以使我们在将来更容易地访问特征的均值和标准差。

  • 这里的zip()函数是元组的迭代器,其中每个特性的值被配对在一起。在 Python 中,元组是不可变的复合数据类型。
  • 我们选择yield,因为我们想要生成一个值序列,稍后我们将对其进行迭代,而不需要显式地将该序列保存在内存中。

5.高斯分布函数

使用高斯分布函数计算遵循正态分布的要素的可能性:

为了使用该公式进行进一步的计算,我们定义了一个分配方法,并完全按照上面的公式嵌入了该公式。

6.训练模型

训练模型意味着将模型应用于数据集,以便它可以遍历数据集并学习数据集的模式。在朴素贝叶斯分类器中,训练包括计算每个类的每个特征的平均值和标准差。这将允许我们计算用于预测的可能性。

如果我们仔细看看上面的代码片段,我们可以看到我们已经在训练数据集中分离了类。然后,计算每类的均值和标准差,然后使用len(feature_values)/len(X)计算该类的先验概率。

7.预测

为了预测一个类,我们必须首先计算每个类的后验概率。具有最高后验概率的类别将是预测的类别。

后验概率是联合概率除以边际概率。边际概率或分母是所有类的总联合概率,并且在所有类中都是相同的。我们需要具有最高后验概率的类,这意味着它将是最大的联合概率。

联合概率

联合概率是用于计算后验概率的分数的分子。对于多个特征,联合概率公式为:

使用 Python 应用相同的公式会产生以下代码片段:

仔细看看上面的片段,我们对每个类都遵循了以下步骤:

  • 获得摘要(平均值、标准偏差和先验概率)
  • 计算每个特征的正态概率
  • 获得总可能性(所有正态概率的乘积)
  • 将先验概率乘以总似然得到联合概率。

预测班级

有了每个类的联合概率后,我们可以选择联合概率值最大的类:

max(joint_proba, key=joint_proba.get)

将所有这些放在一起

如果我们将联合概率步骤和预测类步骤放在一起,我们可以用下面的代码片段预测测试数据集中每一行的类。

8.准确度分数

计算准确度分数是测试任何机器学习模型的基本部分。为了测试我们的朴素贝叶斯分类器的性能,我们将正确预测的数量除以预测的总数,得到一个从 0 到 1 的数。

我们的 naive Bayes classifier vs . sk learn gaussianb

现在我们已经建立了分类模型,让我们使用 UCI 葡萄酒数据集来比较我们的模型与 scikit-learn 的 GaussianNB 模型的性能。

朴素贝叶斯分类器

naive Bayes 分类器精度: 0.972

Sklearn 高斯 NB(朴素贝叶斯)

sci kit-学习高斯精度: 0.972

如您所见,模型的准确性是相同的,这意味着我们从头开始实现了一个成功的高斯朴素贝叶斯模型。

请随意使用这里的 github 资源库来查找整个 python 文件和用于创建本文的笔记本。

参考

朴素贝叶斯分类器如何在机器学习中工作

UCI 葡萄酒数据集

Scikit-学习朴素贝叶斯

脑 MRI 的肿瘤/非肿瘤分类

原文:https://towardsdatascience.com/classification-of-brain-mri-as-tumor-non-tumor-d48838ccc162?source=collection_archive---------24-----------------------

学习训练和应用一个简单的 CNN 来区分有肿瘤的 MRI 和没有肿瘤的 MRI。

大家好!作为一名生物医学本科生,如果我没有向大家展示一个 AI 在医学 中的应用,这难道不是我的错吗?在这个故事中,我将介绍 d eep learning 在医学领域的实际应用,以及它如何在很大程度上帮助医生和放射科医生。

概观

我将在这个实验中使用的数据集来自 Kaggle 链接https://www . ka ggle . com/navoneel/brain-MRI-images-for-brain-tumor-detection

首先,让我描述一下我们将在这里解决的问题。在这种情况下,我们希望将在轴面上获得的患者大脑的 MRI 扫描分类为是否存在肿瘤。我正在分享一个有肿瘤和没有肿瘤的核磁共振扫描的样本图像。

有肿瘤的核磁共振

没有肿瘤的磁共振成像

我们看到在第一张图片中,在大脑的左侧,有一个肿瘤形成,而在第二张图片中,没有这样的形成。因此,我们可以看到这两幅图像之间有明显的区别。现在,我们将如何使用人工智能或深度学习来将图像分类为肿瘤或不是肿瘤?

答案是卷积神经网络 ( CNN )。CNN 或 ConvNet 是深度学习的一类,多应用于分析视觉图像。python 中有很多框架可以应用 CNN 如 TensorFlowPyTorch 来训练模型。我将使用带有 TensorFlow 后端的 Keras 库来训练这个模型。好吧!技术术语说够了,让我们回到解决问题上来。

步骤 1:数据可视化

第一步,我们将分析 MRI 数据。在这个问题中,我们一共有 253 张核磁共振图像。其中, 155 标注为“ 是” ,表示有肿瘤,其余 98 标注为“ ”,表示没有肿瘤。

print("The number of MRI Images labelled 'yes':",len(os.listdir('yes')))print("The number of MRI Images labelled 'no':",len(os.listdir('no')))The number of MRI Images labelled 'yes': 155The number of MRI Images labelled 'no': 98

现在,在一个 CNN 中,我们要训练一个 神经网络 ,它可以被可视化为一系列的算法,可以识别一组数据中图像之间的关系,并可以对它们进行分类。

CNN 架构的一个例子。(图片来自 engmrk.com)

简单来说,神经网络的功能类似于 人脑 。我们用一组带有标签(是或否)的图像来训练神经网络,它有能力理解这两个类别之间的差异。因此,当我们给神经网络一个新的未标记图像时,它可以用训练过程中获得的知识对该图像进行分类。很简单,不是吗?

在我们的例子中,我们有 253 个图像,其中 155 个属于“是”类,98 个属于“否”类。我们遇到了一个新问题,称为数据不平衡。 数据不平衡 是每类的观测值数量分布不均匀的地方(这里我们有 155 个属于“是”类,只有 98 个属于“否”类)。难道我们的神经网络不会在“不”类中得不到足够的训练吗?😦

步骤 2:数据扩充

为了解决这个问题,我们使用了一种叫做 的技术,数据扩充 。这是医学中一个非常重要的方面,在医学中会有很多数据不平衡的例子。不明白吗?加油!通常,在大多数情况下,不健康患者的数量会比健康患者的数量少得多。不是吗?

在数据增强中,我们获取特定的 MRI 图像,并执行各种类型的 图像增强 ,例如旋转、镜像和翻转,以获得更多数量的图像。我们将对图像数量较少的类应用更多的增强,以使两个类的图像数量大致相等。

数据扩充

从上面的图像中,我们可以看到应用于“是”类 MRI 图像的各种增强。通过这种方式,我们增加了数据集的所有图像。

因此,在对我们的数据集应用数据扩充之后,我们有“是”类的图像 1085 和“否”类的 图像 979 。几乎相等,对吗?

*print(f"Number of examples: {m}")print(f"Percentage of positive examples: {pos_prec}%, number of pos examples: {m_pos}")print(f"Percentage of negative examples: {neg_prec}%, number of neg examples: {m_neg}")Number of examples: 2064 Percentage of positive examples: 52.56782945736434%, number of pos examples: 1085 Percentage of negative examples: 47.43217054263566%, number of neg examples: 979*

步骤 3:拆分数据

下一步,我们将数据分为训练集和测试集。图像的 80% ( 1651 个图像)将进入训练集,我们的神经网络将使用该训练集进行训练。剩余的 20% ( 413 张图像)将进入测试集,我们将使用该测试集应用我们训练好的神经网络并对其进行分类,以检查我们的神经网络的准确性。

*The number of MRI Images in the training set labelled 'yes':868The number of MRI Images in the test set labelled 'yes':217The number of MRI Images in the training set labelled 'no':783The number of MRI Images in the test set labelled 'no':196*

步骤 4:构建 CNN 模型

好吧!很好,你已经明白了。现在,我一直告诉你的神经网络在哪里?只是在这个下一步,我们设计了一个神经网络使用 Keras 库与各种卷积和池层。

*model = tf.keras.models.Sequential([tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(150, 150, 3)),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Conv2D(32, (3,3), activation='relu'),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Conv2D(64, (3,3), activation='relu'),tf.keras.layers.MaxPooling2D(2,2),tf.keras.layers.Flatten(),tf.keras.layers.Dense(512, activation='relu'),tf.keras.layers.Dense(1, activation='sigmoid')])model.compile(optimizer='adam'), loss='binary_crossentropy', metrics=['acc'])*

对于本文来说,对这些层的解释有点复杂。我将在后面的文章中解释神经网络的设计。到目前为止,你可以把它看作是帮助'记忆'图像数据的一系列语句。

步骤 5:预先训练 CNN 模型

在这之后,我们将创建一个“ train_generator 和“validation _ generator”来将我们的训练集和测试集的分割图像存储到两个类中(是和否)。

*Found 1651 images belonging to 2 classes. 
Found 413 images belonging to 2 classes.*

如我们所见,2084 幅图像被分为 1651 幅(80%)用于“训练 _ 生成器”的图像和 413 幅(20%)用于“验证 _ 生成器”的图像。

步骤 6:训练 CNN 模型

最后,我们进入将图像数据拟合到训练好的神经网络的阶段。

*history=model.fit_generator(train_generator,epochs=2,verbose=1,validation_data=validation_generator)*

我们将训练大约 100 个“ 时期 ”的图像数据。一个时期可以被认为是一个迭代,其中我们一次又一次地馈送训练图像,以便神经网络用训练图像得到更好的训练。

*Epoch 1/100 50/50 [==============================] - 22s 441ms/step - loss: 0.7400 - acc: 0.5703 - val_loss: 0.6035 - val_acc: 0.6901 Epoch 2/100 50/50 [==============================] - 20s 405ms/step - loss: 0.6231 - acc: 0.6740 - val_loss: 0.5508 - val_acc: 0.7409 Epoch 3/100 50/50 [==============================] - 20s 402ms/step - loss: 0.6253 - acc: 0.6460 - val_loss: 0.5842 - val_acc: 0.6852 Epoch 4/100 50/50 [==============================] - 20s 399ms/step - loss: 0.6421 - acc: 0.6517 - val_loss: 0.5992 - val_acc: 0.6562 Epoch 5/100 50/50 [==============================] - 20s 407ms/step - loss: 0.6518 - acc: 0.6599 - val_loss: 0.5719 - val_acc: 0.7433 Epoch 6/100 50/50 [==============================] - 21s 416ms/step - loss: 0.5928 - acc: 0.6920 - val_loss: 0.4642 - val_acc: 0.8015 Epoch 7/100 50/50 [==============================] - 21s 412ms/step - loss: 0.6008 - acc: 0.6840 - val_loss: 0.5209 - val_acc: 0.7579 Epoch 8/100 50/50 [==============================] - 21s 411ms/step - loss: 0.6435 - acc: 0.6180 - val_loss: 0.6026 - val_acc: 0.6973 Epoch 9/100 50/50 [==============================] - 20s 408ms/step - loss: 0.6365 - acc: 0.6480 - val_loss: 0.5415 - val_acc: 0.7627 Epoch 10/100 50/50 [==============================] - 20s 404ms/step - loss: 0.6383 - acc: 0.6354 - val_loss: 0.5698 - val_acc: 0.7966*

从上图可以看出,训练集的“ acc 【精度】随着每次迭代不断提高。这意味着神经网络模型能够在将图像分类为肿瘤或非肿瘤方面有所改进。记下“”val _ ACC”[验证精度],它表示测试集上模型的精度。很高,不是吗?

在第 100 个历元结束时,我们看到训练好的 CNN 模型的验证准确率为 73.85%

这表明我们的神经网络可以正确地将大约 74%的测试集图像分类为肿瘤或非肿瘤。很准,不是吗?

*Epoch 100/100 50/50 [==============================] - 20s 402ms/step - loss: 0.3604 - acc: 0.8720 - val_loss: 0.5600 - val_acc: 0.7942*

第七步:CNN 模型的分析

在训练之后,我们最终为所有 100 个时期(迭代)绘制“训练 _ 生成器”和“验证 _ 生成器”的“准确性”和“损失”。

***

准确度和损耗图*

在这个故事的最后,使用这个模型,你可以输入一个单独的核磁共振图像,检查它是否有肿瘤。很酷,不是吗?

我已经分享了我的 GitHub 资源库的链接,在那里你可以找到代码和数据供你试用。所以,继续吧,转到我的存储库并开始实验。

* [## MK-gurucharan/脑肿瘤检测

这是一个储存库,有各种核磁共振成像的肿瘤检测代码。总共有 253 张图片,标签为…

github.com](https://github.com/mk-gurucharan/Brain-Tumor-Detection)

希望我已经对这个问题做了很好的解释,让你了解 CNN 及其在医学上的应用。请务必查看我的 Github 以获得详细的代码版本。到那时,快乐的机器学习!*

基于神经网络(PyTorch)的常见水果分类

原文:https://towardsdatascience.com/classification-of-fruit-images-using-neural-networks-pytorch-1d34d49342c7?source=collection_archive---------32-----------------------

一本关于神经网络实现高准确率的易读指南

目的:寻找一种对水果 360 幅图像分类准确率最高的神经网络模型。

  1. 深度前馈
  2. 卷积神经网络
  3. 残差神经网络(ResNet9)

数据来源:【https://www.kaggle.com/moltean/fruits

全码笔记本:https://jovian.ml/limyingying2000/fruitsfinal

D 数据准备

首先,让我们了解一下我们的数据集!

Kaggle Fruits 360 数据集由 131 种不同类型的水果和蔬菜的 90483 张图像组成。

首先,我们导入数据和所需的库来运行我们的代码。

import torch
import os
import jovian
import torchvision
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn
import torchvision.models as models
import torch.nn.functional as F
from torchvision.datasets import ImageFolder
from torchvision.transforms import ToTensor
from torchvision.utils import make_grid
from torch.utils.data.dataloader import DataLoader
from torch.utils.data import random_split
import torchvision.models as models
%matplotlib inline

每种水果都有其独特的文件夹,由 jpg 图像组成。

使用 matplotlib 库显示彩色图像:

import matplotlib.pyplot as plt

def **show_example**(img, label):
    print('Label: ', dataset.classes[label], "("+str(label)+")")
    plt.imshow(img.permute(1, 2, 0))

数据集[5000]是一个苹果蛇果

由于我们使用的是 PyTorch ,我们必须使用ToTensor将上面的像素图像转换成张量:

dataset = ImageFolder(data_dir + '/Training', transform=ToTensor())
img, label = dataset[0]
print(img.shape, label) 
img

图像转换成张量的一个例子

有 3 个通道(红、绿、蓝),100*100 图像尺寸。每个值代表相对于通道颜色的颜色强度。

训练和验证数据集

接下来,我们将随机分割数据以获得 3 组数据:

  1. 训练集:训练模型
  2. 验证集:评估模型
  3. 测试集:报告模型的最终准确性

训练数据集的大小:57,692

验证数据集的大小:10,000

测试数据集的大小:22,688

分批培训

因为我们总共有 57,692 个训练图像,所以在使用*DataLoader*训练我们的模型之前,我们应该将我们的图像分成更小的批次。使用较小的数据集可以减少内存空间,从而提高训练速度。

对于我们的数据集,我们将使用 128 的批量大小。

在训练批次中随机分配 128 个图像

现在,我们将开始设计我们的模型。

1.深度前馈

超参数:

架构:“5 层(2000,1000,500,250,131)”

学习率:[0.01,0.001]

历元数:[10,10]

优化函数:随机梯度下降(SGD)

用 5 层架构训练模型:

class **FruitsModelFF**(ImageClassificationBase):
    def **__init__**(self):
        super().__init__()
        self.linear1= nn.Linear(input_size, 2000)
        self.linear2= nn.Linear(2000, 1000)
        self.linear3= nn.Linear(1000,500)
        self.linear4= nn.Linear(500,250)
        self.linear5= nn.Linear(250, output_size)

    def **forward**(self, xb):
        *# Flatten images into vectors*
        out = xb.view(xb.size(0), -1)
        *# Apply layers & activation functions* 
        out= self.linear1(out)
        out=F.relu(out)  
        out=self.linear2(out)
        out=F.relu(out)  
        out=self.linear3(out)
        out=F.relu(out)  
        out=self.linear4(out)
        out=F.relu(out)  
        out=self.linear5(out)
        return out

训练前,验证准确率为: 0.52734%

A 在以[0.01,0.001]的学习速率训练了总共 20 个周期后,验证准确率在大约 96.84% 处达到平稳状态。这与最初的 0.52734%相比是一个巨大的跳跃。

最后,让我们用测试数据集来测试我们训练好的模型!

img, label = test[8000]
plt.imshow(img.permute(1, 2, 0))
print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

img, label = test[1002]
plt.imshow(img.permute(1, 2, 0))
print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

img, label = test[0]
plt.imshow(img.permute(1, 2, 0))
print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

我们训练的模型正确地预测了上述所有结果。

**Final test accuracy: 86.209%**

为了进一步提高我们的测试精度,我们将使用卷积神经网络,它通常比前馈神经网络性能更好。

原因:

通过应用相关过滤器,ConvNet 能够成功捕捉图像中的空间和时间相关性。由于所涉及的参数数量的减少和权重的可重用性,该架构对图像数据集执行更好的拟合。换句话说,可以训练网络更好地理解图像的复杂程度。

简而言之,CNN 非常适合计算密集型的大尺寸图像:

  1. 需要更少的参数
  2. 形成连接的稀疏性
  3. 能够检测相似的模式,并在图像的不同部分应用学到的特征

2。简单卷积神经网络(CNN)

CNN 功能简介:

55 图像尺寸,33 内核尺寸,3*3 输出尺寸

内核上的权重首先被随机初始化为:

[0, 1, 2] [2, 2, 0] [0, 1, 2]

我们的示例图像如下所示:

[3, 3, 2, 1, 0] [0, 0, 1, 3, 1] [3, 1, 2, 2, 3] [2, 0, 0, 2, 2] [2, 0, 0, 0, 1]

当我们对样本图像应用内核时,输出将是:

[12., 12., 17.] [10., 17., 19.] [ 9., 6., 14.]

申请:

输出= 2 * 0+2 * 1+3 * 2+0 * 2+2 * 2+2 * 0+0 * 0+0 * 1+1 * 2 = 14

对样本图像上内核的每次移动重复计算输出,以获得新的输出大小。

def **apply_kernel**(image, kernel):
    ri, ci = image.shape       *# image dimensions*
    rk, ck = kernel.shape      *# kernel dimensions*
    ro, co = ri-rk+1, ci-ck+1  *# output dimensions*
    output = torch.zeros([ro, co])
    for i in range(ro): 
        for j in range(co):
            output[i,j] = torch.sum(image[i:i+rk,j:j+ck] * kernel)
    return output

此外,我们通过应用最大池层来逐渐减小每个卷积层的输出张量的大小。

最大池可视化

如上所述,卷积层增加了通道,而最大池层减少了图像大小。

具有卷积和最大池的 CNN 结构的例子

现在,让我们为同一个 Kaggle 水果数据集构建 CNN 模型。

超参数:

纪元数量:10

学习率:0.001

优化函数:亚当

class **FruitsModel**(ImageClassificationBase):
    def **__init__**(self):
        super().__init__()
        self.network = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1), *#3 channels to 32 channels*
            nn.ReLU(),
            nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2, 2), *# output: 64 channels x 50 x 50 image size - decrease*

            nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1), *#can keep the same, increase power of model , go deeper as u add linearity to non-linearity*
            nn.ReLU(),
            nn.MaxPool2d(2, 2), *# output: 128 x 25 x 25*

            nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(5, 5), *# output: 256 x 5 x 5*

            nn.Flatten(), *#a single vector 256*5*5,*
            nn.Linear(256*5*5, 1024),
            nn.ReLU(),
            nn.Linear(1024, 512),
            nn.ReLU(),
            nn.Linear(512, 131))

    def **forward**(self, xb):
        return self.network(xb)

除了在我们的模型中的改变之外,我们使用 Adam 优化器函数,因为它是在分类问题中寻找最小成本函数的更有效的方式。

**Final test accuracy rate: 92.571%**

我们已经实现了非常高的最终测试准确率,大约比前馈神经网络高6。然而,让我们通过额外的残差块和对 CNN 模型的微小调整来进一步拓展边界。

3。残差神经网络( ResNet9)

超参数:

最大学习率:0.01

纪元数量:10

优化函数:亚当

def **conv_block**(in_channels, out_channels, pool=False):
    layers = [nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), 
              nn.BatchNorm2d(out_channels), 
              nn.ReLU(inplace=True)]
    if pool: layers.append(nn.MaxPool2d(2))
    return nn.Sequential(*layers)

class **ResNet9**(ImageClassificationBase):
    def **__init__**(self, in_channels, num_classes):
        super().__init__()

        self.conv1 = conv_block(in_channels, 64)
        self.conv2 = conv_block(64, 128, pool=True)
        self.res1 = nn.Sequential(conv_block(128, 128), conv_block(128, 128))

        self.conv3 = conv_block(128, 256, pool=True)
        self.conv4 = conv_block(256, 512, pool=True)
        self.res2 = nn.Sequential(conv_block(512, 512), conv_block(512, 512))

        self.classifier = nn.Sequential(nn.MaxPool2d(4), 
                                        nn.Flatten(), 
                                        nn.Linear(4608, num_classes))

    def **forward**(self, xb):
        out = self.conv1(xb)
        out = self.conv2(out)
        out = self.res1(out) + out
        out = self.conv3(out)
        out = self.conv4(out)
        out = self.res2(out) + out
        out = self.classifier(out)
        return out

除此之外,我们还将引入“一个周期学习率策略”,它会逐渐提高学习率,直至达到用户设定的最大学习率,然后逐渐降至极低的学习率。这种学习率的变化发生在每一批训练之后。

很难找到正确的学习速率,因为相对较高的学习速率会导致发散,而相对较低的学习速率会导致模型过拟合。

学习率

然而,“一个周期学习率策略”通过为我们的模型找到一个最佳学习率范围克服了这样的问题。

学习率在大约第 1200 批次时达到峰值 0.01

**Final test accuracy: 98.85%** 

经过一些修改,我们的最终测试精度又提高了6%。

总结:

在这 3 个不同的模型中,ResNet9 的测试准确率最高,为 98.85%。

未来工作:

  1. 数据转换(数据扩充和标准化)
  2. 高级迁移学习

演职员表:

第一张水果照片由侯塞因Unsplash 上拍摄

第二张水果照片由布鲁克·拉克Unsplash 上拍摄

课程资料来自深度学习用 py torch:Zero to GANs&freeCodeCamp

posted @ 2024-10-14 11:50  绝不原创的飞龙  阅读(434)  评论(0)    收藏  举报