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

龙哥盟 / 2024-10-14 / 原文

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

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

基础:多重共线性和可解释性

原文:https://towardsdatascience.com/basics-multicollinearity-and-interpretability-3dfef2168efc?source=collection_archive---------33-----------------------

鲁莽的数据科学家的基本错误之一。

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

多重共线性是数据集的一种属性,它可能会给您带来对模型和数据的意外、不稳定但在技术上并非错误的解释。在进行回归分析之前检查多重共线性(为简洁起见,以下简称为 MC)有助于确保从数据中获得最大的洞察力,并且不会忽略重要的关系。

多重共线性的例子。

数据中的 MC 意味着数据表中的多列(即特征、预测值、输入变量)是线性 依赖。换句话说,数据表中存在可以表示为其他列的线性组合的列。您的数据矩阵 X 不是满秩的。

我将在线性模型的上下文中证明 MC 的重要性。这个问题也延伸到非线性模型,但只是不容易暴露,因为需要复杂的解释方法来解释这种模型。

线性模型(如线性回归)以可解释而闻名,这意味着与复杂的非线性模型(如神经网络)不同,很容易看出输入与输出之间的关系。您只需读出系数:系数的幅度和符号直接对应于相关特性对输出的影响。

通常,数据分析师通过应用线性回归并检查回归系数,使用该属性来量化两个或多个列的关系。

线性回归模型使得 x 和 y 的关系很容易看出。

MC 通过引入模糊性破坏了线性回归的可解释性。在 MC 数据集中,输出不仅可以表示为列的唯一线性组合,还可以等价地表示为其共线列的组合。

以一个虚构的玩具为例,它预测孩子的阅读能力( y )是其年龄( a )和身高( h )的函数。让我们假设年龄和身高在我们的数据中完全相关,如下例所示。现在我们可以将 y 等效表示为:

阅读能力 y、年龄 a 和身高 h(单位:厘米)的数据集示例。

这三个表达式都是正确的,但是它们导致对数据中的关系的非常不同的解释。在第一种情况下,我们可以得出结论,身高是阅读能力的唯一预测因素,年龄没有任何作用。在最后一种情况下,我们可能倾向于假设身高和年龄都是预测阅读能力所需要的。

看待这个问题的另一种方式是,多共线性矩阵不是满秩的。非满秩矩阵 X 是不可逆的。还有,(X^T)X 是不可逆的。线性回归的解析最小二乘解需要 X^T)X 的精确反演,因此它对于多共线性矩阵是不存在的。对于“几乎”MC 矩阵,问题是病态。

到目前为止,我们考虑了一些列是其他列的精确线性组合的情况。在实践中,这种情况可以忽略不计,因为如果我们使用真实(即有限和有噪声的)数据,这种精确的关系实际上永远不会出现。但是,即使列只是近似共线,我们仍然有一个可解释性的问题。我们的模型在固定数据集上可能相当稳定,但对数据中的微小变化仍然敏感。添加或删除一些样本可以使我们的模型从依赖一组特征“跳到”另一组特征——就像以前一样。

如前所述,MC 不仅会妨碍线性模型的可解释性,还会影响非线性模型及其解释方法,如输入梯度、逐层相关性传播,或综合梯度。这是因为不确定性不在于所使用的解释方法,而在于数据,因此也就在于可以从中学习的模型。

现在您已经了解了多重共线性的概念和后果,您可能想知道如何在数据中检测它以及如何补救它的影响。这些步骤超出了我想在这篇文章中传达的基本内容,但是我建议看看在维基百科上收集的有用的方法列表。

希望你学到了有用的东西!

保险定价基础

原文:https://towardsdatascience.com/basics-of-insurance-pricing-47243c2630b9?source=collection_archive---------4-----------------------

快速介绍 GLM 模特

布雷特·乔丹在 Unsplash 上的照片

简介

在这篇文章中,保险定价的基础知识将被解释:为什么定价如此重要,如果定价策略不一致会发生什么,以及保险公司如何使用统计模型设定他们的保费。在最后一节中,我们将使用真实的保险数据进行一个非常简单的案例研究,以充实导言中的思想。

为什么定价很重要

保险业是一个关注对冲不确定财务损失风险的行业,因此保险公司的业务在很大程度上是一项风险管理工作。被保险人通过一份被称为保险单的合同与保险公司交易未来风险以获得固定的保费,如果保单持有人遭受损失,他们可以在保单允许的情况下向保险公司提出索赔。保费是由保险公司在任何索赔之前设定的,因此,公司预测客户的风险以设定有利可图的保费是至关重要的。考虑到这一点,预测模型在保险公司广泛使用就不足为奇了;无论是评估客户还是设定保费。

作为一个例子来强调有一个深思熟虑的定价策略的重要性,假设有两家保险公司,A 和 B,A 有相对于损失风险的低保费,而 B 有相对于风险的适当保费。在这种情况下,高风险客户会选择 A,因为他们的保费与 B 相比相对较低,因此 A 会吸引高风险客户,实际上看到他们的利润被吃掉。相反,如果 A 的保费太高,他们不会吸引任何有利可图的客户,仍然亏损。根据这个简单的例子,我们明白了为什么有竞争力的定价策略是至关重要的。

此外,根据埃森哲金融服务公司 2017 年全球分销和营销消费者调查,对 18 个市场的 32,715 名保险客户的研究发现,价格是客户忠诚度的头号驱动因素,52%的汽车保险客户选择价格作为他们的首要杠杆。

作者图片

保险公司如何制定保费?

如上所述,保险费是根据客户的风险确定的,以确保客户的损失得到补偿。然而,这并不代表最终价格的全部。像任何其他业务一样,保险公司有自己的成本,并通过运营来盈利。因此,保费不仅要弥补客户的损失,还要弥补成本,保持可观的利润。

尽管如此,保费的基础是根据客户的风险选择保费。要做到这一点,必须估计客户寻求保险的风险。根据我们考虑的保险产品,使用不同的解释变量,通常分为两组:主题变量,涉及购买保险的人,和客体变量,涉及被保险的客体;无论是房子、汽车或任何其他可保物品。例如,在家庭保险中,精算师可以使用诸如财产的居住面积、家庭中居住的人数或投保者的年龄等变量。潜在的假设是,这些变量和风险之间存在相关性,这种相关性看起来当然不同,但作为一个例子,财产保险的风险通常随着承保人的年龄而降低,因为年老通常意味着更加注意和小心。

什么是风险?

在保险术语中,风险是有害的或意想不到的事情发生的可能性。这可能涉及贵重财产和物品的丢失、被盗或损坏,也可能涉及有人受伤。从统计学的角度来看,风险可以定义为:

其中 L 为损失, e 为保险有效期(敞口)。如果我们假设索赔的大小与索赔的频率无关,我们可以进行如下扩展:

其中 N 是索赔的数量, S 是索赔的严重性或规模, F 是索赔频率。

评估风险的方法

精算师使用统计方法来估计风险并不奇怪,直到 20 世纪 80 年代,精算师都依赖线性回归来模拟风险,但由于建立了一个称为广义线性模型(GLM)的模型,这种情况发生了变化。GLM 相对于简单的线性回归的优势在于,GLM 模型通过所谓的链接函数(下面等式中的 g)允许非线性相关性。

其中 Y 为因变量, X 为自变量,β为回归拟合的参数。请注意,如果没有链接函数,表达式将只是简单的线性回归。

今天,大多数保险公司的保费是使用 GLM 模型来确定的,它们在一定程度上已经成为精算师的舒适区。然而,近年来,由于技术突破和许多行业大数据的实现,在业务应用中使用机器学习(ML)的普及程度出现了激增,保险业也不例外。当在保险业中使用 ML 模型时,记住 GDPR 是很重要的,因为它对模型的可解释性提出了要求。因此,易于解释的基于树的模型通常受到青睐,甚至被证明在保险数据上比传统的 GLMs 具有更好的预测准确性(见https://arxiv.org/abs/1904.10890)。

建模假设

在任何模型中,必须对数据的性质和使用的变量做出假设。我们已经遇到了保险风险模型中常见的一个假设,即客户索赔的严重程度和频率是独立的。利用这一假设,精算师建立了两个模型,一个是严重性模型,一个是频率模型,然后将两个模型的预测结合起来,得出风险估计值。但是,这不是一个必要的假设,因为风险也可以直接建模。无论作出何种决定,因变量,无论是风险、严重程度还是频率,总是假定遵循已知的统计分布。例如,客户提交的索赔数量通常被假定为按照泊松分布分布,而严重性通常遵循伽马分布。当精算师直接对风险建模时,通常选择所谓的 Tweedie 分布。

案例分析:从理赔数据到风险预测

这里的一个例子是建立一个频率模型的家庭保险数据使用统计软件 R。

首先,我们看看手头的数据,索赔数量是我们的因变量,我们通过直方图将其可视化,以查看它遵循什么分布,并获得问题的概述:

显然,索赔数量严重倾斜,因为大多数客户没有任何索赔,所以我们看到峰值为零。这激发了为什么使用泊松分布可能是一个好主意,通过调整泊松分布中的λ参数,可以捕获这种偏斜。

建模的第一步是清理数据并选择要使用的要素。完成这些后,我们可以对数据进行 GLM 拟合。

首先,我们将数据读入 R,并将其分成训练/测试集:

Frequency_data <- read.csv("C:/Users/Samuel Tober/Desktop/Projects/Data/Frequency_data.csv")set.seed(123) #Set seed for reproducibility
sample <- sample.split(Frequency_data, SplitRatio = 0.80) #Split data into 80% training 20% test
train = subset(Frequency_data, sample==TRUE)
test = subset(Frequency_data, sample==FALSE)

然后,我们使用“glm”软件包将 GLM 模型拟合到训练数据:

model <- glm('NO_CLAIM_NOT_NULL ~ NO_INSUR + AGE_INSUR_PERS +                                    LIVE_AREA + offset(log(EXP_COV))', family = poisson(link = "log"),         data = train)

在这里,我们将索赔数量(NO_CLAIM_NOT_NULL)建模为家庭人数(NO_INSUR)、客户年龄(AGE_INSUR_PERS)和房产居住面积(LIVE_AREA)的函数。请注意,我们在 GLM 模型中包含了风险敞口(EXP_COV)作为补偿,这样我们就可以对比率数据使用泊松回归(泊松通常仅适用于计数数据)。此外,我们指定 link = "log ",其中 link 指的是前面提到的链接函数 g,我们选择对数,因为我们处理的是泊松分布数据。

接下来,我们使用均方误差(MSE)和平均绝对误差(MAE)作为度量标准来测试和评估该模型(有更合适的度量标准,如泊松偏差,但这里我们选择一个简单易懂的度量标准用于教育目的,在未来的文章中有更多关于度量标准的信息):

pred <- exp(predict(model, test))
MSE <- sqrt(mean((test$NO_CLAIM_NOT_NULL - pred*test$EXP_COV)^2)) #Mean squared error
MAE <- sum(abs(test$NO_CLAIM_NOT_NULL - pred*test$EXP_COV))/nrow(test) #Mean absolute error> MSE = 0.182480104096452
> MAE = 0.0582112950956896

有了这个模型,我们现在可以预测保险客户的索赔频率,如果我们同样建立一个严重性模型,我们在频率-严重性独立性假设下得到一个完全成熟的定价模型。

请注意,这是一个极其简化的示例,请参考https://www . casact . org/pubs/monographs/papers/05-gold burd-Khare-tevet . pdf和/或【https://link.springer.com/book/10.1007/978-3-642-10791-7】获取 GLM 模式的更多解释和展示。

OpenCV 内核和卷积的基础知识

原文:https://towardsdatascience.com/basics-of-kernels-and-convolutions-with-opencv-c15311ab8f55?source=collection_archive---------4-----------------------

如何使用 Python 和 OpenCV 将简单的内核应用于图像

我一直在尝试用 Python 和 OpenCV 学习计算机视觉,我总是偶然发现术语内核卷积

图片来自 JESHOTS

起初,我试图依靠那些 gif 和一些简短的解释,但我经常对它们的使用感到困惑,所以我决定更好地看看它。

在这篇文章中,我将分享我对内核和卷积的一些了解,同时探索它的一些主要应用,如模糊,锐化,提取和腐蚀。

核和卷积

和我一样,你可能觉得这和玉米有关系,其实没有。

身份内核——用碳制成的图片

计算机视觉中的核是矩阵,用于在我们的数据中执行某种卷积。让我们试着分解一下。

卷积是两个函数之间创建第三个函数的数学运算。在图像处理中,它通过遍历每个像素来执行与该像素及其邻居的计算。

内核将定义卷积的大小、应用于卷积的权重以及通常位于中心的锚点。

因此,在 3×3 矩阵中,每个像素只受其周围像素的影响,而 7×7 的像素会改变它。

高斯模糊

好的,那么要把它应用到一个图像上,我们会:用它的定位点把它定位在一个给定的像素上,在核的值和像素的值之间执行一些操作,为那个像素定义一个新的值,然后移动到下一个。

图片来源:https://giphy.com/gifs/blog-daniel-keypoints-i4NjAwytgIRDW

总结:

  • 我们可以通过与图像的像素交互来过滤和修改图像;
  • 这种相互作用可能发生在盘旋时;
  • 这些卷积使用核来描述像素将如何受到影响;
  • 内核表示每个操作的区域、值/权重和锚点;

亲自动手

说得够多了,让我们看看如何使用这些内核。
我们将使用 OpenCV、Numpy 和 Matplotlib。

import cv2
import numpy as np
import matplotlib.pyplot as plt

导入库后,我们可以绘制原始图像,这样我们就知道发生了什么变化。

image = cv2.imread('Images/6.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)fig, ax = plt.subplots(1, figsize=(12,8))
plt.imshow(image)

雅典艺术学院——拉斐尔

酷,现在让我们做一个模糊图像的内核。我们将使用 Numpy 构建一个 3x3 的 1 矩阵,然后除以 9。

https://en . Wikipedia . org/wiki/Kernel _(image _ processing)

>>> kernel = np.ones((3, 3), np.float32) / 9
>>> kernel
...
array([[0.11111111, 0.11111111, 0.11111111],
       [0.11111111, 0.11111111, 0.11111111],
       [0.11111111, 0.11111111, 0.11111111]], dtype=float32)

我们可以用. filter2D 把它应用到图像上。

img = cv2.filter2D(image, -1, kernel)fig, ax = plt.subplots(1, figsize=(12,8))
plt.imshow(img)

框模糊。

让我们用一个锐化的内核来尝试一下。

https://en . Wikipedia . org/wiki/Kernel _(image _ processing)

kernel = np.array([[0, -1, 0],
                   [-1, 5, -1],
                   [0, -1, 0]])

锐化。

通过使用. filter2D,我们可以使用任何我们想要的内核来应用线性过滤器。但是也有更舒适的方式来达到这些结果。

简单的方法

OpenCV 有一些方便的函数来过滤图像,很多时候你甚至不需要定义内核。

我们可以利用。模糊应用一个框模糊,我们只需要传递图像和内核的大小。

image = cv2.imread('Images/6.jpg')
**image = cv2.blur(img, (5,5))**
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)fig, ax = plt.subplots(1, figsize=(12,8))
plt.imshow(image)

框模糊。

高斯模糊和中值模糊:

image = cv2.imread('Images/6.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)fig, ax = plt.subplots(1, figsize=(12,16))ax = plt.subplot(211)
g = **cv2.GaussianBlur(image, (3,3), 0)**
plt.imshow(g)ax = plt.subplot(212)
m = **cv2.medianBlur(image, 3)**
plt.imshow(m)

高斯和中值模糊。

膨胀和腐蚀

内核还可以帮助放大和侵蚀图像——这在处理图片和文本时似乎很有用。

image = cv2.imread('Images/9.png')# convert to black and white
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
r ,image = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY)# create kernel
kernel = np.ones((5,5), np.uint8)fig, ax = plt.subplots(1, figsize=(16,12))# original
ax = plt.subplot(232)
plt.imshow(image, cmap='Greys')
plt.title('original')# erosion
e = cv2.erode(image, kernel)
ax = plt.subplot(234)
plt.imshow(e, cmap='Greys')
plt.title('erosion')# dilation
d = cv2.dilate(image, kernel)
ax = plt.subplot(235)
plt.imshow(d, cmap='Greys')
plt.title('dilation')# morphological gradient (dilation - erosion)
m = cv2.morphologyEx(image, cv2.MORPH_GRADIENT, kernel)
ax = plt.subplot(236)
plt.imshow(m, cmap='Greys')
plt.title('dilation - erosion')

图片作者赫尔巴努

在该应用中,核是定义所应用效果的形状和范围的结构化元素。即使您必须创建一个矩阵,OpenCV 也有一些功能来简化这个过程。

https://docs . opencv . org/trunk/d9/d61/tutorial _ py _ morphology _ ops . html

内核和卷积比我预期的要简单得多,也更容易理解为什么它们在图像处理中被如此广泛地使用,以及它们如何增加复杂性以支持图像分类、对象检测等任务。

感谢阅读我的文章。我希望你能更清楚地了解卷积是如何使用内核来执行运算的。

资源: OpenCV 2D 滤镜;
OpenCV 平滑;
OpenCV 过滤;
OpenCV 形态变换;

更进一步:
OpenCV 去噪;
OpenCV 边缘检测;

每个数据科学家都应该了解线性代数的基础知识

原文:https://towardsdatascience.com/basics-of-linear-algebra-for-data-science-9e93ada24e5c?source=collection_archive---------14-----------------------

照片由 Michael Dziedzic 在 Unsplash 上拍摄

线性代数是我们如此熟悉的强大的机器学习算法的背后

线性代数是广泛应用于各个学科的数学领域。数据科学领域也依赖于线性代数的许多不同应用。这并不意味着每个数据科学家都需要有非凡的数学背景,因为你将处理的数学量在很大程度上取决于你的角色。然而,很好地理解线性代数确实会增强对许多机器学习算法的理解。首先,要真正理解深度学习算法,线性代数是必不可少的。本文介绍了最重要的基本线性代数概念,并展示了线性代数的两个相关数据科学应用。

内容

  • 矩阵和向量
  • 矩阵运算
  • 矩阵求逆
  • 正交矩阵
  • 线性代数在数据科学中的应用(奇异值分解和主成分分析)

矩阵和向量

简而言之,我们可以说线性代数是向量和矩阵的数学。我们利用这样的向量和矩阵,因为它们是表示大量信息的方便的数学方法。

矩阵是由行和列组成的数字、符号或表达式的数组。矩阵的特征在于它的行数 m 和列数 n。一般来说,阶为' m x n '(读作:“m 乘 n”)的矩阵具有 m 行和 n 列。下面,我们展示一个 2×3 矩阵 A 的例子:

我们可以通过相应的行和列来引用矩阵的各个元素。例如,A[1,2] = 2,因为数字 2 位于第一行第二列。

只有一列的矩阵称为向量。例如,上面矩阵 A 的每一列都是一个向量。让我们把矩阵 A 的第一列作为向量 v:

在向量中,我们也可以指单个的元素。这里,我们只需要使用一个索引。例如,v[2] = 4,因为 4 是向量 v 的第二个元素。

矩阵运算

当我们能够用矩阵进行代数运算时,我们分析和解决线性代数领域中特殊问题的能力将会大大提高。这里列出了执行这些操作的最重要的基本工具。

㈠矩阵和

如果 A 和 B 是 m×n 矩阵,那么 A+B 就是 m×n 矩阵,它的列是 A 和 B 中对应列的和,和 A+B 只有在 A 和 B 大小相同时才定义。

当然,矩阵的减法,A-B,以同样的方式工作,B 中的列从 a 中的列中减去

(二)标量倍数

如果 r 是标量,那么矩阵 A 的标量倍数是 r*A,即其列是 A 中相应列的 r 倍的矩阵。

㈢矩阵向量乘法

如果矩阵 A 的大小是 m×n(因此,它有 n 列),并且 u 是大小为 n 的向量,那么 A 和 u 的乘积,用 Au 表示,是 A 的列的线性组合,使用 u 中的相应条目作为权重。

:只有矩阵 A 的列数等于向量 u 的项数,才定义乘积 Au!

性质:如果 A 是 m×n 矩阵,u 和 v 是大小为 n 的向量,r 是标量,则:

㈣矩阵乘法

如果 A 是一个 m×n 矩阵,B = [ b 1, b 2,…, b p]是一个 n×p 矩阵,其中 b i 是矩阵 B 的第 I 列,那么矩阵乘积 AB 就是 m×p 矩阵,它的列是 A b 1,A b 2,…,A b p。所以

因为

:A 中的列数必须与 B 中的行数相匹配,才能进行矩阵乘法。

性质:设 A 是 m×n 矩阵,设 B 和 C 的大小使得和与积被定义,设 r 是标量。然后:

(五)矩阵的幂

如果 a 是一个 n×n 矩阵, k 是一个正整数,那么 A^k (A 的 k 次方)是 a 的 k 个副本的乘积:

㈥矩阵转置

假设我们有一个大小为 m×n 的矩阵 a,那么 a 的转置矩阵(用 A^T 表示)是 n×m 矩阵,它的列是由 a 的相应行组成的

性质:设 A 和 B 为矩阵,其大小适合下列和与积。然后:

矩阵求逆

矩阵代数提供了处理矩阵和创建各种有用公式的工具,其方式类似于用实数处理普通代数。例如,一个实数的(乘法),比如说 3,就是 3^-1,或者 1/3。该逆满足以下等式:

这个概念可以推广到方阵。如果存在一个 n×n 矩阵 C,则称 n×n 矩阵 A 是可逆的:

其中 I 是 n×n单位矩阵。单位矩阵是对角线上有 1 而其他地方有 0 的方阵。下图显示了 5 x 5 单位矩阵:

回到上面的可逆性原理,我们称矩阵 c 为 a 的事实上,c 是由 a 唯一确定的,因为如果 b 是 a 的另一个逆,那么 B = BI = B(AC) = (BA)C = IC = C。这个唯一的逆由 A^-1 表示,因此:

属性:

正交矩阵

正交矩阵是其列和行是正交单位向量的方阵。也就是说,正交矩阵是可逆矩阵,我们称之为 Q,其中:

这导致了等价的特征:如果矩阵 Q 的转置与其逆矩阵相等,则矩阵 Q 是正交的:

线性代数在数据科学中的应用

为了展示线性代数在数据科学领域中的相关性,我们将简要介绍两个相关的应用。

奇异值分解

奇异值分解是数据科学领域中一个非常重要的概念。奇异值分解的一些重要应用是图像压缩和降维。让我们在这里集中讨论后一种应用。降维是将数据从一个高维空间转换到一个低维空间,这样原始数据中最重要的信息仍然保留。这是期望的,因为一旦数据的维度太高,数据的分析在计算上变得难以处理。

SVD 将矩阵分解为三个独立矩阵的乘积,如下所示:

在哪里

假设矩阵 M 是一个 M×n 矩阵:

  • u 是左奇异向量的 m×m 正交矩阵;
  • σ是 M×n 矩阵,其中 D(即 r×r)中的对角元素是 M 的前 r 个奇异值
  • v 是右奇异向量的 n×n 正交矩阵。

奇异值可用于理解由每个奇异向量解释的方差量。它捕捉的差异越多,它包含的信息就越多。通过这种方式,我们可以使用这些信息将向量的数量限制在我们希望捕获的方差的数量之内。

手动计算 SVD 是可能的,但是当矩阵变得更高维时,这很快变成一个密集的过程。在实践中,人们正在处理大量的数据。幸运的是,通过使用Numpy,我们可以很容易地用 Python 实现 SVD。为了使例子简单,我们定义一个 3×3 的矩阵 M:

import numpy as np
from numpy.linalg import svd

# define the matrix as a numpy array
M = np.array([[4, 1, 5], [2, -3, 2], [1, 2, 3]])

U, Sigma, VT = svd(M)

print("Left Singular Vectors:")
print(U)
print("Singular Values:")
print(np.diag(Sigma))
print("Right Singular Vectors:")
print(VT)

输出:

Left Singular Vectors:
[[-0.84705289  0.08910901 -0.52398567]
 [-0.32885778 -0.8623538   0.38496556]
 [-0.41755714  0.49840295  0.75976347]]
Singular Values:
[[7.62729138 0\.         0\.        ]
 [0\.         3.78075422 0\.        ]
 [0\.         0\.         0.72823326]]
Right Singular Vectors:
[[-0.58519913 -0.09119802 -0.80574494]
 [-0.23007807  0.97149302  0.0571437 ]
 [-0.77756419 -0.21882468  0.58949953]]

因此,在这个小例子中,奇异值(通常表示为σ)为σ1 = 7.627,σ2 = 3.781,σ3 = 0.728。于是,当只使用前两个奇异向量时,我们解释为(σ1 + σ2 ) / (σ1 + σ2 + σ3 ) = 99.3%的方差!

主成分分析

正如奇异值分解一样,主成分分析(PCA) 是一种降维的替代技术。PCA 的目标是创建新的不相关变量,称为主成分,最大化捕获的方差。因此,我们的想法是降低数据集的维度,同时尽可能多地保留“可变性”(即信息)。这个问题归结为求解一个特征值-特征向量问题。

由于特征值和特征向量超出了本文的范围,我们将不深究 PCA 的数学解释。

结论

在数据科学领域,数学无处不在。要成为一名成功的数据科学家,你绝对不需要知道每个概念背后的所有数学细节。然而,为了能够在处理数据和算法时做出更好的决策,您需要对其背后的数学和统计学有坚实的理解。本文主要关注线性代数的基础知识,作为一名数据科学家,这是一门非常重要的数学学科。

Python 中列表理解的基础

原文:https://towardsdatascience.com/basics-of-list-comprehensions-in-python-e8b75da50b30?source=collection_archive---------40-----------------------

技术的

理解如何在 python 编程语言中比循环标准更快地创建序列类型列表

照片由克莱门特·H在 Unsplash 上拍摄

介绍

本文介绍了列表理解的基础 Python 语言中一种常见的编程语法风格。

尽管列表理解在 python 中很常见,但是来自松散类型语言(如 JavaScript)的程序员可能不熟悉列表理解。

列表理解背后的直觉很容易理解,它们的实现方法也是如此。

所以本文旨在做以下几点:

  • 呈现列表理解的直觉
  • 用示例代码比较创建列表的标准方法和使用列表理解的方法
  • 利用列表理解的好处
  • 围绕列表理解主题的常见关键术语的定义。

列表

列表是 Python 编程语言中常见的序列类型之一。还有其他常见的序列类型,如元组、集合或字节数组。

example_list = ['deeplearning', 'machinelearning', 'python', 'datascience']
print(example_list)
print(type(example_list))>> ['deeplearning', 'machinelearning', 'python', 'datascience']
>> <class 'list'>

给来自 JavaScript 等语言的人的提示。列表和数组可能看起来相似,但它们在 Python 中并不相同。Python 中经常使用列表。下面就简要解释一下它们的区别

python 编程语言中的列表被归类为序列类型。序列类型通常能够以结构化的方式存储一个或多个值。

列表是序列类型,可以分为容器序列和可变序列。

  • 容器序列中存储了对象的引用,而不是对象本身。
  • 可变序列允许修改包含在其中的对象。

列出理解

我们对列表有了一个了解,现在可以深入到列表理解这个话题了。

与使用 for 循环的传统方式相比,列表理解是在 python 中构造列表的一种有效方式。

密码

下面的代码片段描述了构建列表的标准方式

下面的代码没有多大意义,写出来只是为了说明。

name = 'James'
name_and_number = []for i in range(5):
   name_and_number.append(name + ' ' + str(i))
print(name_and_number)>> ['James 0', 'James 1', 'James 2', 'James 3', 'James 4']

上面的代码简单地将数字添加到名称中,并修改在变量' name_and_number 中初始化的空列表。

现在让我们看看如何用列表理解生成相同的列表。

name = 'James'
name_and_number = [name + ' ' + str(i) for i in range(5)]
print(name_and_number)
>>['James 0', 'James 1', 'James 2', 'James 3', 'James 4']

仅此而已,三行代码实现了相同的结果,如果不包括 print 语句,则需要两行。

列表理解的好处是显而易见的,我将在下面的部分总结它们。

在我们继续之前,读者应该注意到,“ for ”循环允许对列表中的每个元素执行更多的操作,而列表理解只是为构造列表而设计的。

您也可以在列表理解中放置条件语句。

name = 'James'
name_and_number = [name + ' ' + str(i) for i in range(5) if i%2==0 ]
print(name_and_number)
>> ['James 0', 'James 2', 'James 4']

利益

  • 简洁:当使用普通的 for 循环时,列表可以在一行中生成,而不是几行
  • 可读性:列表理解有一个易于阅读的语法,可以很容易地传达实现的目的。

列表理解是一个有用且容易理解和学习的概念,请随意使用你的例子。

如果你喜欢这篇文章,这里有一些我写的。

[## 人工智能中的算法偏差需要讨论(和解决)

你在这件事上有责任…

towardsdatascience.com](/algorithm-bias-in-artificial-intelligence-needs-to-be-discussed-and-addressed-8d369d675a70) [## 为什么机器学习工程师(或数据科学家)不是这场秀的主角

但是我们仍然是成功的员工队伍中不可或缺的一部分

towardsdatascience.com](/why-machine-learning-engineers-or-data-scientists-are-not-the-stars-of-the-show-d91ec9c5256b)

机器学习所需的 Python 基础知识及其库模块

原文:https://towardsdatascience.com/basics-of-python-and-its-library-modules-required-for-machine-learning-51c9d26026b8?source=collection_archive---------21-----------------------

关于 ML 的一切

通过对机器学习所需的每个库的直观理解,学习 python 数据结构的基础知识

照片由在 Unsplash 上拍摄

ython 是数据科学、机器学习和深度学习的最佳编程选择之一。Python 为完成每项任务提供了广泛的选择。它非常容易使用,也是开始编程的最佳方式之一,因为它使用起来相当简单,学习起来也相当容易。它还有一个不断更新和升级的社区。在撰写本文时,python 的最新版本是 3.8。

本文假设读者具有轻微或适度的编程知识,并了解一点 python。如果你之前没有编程知识,那么不要担心。Python 非常容易上手,YouTube 上有大量免费视频,网上也有很多有趣的教程。如果你们想让我从头开始做一个 python 基础教程,请随时告诉我。只要对 python 有一个基本的了解,我们就可以继续了解这种令人惊叹的语言,以及对机器学习有益的所有扩展和库。

注意:这将是我的“关于机器学习”课程的第二部分。但是,每个后续零件都将是独立零件。你可以根据你的方便以任何顺序阅读这个系列。我将在接下来的文章中尝试涵盖基础知识和大多数机器学习算法。要查看该系列的其他部分,您可以点击此处。如果你还没有看过之前的文章,请点击下面的链接。

[## 开始使用 Python 掌握机器学习的旅程

了解精通机器学习的基本要求

towardsdatascience.com](/starting-your-journey-to-master-machine-learning-with-python-d0bd47ebada9)

你可以从下面的链接下载 python。

[## 下载 Python

关于特定端口的信息、开发人员信息来源和二进制可执行文件由发布经理或……

www.python.org](https://www.python.org/downloads/)

你能从这篇文章中期待什么?

今天,我们将探讨机器学习所需的 python 的所有基本概念。我们将理解 python 的各种数据结构,然后继续深入挖掘机器学习所需的所有库的基础。我们将用一些简单的代码片段来涵盖所有这些概念,以便更好地掌握这些库和特性。所以,事不宜迟,让我们动手做一些编码吧!

在 Unsplash 上由 Max Duzij 拍照

Python 中的数据结构:

数据结构是以某种方式组织起来的数据元素的集合。python 中有很多内置的数据结构。让我们逐一探讨这些问题。

1.列表—

列表是可变的有序元素序列。可变意味着列表可以被修改或改变。列表用方括号“[ ]”括起来。我们在 python 中用于机器学习的列表的重要函数是——“append ”,用于向列表添加元素,“len”函数用于查找列表的长度,而“sort”函数用于按升序排列列表中的元素。这三个通常是列表中最常用的函数。列表切片是另一个理解起来非常有用的概念。列表元素可以通过它们的索引号来寻址。第 0 个索引由第一个元素组成,第 1 个索引由第二个元素组成,依此类推。

关于列表的另一个重要概念是列表理解。这是通过提供一种简洁的方式来创建列表,从而简化代码。创建多达 10 个正方形的示例如下:

您也可以在名为嵌套列表的列表中创建一个列表。这些通常对机器学习中的矩阵运算有帮助。

2.字典—

字典是条目的无序集合。与列表和其他数据结构(如元组或集合)不同,字典数据结构有一对称为键和值的元素。dict()函数可以用来给一个变量分配一个字典。另一种方法是使用花括号' {} '将变量指定为字典。定义了一个字典之后,我们主要有三个函数——items函数用于查看字典的键和值, keys 函数用于访问字典的键, values 函数用于访问各个键的所有值。字典功能甚至可以用于为熊猫图书馆构建数据框。它是和列表一样重要的数据结构之一。下面的例子展示了如何声明一个字典并访问字典中的所有变量。

3.元组—

元组数据结构类似于列表数据结构,在列表数据结构中,可以用固定数量的元素定义元组。唯一的区别是元组是不可变的。这可以防止对元组中的元素进行任何修改,因为不能从创建的特定元组中追加或删除更多的元素。可以通过指定元组函数或使用普通括号“()”来创建元组。访问元组中的元素的过程可以通过访问它的特定索引位置来完成,类似于列表。还可以创建嵌套元组,即元组中的元素元组。元组数据结构的主要优点是它可以适合于定义图上的(X,Y)点,使得这些点在整个程序中保持一致并且不能被改变。让我们看一个嵌套元组的例子,其中主元组包含((x1,y1))和(x2,y2)形式的另外两个元组。让我们来看看如何访问元组的 y1 元素,如下面的代码块所示。

上面代码块的输出是 2,也就是 y1 和我们想要访问的元素。

4.集合—

集合是无序元素的集合。这些元素也没有被索引。可以通过使用 set 函数或使用只有一个元素的大括号“{ 0 }”来定义集合。集合数据结构是可变的,因为元素可以被添加或删除,但是集合只包含每个元素中的一个。元素的重复不能在一个集合中重复,并且一个集合总是有序的。从最小意义到最大意义进行排序,即按升序排序。集合可用于执行数学集合运算,如并、交、对称差等。下面是一个代码块,展示了集合的简单工作。

其他的数据结构是字符串冻结集。大多数观众在学习 python 的基础知识时都已经了解了字符串。我将简要介绍字符串,但我个人并没有在我的机器学习项目中大量使用冻结集,因为我觉得它没那么有用。如果你有兴趣了解更多关于这些的信息,请随时学习。

字符串可以在单引号“”或双引号“”中定义。字符串是不可变的字符序列。计算机不处理字符。相反,他们处理数字,尤其是二进制数字。尽管您可能在屏幕上看到字符,但在内部,它是以 0 和 1 的组合形式存储和操作的。这种将字符转换为数字的过程称为编码,相反的过程是解码。美国信息交换标准码(ASCII)和 Unicode 是一些常用的编码。在 Python 中,字符串是 Unicode 字符序列。字符串用于编码的常用格式化技术是用字节表示的 UTF-8 标准。

照片由 Emil Widlund 在 Unsplash 拍摄

python 中用于机器学习的基本重要库:

1.熊猫—

Pandas模块是 python 中的一个开源库,用于创建数据框,这对于组织数据非常有用。Pandas 广泛用于数据科学、机器学习和深度学习领域,用于数据的结构化排列。在 pandas 中创建的数据框是数据的二维表示。将 pandas 库作为 pd 导入后,您可以可视化您喜欢的表格数据。这方面的一个例子如下所示:

总的来说,pandas 模块是一个用于系统查看数据的极好的库,它还允许执行各种各样的操作。

2.Matplotlib —

Matplotlib 模块是可视化数据框或任何其他形式数据的最佳工具之一。Matplotlib 用于可视化数据,以便在数据科学中进行探索性数据分析。了解我们正在处理的数据类型以及确定必须执行的下一步操作非常有用。该库提供了各种各样的可视化功能,如散点图、条形图、直方图、饼图和许多其他类似的功能。将 matplotlib.pyplot 模块作为 plt 导入,以便使用 matplotlib 执行可视化任务。下面是一个例子

散点图

条形图

图中显示了使用 matplotlib 绘制的散点图和条形图。该模块的一个优点是使用非常简单,并且在提供可视化方面非常有效。它还可以与 seaborn 库结合使用,以获得更好的视觉和美学效果。

3.NumPy —

NumPy 库代表数值 Python 。numpy 库是执行矩阵运算的最佳选择之一。它支持多维数组。可以在数组上执行大量的数学和逻辑运算。通过将列表转换成 numpy 数组,我们可以执行诸如加法、减法、点积等计算。numpy 的用例适用于计算机视觉和自然语言处理项目。在计算机视觉中,您可以使用 numpy 数组来可视化 numpy 数组中的 RGB 或灰度图像,并相应地转换它们。在自然语言处理项目中,为了优化计算,您通常喜欢将文本数据转换成向量和数字的形式。将 numpy 作为 np 导入,您可以将文本数据转换为分类数据,如下所示:

4.Scikit-learn —

scikit-learn 模块是机器学习和预测数据分析的最佳工具之一。它提供了广泛的预建算法,如逻辑回归,支持向量机(SVM),分类算法,如 K 均值聚类,以及更多的操作。这是初学者开始学习机器学习算法的最佳方式,因为该模块提供了简单高效的工具。它是开源的,可以在商业上使用,同时几乎允许任何人访问。它是可重用的,并受到诸如 NumPy、SciPy 和 Matplotlib 等库的支持。导入 sklearn 模块来运行 scikit-learn 代码。下面是一个代码示例,用于将我们拥有的数据集分割成一种形式的训练和测试或验证数据。这对于模型的训练和评估是有用的。

5.NLTK —

NLTK 库代表自然语言工具包平台,它是自然语言处理数据的机器学习的最佳库之一。自然语言处理(NLP)是人工智能的一个分支,它帮助计算机理解、解释和操纵人类语言。NLTK 库非常适合基于语言的任务。它为分类、标记化、词干化、标记、解析和语义推理等任务提供了广泛的选项。它允许用户将数据分成实体,这些实体可以组合在一起,以产生更有组织的意义。该库可以作为 nltk 导入,下面是一个句子标记化的示例代码。

注:这只是对所有库的简单介绍。如果你还没有完全理解它们,那也没什么。在本系列接下来的部分中,我们将通过实际的例子以及它们在机器学习算法和问题中的具体应用来更详细地了解每一个问题。

结论:

我们能够对各种数据结构和它们执行的任务有一个简单的了解,同时对 python 中提供机器学习灵活性的各种库有一个直观的了解。有了 python 及其相应的机器学习库模块的基础知识,我们就可以更深入地探索机器学习的各个领域和算法了。在接下来的文章中,我们将重点关注探索性数据分析和机器学习背后的数学。一旦完成,我们将单独查看每个算法,并对它们及其特定用例进行完整的分解。

对于本文中使用的一些代码、截图和图像,参考了我以前的一些文章。请随意查看下面的参考资料。

[## 使用深度学习的人类情感和手势检测器:第 1 部分

了解如何从零开始构建具有深度学习的人类情感和手势检测器。

towardsdatascience.com](/human-emotion-and-gesture-detector-using-deep-learning-part-1-d0023008d0eb) [## 基于自然语言处理和深度学习的下一个单词预测

使用 LSTM 设计单词预测系统

towardsdatascience.com](/next-word-prediction-with-nlp-and-deep-learning-48b9fe0a17bf) [## 使用一维卷积层的创新聊天机器人

从头开始使用深度学习和 Conv-1D 层构建聊天机器人

towardsdatascience.com](/innovative-chatbot-using-1-dimensional-convolutional-layers-2cab4090b0fc)

从以下链接查看与本系列相关的所有文章:

[## 关于 Ml 的一切——走向数据科学

阅读《走向数据科学》中关于 Ml 的文章。共享概念、想法和代码的媒体出版物。

towardsdatascience.com](https://towardsdatascience.com/tagged/All About ML)

谢谢大家坚持到最后,祝大家有美好的一天!

监督学习基础(分类)

原文:https://towardsdatascience.com/basics-of-supervised-learning-classification-d26c00d80100?source=collection_archive---------40-----------------------

在具有概念、组件和示例的机器学习中

由 Unsplash 上的 Pietro Jeng 拍摄

在这篇文章中,我们将深入探讨监督学习的概念,或者更确切地说是机器学习领域中的分类。我们将讨论分类的定义、组成和例子。

分类可以定义为学习一个目标函数 f 的任务,该目标函数将每个属性集合 x 映射到一个预定义的标签 y

示例:将一条新闻分配到预定义的类别之一。

在数据科学或机器学习的社区中,对数据所做的任何事情都被称为建模。在分类的背景下,有两种类型的建模:

  1. 描述性建模:分类模型可以作为一种解释工具,用于区分不同类别的对象。示例:基于特征定义椎骨类型的模型。
  2. 预测建模:分类模型也可用于预测未知记录的类别标签。

分类技术最适合预测或描述带有二进制或名义类别的数据集。它们对于有序类别(例如,将一个人归类为高、中或低收入群体的成员)不太有效,因为它们没有考虑类别之间的隐含顺序。

从鸟瞰图分类

让我们稍微详细地看看上面提到的所有组件。

  1. 训练和测试集:整个数据通常分为两部分,一部分由学习算法用来学习一个模型(称为训练数据),另一部分用来评估所学习模型的性能(称为测试数据)。更多细节请看下面的帖子。

[## 数据挖掘和机器学习中的数据预处理

有了详细的概念…

towardsdatascience.com](/data-preprocessing-in-data-mining-machine-learning-79a9662e2eb) [## Python 中的数据预处理

对于机器学习与工作代码的例子…

towardsdatascience.com](/data-preprocessing-in-python-b52b652e37d5)

2.学习算法:它是一种在数据集(训练集)中寻找模式,并将该数据的属性与训练数据集中提到的类别关联起来的算法,这样当测试数据作为输入时,它就可以分配准确的类别。

学习算法的一个关键目标是建立具有良好概括能力的模型,即准确预测先前未知记录的类别标签的模型。

3.模型/分类器:它实际上做分类。它识别一个数据实例与另一个数据实例的差异,然后将新的数据实例分配给其中一个类。

4.归纳与演绎:在理解它之前,需要理解分类的两个阶段。它们分别是学习和查询阶段。

学习阶段由两部分组成,即归纳(训练)和演绎(测试)。

查询阶段也称为应用阶段。

现在用更正式的方式来说吧。

正式定义:

  • 在任务测试上有所改进,
  • 关于业绩计量 P,
  • 基于经验 e。

这个正式的定义可能有点难以理解。举几个例子可以更好理解。

示例:垃圾邮件分类

  • 任务 T-将电子邮件分类为垃圾邮件/非垃圾邮件
  • 性能指标 P —正确分类的电子邮件的比例
  • 体验 E —手动标记垃圾邮件/非垃圾邮件

举例:跳棋

  • 任务 T —玩跳棋
  • 绩效指标 P —锦标赛中获胜游戏的百分比
  • 体验 E——与自我对抗的机会

其他例子包括

  • 基于 MRI 扫描的结果将细胞分类为恶性或良性
  • 根据星系的形状对它们进行分类

上述这些例子可以基于不同的学习方法进行建模。以下是一些学习方法:

  1. 朴素贝叶斯分类器
  2. 决策树分类器
  3. 神经网络
  4. 基于规则的分类器
  5. 支持向量机

还有很多。

我将免费赠送一本关于一致性的电子书。在这里获得你的免费电子书。

感谢您的阅读。我希望阅读这篇文章的人都清楚监督学习的基本知识。

如果你喜欢阅读这样的故事,那么你应该 在你的收件箱 中收到我的帖子,如果你想支持我成为一名作家,考虑注册成为一名媒体成员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你注册使用我的链接,我会赚一小笔佣金,不需要你额外付费。

[## 加入我的推荐链接-塔伦古普塔

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

tarun-gupta.medium.com](https://tarun-gupta.medium.com/membership)

你可以在这里阅读我的更多帖子:

[## 标记故事列表的快速链接—感谢您的访问

我也有一份以快节奏出版为目标的出版物。读书成为作家。

tarun-gupta.medium.com](https://tarun-gupta.medium.com/thank-you-for-visiting-my-profile-9f708062c75e)

使用 Tensorflow 的标记器基础

原文:https://towardsdatascience.com/basics-of-tokenizer-using-tensorflow-f5c8e04d686?source=collection_archive---------46-----------------------

一个直观的仪表板,用于研究记号赋予器的工作原理

这篇文章是写给那些在自然语言处理领域是新手,想做一个情感分类/文本分类的项目的人。

由罗曼·维尼斯在 Unsplash 上拍摄的照片

什么是标记化?

顾名思义,记号化意味着将句子分成一系列记号,或者用外行的话来说,我们可以说,只要句子中有空格,我们就在它们之间添加一个逗号,这样我们的句子就会被分解成记号,每个单词都获得一个唯一的整数值。

下面是使用 TensorFlow 的 python 代码。

tokenizer = Tokenizer ( num_words=20, oov_token='<OOV>')
tokenizer.fit_on_texts(sentence)word_index=tokenizer.word_index
sequences=tokenizer.texts_to_sequences(sentence)

在执行了上面这段代码后,我们的普通文本被转换成一组整数,如下所示。

[[3, 4, 5, 2], [3], [4, 5, 2], [6, 7, 8], [9, 2]]
['Hello How are you ?', 'Hello', 'How are you', 'I am fine', 'Thank You']

现在我们的任务是将可变长度的数组转换成固定长度的数组,这可以使用填充来完成。

什么是填充?

填充是通过截断(如果长度大于定义的 max_length,则截断数组)或填充(如果长度小于 max_length,则用 0 填充数组)将可变长度的整数数组转换为固定长度的方法。

下面是这样做的 python 代码。

padded=pad_sequences(sequences, maxlen=7, truncating='post')

执行上面的代码后,我们的新数组的长度将是固定的,如下所示。

[[0 0 0 3 4 5 2]
[0 0 0 0 0 0 3]
[0 0 0 0 4 5 2]
[0 0 0 0 6 7 8]
[0 0 0 0 0 9 2]]

对应文字的整数值

下面是 python 代码,看看每个单词对应的值是什么。

tokenizer.word_index

执行上述代码后,输出将如下所示。

{'<OOV>': 1, 'am': 7, 'are': 5, 'fine': 8, 'hello': 3, 'how': 4, 'i': 6, 'thank': 9, 'you': 2}

结论

在这里,我们实现了基本的标记器,这将有助于使用深度学习进行情感分类,并将用于真实世界的数据集中。

批量标准化说明

原文:https://towardsdatascience.com/batch-normalisation-explained-5f4bd9de5feb?source=collection_archive---------16-----------------------

批量标准化

批量标准化工作原理及其解决的问题的详细指南

在这篇文章中,我详细介绍了批量规范化及其工作原理。Loffe 和 Szegedy 在 2015 年引入了批量规范化,并迅速成为几乎每个深度网络中实施的标准功能。

概述

  1. 内部协变量移位
  2. 消失和爆炸渐变
  3. 批量标准化是如何工作的?
  4. 批量标准化的优势

1.内部协变量移位

批量标准化处理的关键问题是内部协变量移位。由于神经网络的本质,会发生内部协变量移位。在训练的每一个时期,权重被更新,不同的数据被处理,这意味着神经元的输入每次都略有不同。当这些变化传递到下一个神经元时,它会产生一种情况,即每个神经元的输入分布在每个时期都是不同的。

通常,这没什么大不了的,但在深层网络中,输入分布的这些微小变化会快速累积,并在网络深处放大。最终,由最深层神经元接收的输入分布在每个时期之间变化很大。

因此,这些神经元需要不断适应不断变化的输入分布,这意味着它们的学习能力受到严重制约。这种不断变化的输入分布被称为内部协变量移位。

2.消失和爆炸渐变

批量规格化处理的另一个问题是消失或爆炸梯度。在整流线性单元(ReLUs)之前,使用饱和激活函数。饱和函数是具有朝向左右边界的“平坦”曲线的函数,例如 sigmoid 函数。

Sigmoid 曲线及其导数

在 sigmoid 函数中,随着 x 的值趋向于∞,梯度趋向于 0。随着神经网络被训练,权重可以被推向 s 形曲线的饱和端。这样,梯度变得越来越小,接近 0。

当这些小梯度在网络中更深地相乘时,它们会变得更小。当使用反向传播时,梯度以指数方式接近 0。这种“消失”梯度严重限制了网络的深度。

虽然可以通过使用 ReLU 等非饱和激活函数轻松管理这种消失梯度,但批量归一化仍然有一席之地,因为它通过确保没有值变得过高或过低,防止权重被推到那些饱和区域。

3.批量标准化是如何工作的?

批量标准化通过减去小批量平均值除以小批量标准偏差来标准化层输入。小批量指的是为任何给定时期提供的一批数据,是整个训练数据的子集。

批量归一化的公式,其中 x̂指的是归一化的向量。

标准化确保输入的平均值为 0,标准偏差为 1,这意味着每个神经元的输入分布是相同的,从而解决了内部协变量偏移的问题,并提供了正则化。

然而,网络的代表性已经严重受损。如果对每一层进行归一化,则前一层所做的权重变化和数据间的噪声会部分丢失,因为在归一化过程中会丢失一些非线性关系。这可能导致传递次优权重。

为了解决这个问题,批处理规格化增加了两个可训练的参数,gamma γ和 beta β,它们可以缩放和移动规格化的值。

随机梯度下降可以在标准反向传播过程中调整γ和β,以找到最佳分布,从而解决数据之间的噪声和权重变化的稀疏性。从本质上讲,这些参数缩放并改变了归一化的输入分布,以适应给定数据集的特性。

例如,假设未归一化的输入分布对于给定的数据集是最佳的,γ和β将收敛到√Var[x]和 E[x],从而获得原始的未归一化的 x 向量。因此,批量归一化确保归一化对于给定的数据集总是最优的。

a.为什么要针对小批量进行标准化?

理想情况下,标准化应该针对整个训练数据集,因为这确保了不同批次之间的输入分布没有变化。然而,由于不在当前批次中的任何数据集都在反向传播的范围之外,随机梯度下降将不起作用,因为归一化中使用的统计数据来自该范围之外。

因此,标准化是针对小批量进行的,以确保可以进行标准反向传播。唯一的含义是,每一批应该在某种程度上代表整个训练集的分布,如果您的批大小不是太小,这是一个安全的假设。

b.测试阶段

在训练期间,使用小批量中的样本计算平均值和标准偏差。但是,在测试中,计算新值没有意义。因此,批量标准化使用在训练期间计算的运行平均值和运行方差。需要引入一个新的参数,动量或衰变。

running_mean = momentum * running_mean + (1-momentum) * new_mean
running_var = momentum* running_var + (1-momentum) * new_var

动量是对最后一次看到的小批量的重视,也被称为“滞后”。如果动量设置为 0,运行平均值和方差来自最后一次看到的小批量。然而,这可能是有偏见的,不是理想的测试。相反,如果动量设置为 1,它将使用第一个小批量的运行平均值和方差。本质上,动量控制每个新的小批量对运行平均值的贡献。

理想情况下,动量应设置为接近 1 (>0.9),以确保运行均值和方差的缓慢学习,从而忽略小批量中的噪声。

4.批量标准化的优势

a.更高的学习率

通常,较大的学习速率会导致梯度消失/爆炸。然而,由于批量标准化处理了这一点,可以放心地使用更大的学习率。

b.减少过度拟合

批量归一化具有正则化效果,因为它向每一层的输入添加了噪声。这阻止了过度拟合,因为模型不再单独为给定的训练示例产生确定性的值。

结论

批量标准化的力量已经在机器学习的许多领域反复展示。这是一个简单的解决方案,将产生几乎任何型号的性能显着改善。

参考资料:

[1] 批量归一化:通过减少内部协变量偏移加速深度网络训练

为什么批量归一化在深度神经网络中有用?

原文:https://towardsdatascience.com/batch-normalisation-in-deep-neural-network-ce65dd9e8dbf?source=collection_archive---------8-----------------------

数据科学,深度学习

批量规范化有助于深度神经网络的规范化

纳斯蒂亚·杜尔希尔在 Unsplash 上的照片

在本文中,您可以探索规范化与批量规范化,为什么深度学习需要批量规范化,批量规范化在深度神经网络中是如何执行的,以及批量规范化的优势是什么?

什么是规范化 vs 批量规范化?

标准化是将数据集中数值变量的值更改为典型标度的过程,不会在值的范围内形成错误的对比。

批量标准化是一种用于训练深度神经网络的技术,可对每个小批量的层贡献进行标准化。这有助于解决学习过程,并大幅减少训练深度神经网络所需的训练次数。

深度学习为什么需要批量归一化?批处理规范化为什么有帮助?

深度学习中,准备具有许多层的深度神经网络,因为它们可能对底层初始随机权重和学习算法的设计很敏感。

这个问题背后的一个潜在目的是,当权重被刷新时,在每个小批量之后,网络中某处的层的输入分布可能改变。这可以使学习算法始终追求一个移动的目标。对网络中各层的输入分布的这种调整暗指了专门的名称内部协变量移位

挑战在于,利用接受当前层之前的层中的权重是固定的误差估计,从输出到输入逐层反向刷新模型。

批量规格化 给出了一个丰富的参数化实际上任何深度神经网络的方法。重新参数化从根本上减少了跨多个层规划更新的问题。

深度神经网络是如何进行批量归一化的?

它通过对每个小批量的每个输入变量的激活进行归一化,明确地缩放该层的输出,例如,来自最后一层的节点的制定。回顾一下,标准化意味着重新调整数据以使平均值为 0,而标准偏差为 1。

通过使每一层的输入变亮,它将朝着实现输入的固定分布迈出一大步,这将消除内部协变量移动的不利影响。

归一化早期层的激活意味着后续层在权重更新期间做出的关于输入的传播和分布的假设不会改变,无论如何不会显著改变。这具有稳定和加速深度神经网络的准备训练过程的影响。

对于不包含来自训练数据集的模型的代理分布的较小的小批量,训练和推理(利用训练后的模型)之间的标准化输入的差异可以在执行性能中带来可察觉的对比。这可以通过改变称为批量重正化的技术来实现,该技术使得小批量的变量平均值和标准偏差的评估越来越稳定。

这种输入的标准化可以应用于第一个隐藏层的输入变量,或者应用于更深层的隐藏层的激活。

倾向于与大多数深度网络类型一起使用,例如 卷积神经网络(CNN) 递归神经网络(RNN)

它可以用在先前层的输入上,或者用在过去层的激活功能之后。

如果对于像 双曲正切 逻辑函数 这样的 s 形容量,激活函数后可能会更加合适。

它可能在激活函数之前适合于可能在非高斯散射中上升的激活,如整流线性激活函数(ReLU)** ,这是大多数深度神经网络类型的前线默认值。**

它提供了一些正则化影响,减少了泛化误差,可能需要利用丢失进行正则化。

批量标准化网络中,平均值和方差在整个网络中保持适度稳定。对于一个非规范化的网络,他们似乎以指数发展有深度。

批量标准化的优势是什么?

  • 该模型对超参数调整不太敏感。也就是说,尽管更大的学习率已经促进了无价值的模型,更大的 lr 在这一点上是令人满意的
  • 收缩内部协变移位
  • 减少渐变对参数比例或其潜在值的依赖
  • 权重初始化在这一点上不太重要
  • 辍学者可被疏散进行调整

结论

这使我们达到了本文的最大限度,在这里我们发现了批处理规范化和利用它的优点。批处理规范化解决了一个叫做内部协变量移位的主要问题。

它有助于使神经网络中间层之间的数据流动看起来,这意味着你可以使用更高的学习速率。它有一个正规化的效果,这意味着你可以经常消除辍学。

现在,把你对TwitterLinkedin,以及Github!!

同意 还是 不同意 与 Saurav Singla 的观点和例子?想告诉我们你的故事吗?

他乐于接受建设性的反馈——如果您对此分析有后续想法,请在下面的 评论 或联系我们!!

推文@ SauravSingla _ 08、评论Saurav _ Singla以及明星SauravSingla

批量标准化—直观的解释

原文:https://towardsdatascience.com/batch-normalization-an-intuitive-explanation-42e473fa753f?source=collection_archive---------20-----------------------

为什么批量范数有助于训练深度学习模型?

这篇文章的目的是提供一个简单直观的理解批处理规范化(BN)以及它如何帮助训练更深更好的模型。我们开始吧,好吗?

开始吧!伊恩·杜利在 Unsplash 上拍摄的照片

前奏:

一般来说,规范化是指将不同范围的数字压缩到一个固定的范围。例如,考虑简单双参数模型 f(x)的输入 x1x2

f(x)= w1 * x1+w2 * x2

如果 x1 和 x2 处于完全不同的范围,比如 x1 的范围是[1000–2000]而 x2 的范围是[0.1–0.5],那么按原样使用它们就意味着优化我们的损失函数。直观地说,在这种情况下,模型参数没有一个公平的竞争环境,网络容易被 w1 压倒。通过将 x1 和 x2 的范围归一化为[0–1 ],可以使所有输入达到相似的范围,并帮助模型更快地学习。这是应用于输入的规范化的特例,称为 输入规范化 (咄!).在计算机视觉中,通常使用训练数据集的平均值和标准差来标准化模型输入。如果你仍然困惑,我推荐这个来自吴恩达的简短的视觉解释。

好了,有了上述直觉,让我们问这个问题:考虑到输入只是深层神经网络(DNN)的另一层,那么模型的其他层的输入呢?将这些中间输入标准化是否也有益?

这就引出了我们的问题陈述。

问题——或者说我们为什么需要批量定额:

深度学习模型通常是一系列级联的层,每一层都接收一些输入,应用一些计算,然后将输出移交给下一层。本质上,每一层的输入构成了该层试图以某种方式“适应”的数据分布。现在,只要一个层的输入数据分布在数据的多个批处理/传递中保持相当一致,该层就可以轻松地完成拟合数据的“任务”。

但是模型/网络管道的本质使得这种一致的输入分布的期望变得困难。随着不同的小批量数据在网络中加载和传递,各层的输入分布会发生跳跃,使我们的各层更难完成工作。除了拟合基础分布之外,所讨论的图层现在还必须考虑图层输入分布中的漂移。这种转移输入分布的现象被称为 内部同变量转移

另一个问题是,当网络的不同参数的比例与梯度更新相关联时,它们可能导致 爆炸和消失梯度 。一些激活可能会被推到它们的饱和区域,并且可能永远不会从那里恢复。直观上,模型参数不再具有公平的竞争环境(就像前面提到的 f(x)中 w1 和 w2 的比例一样),并且一些参数的梯度可能不受控制地增加和减少。因此,从梯度更新中分离网络参数的比例可能有利于训练。 避免爆炸和消失梯度的变通方法通常包括使用更鲁棒的激活函数,如【ReLU】, 选择较低的学习速率和小心初始化网络参数,但由于有许多旋钮要调节,核心问题仍然存在:训练我们的 DNN 是一个挑战。

解决方案:

批处理规范化旨在解决我们上面描述的问题:

  1. 避免不稳定的梯度
  2. 减少网络初始化对收敛的影响。
  3. 允许更快的学习速率导致更快的收敛。

所有这些都是通过一个相当简单的方法→ 来实现的,即使用数据集均值和标准偏差 来归一化每个中间层的输入。理想情况下,与输入归一化一样,批处理归一化也应基于整个数据集归一化每个图层,但 t 这并非微不足道,因此作者进行了简化: 使用小型批处理统计数据而非 进行归一化,因此得名—批处理归一化。

就是这样!

不完全是,我还没有复制粘贴强制 BN 方程!

图片来自http://arxiv.org/abs/1502.03167

在上面的片段中,前三个方程计算批次平均值和标准差,然后分别用这些矩对输入进行归一化。第三步中的ε是一个小数值,有助于数值稳定性。需要注意的关键点是,对批处理中的所有输入维度分别进行归一化(在卷积术语中,认为是通道)

最后一个等式引入了两个参数-> 伽马(缩放)贝塔(移位)来进一步变换归一化的输入。原因是简单的标准化通过限制其范围降低了后续激活的表达能力(对于 sigmoid,这将限制其输出到 S 曲线的线性范围)。为了克服这一点,BN 允许网络学习 gamma 和 beta 参数,以便让层“调整”标准化的输入分布,使其更具表现力。与每个小批量计算的平均值和方差相反,伽马和贝塔参数是在整个数据集上学习的。

BN 有助于内部协变量转移->神话还是事实?

在介绍 BN 时,我说它有助于解决内部同变量转移的问题,这也是最初的作者声称的。但是,经过几年的辩论和研究,最近的证据指出情况可能并非如此。批次标准和内部协变量移位可能无关。事实上,在某些情况下,BN 实际上可能增加内部同变移位!

一个这样的实验训练了三个不同的模型:

1.没有国阵的 DNN

2.一个 DNN BN

3.具有 BN 的 DNN ,但是现在具有添加噪声(在应用 BN 之后并且在应用激活以创建同变量移位之前)。****

结果表明,后两种模型更快地达到更好的精度,这是预期的,因为它们使用了 BN。然而,第二种模式并不比第三种模式好多少。这表明,虽然 BN 确实有助于更好的训练制度,但它可能与内部协变量变化无关。

那么,BN 到底为什么有效呢?

有些答案很直观。由于 BN 对每一层的输入进行归一化,这将梯度从网络参数的规模中解耦,从而防止不稳定的梯度。这也允许更高的学习率,因为网络现在有更少的机会卡住。所有这些都是稳定训练体制的关键因素。

进一步观察发现,BN 实际上将优化过程(准确地说是损失面)重新参数化为更平滑的状态。直观地说,这意味着 BN 采用了一个充满山丘和山谷的复杂损失表面,并使其变得更简单,山丘和山谷越来越少。优化过程现在可以朝着全局最优迈出更有信心和更大的步伐(具有更大的学习率),并且陷入可怕的局部最优的机会更少。用专业术语来说,这被描述为“平滑损失函数的】Lipschitz ness”。

我在参考资料部分包括了所有的资源,如果你想了解更多关于 BN 的细节,我强烈推荐你阅读前三篇文章。

今天到此为止,各位!一如既往的感谢阅读!

参考

  1. 约夫和塞格迪(2015 年)。批量标准化:通过减少内部协变量偏移来加速深度网络训练。http://arxiv.org/abs/1502.03167**
  2. 比约克、戈麦斯、塞尔曼和温伯格。了解批量标准化
    https://arxiv.org/abs/1806.02375
    **
  3. 桑图尔卡,齐普拉斯,伊利亚斯,麻省理工学院,˛。批量规范化对优化有什么帮助? https://arxiv.org/abs/1805.11604**
  4. https://www.jeremyjordan.me/batch-normalization/

解释了神经网络中的批量标准化(算法分解)

原文:https://towardsdatascience.com/batch-normalization-explained-algorithm-breakdown-23d2794511c?source=collection_archive---------11-----------------------

理解深度神经网络中使用的一种常见转换技术

瓦迪姆·谢尔巴科夫在 Unsplash 上拍摄的照片

介绍

批量归一化(BN) 是很多机器学习从业者都会遇到的技术。如果你曾经使用过卷积神经网络,比如exception、 ResNet50 和 Inception V3 ,那么你就使用过批量归一化。

这篇文章解释了 BN 背后的基本直觉。对于那些已经熟悉 BN 技术的人来说,这篇文章深入研究了 BN 算法并解释了它的关键部分。

定义

批量标准化是一种减轻深度神经网络中不稳定梯度影响的技术。BN 为神经网络引入了一个附加层,该层对来自前一层的输入执行操作。

该操作对输入值进行标准化和规范化。然后,输入值通过缩放和移位操作进行转换。

如果这令人困惑,下面的下一节将使该技术变得更加清晰。

说明

Christian Szegedy 和 Sergey Ioffe 于 2015 年在这篇已发表的论文中提出了批量标准化技术。

通过在神经网络层内引入输入值的内部标准化,执行批量标准化作为加速深度神经网络训练阶段的解决方案。

术语“批处理规范化”中使用“批处理”的原因是因为神经网络通常一次用一组经过整理的数据进行训练,这组或一组数据被称为批处理。BN 技术中的运算发生在整批输入值上,而不是单个输入值上。

通常,在机器学习中,在将数据传递到输入层之前,通常会对输入数据进行规范化。我们规范化的部分原因是为了确保我们的模型能够适当地一般化。这是通过确保值的比例是平衡的来实现的,并且尽管值的比例变化,值的范围也是保持和成比例的。

通常对输入数据进行规范化,但是网络中的内部数据流应该保持规范化。

BN 是在神经网络层之间传递的输入值内标准化的内部实施者。内部标准化限制了通常发生在层内激活的协变量偏移。

如前所述,BN 技术的工作原理是对进入 BN 层的输入数据执行一系列操作。下面是一个小批量 BN 算法的数学符号片段。

官方研究论文中提出的批量归一化操作

上图中的数学符号可能看起来有点吓人,但是有一些主要的要点。

  1. 输入数据的标准化
  2. 输入数据的归一化重新缩放
  3. 偏置输入数据

标准化是将一批输入数据转换为平均值为零、标准差为一的操作。在 BN 算法中,我们需要计算最小批量的平均值,然后计算方差。方差提供了关于标准偏差的信息;我们只需要求方差的平方根。

让我们分解算法的数学符号,解释这个过程。

计算当前小批量的平均值

第一个操作计算小批量内输入的平均值。运算的结果是一个包含每个输入平均值的向量。

m 指小批量的投入数量。

谓卑鄙。

B 是指当前批次的下标。

xi 是输入数据的一个实例。

一批(‘B’)的平均值()是通过该批的几个输入实例的总和除以输入总数(‘m’)来计算的。

计算当前小批量的差异

在上面的操作中,输入方差( σ )通过平方输入的标准偏差来计算。为了计算标准偏差,我们取当前小批量中的每个输入实例( Xi ),减去在先前操作中计算的小批量的平均值( B ),并对结果求平方。

这个值然后被平方以获得方差( σ )。

标准化输入

现在我们有了零定心和标准化输入所需的所有值。在上面的操作中,我们对输入数据进行了标准化处理。术语标准化和规范化可以互换使用。这两个术语之间有细微的差别。

在上面的操作中,从每个输入时刻减去批次的平均值。然后我们将结果除以当前批次的标准偏差值与平滑项( ε )相加的平方根值。

平滑项( ε )通过停止除以零值来确保运算中的数值稳定性。平滑项通常为 0.00005。

缩放和偏移输入

在最后一个操作中,输入值的重新缩放和偏移发生。该操作的输出是 BN 算法对当前小批量的结果。

在最后的操作中,我们介绍了 BN 算法的两个新组件。这些分量是参数向量,用于包含来自先前操作的值的向量的缩放( γ )和移位( β )。用于缩放和移位的参数向量的值是可学习的参数。在神经网络训练期间,BN 确保可学习的参数是能够使每个小批量精确标准化的最佳值。

BN 变换是提高深度神经网络性能的有效方法。

批量标准化的好处

  • 在深度神经网络中包括批量标准化技术改进了训练时间
  • BN 能够利用更大的学习速率,这在训练神经网络时缩短了收敛时间
  • 减少渐变消失的常见问题
  • 减少了神经网络内的协变量移位

结论

BN 背后的算法并没有看起来那么复杂。

通过引入现代机器学习库,如 TensorFlow 和 PyTorch ,抽象出在神经网络内实现 BN 的复杂性。这使得在神经网络中实现 BN 成为一项微不足道的任务。

理解批处理规范化算法如何操作仍然是一项有价值的技能。

3 个理解层次的批量标准化

原文:https://towardsdatascience.com/batch-normalization-in-3-levels-of-understanding-14c2da90a338?source=collection_archive---------0-----------------------

入门

到目前为止,我们对它了解多少:从 30 秒摘要到综合指南

鸣谢:贾巴里·蒂莫西上 Unsplash

T 网上有很多关于批量归一化(BN)的内容。然而,他们中的许多人都在捍卫一种过时的直觉。我花了很多时间将所有这些零散的信息放在一起,以建立对这个基本方法的良好直觉,我认为一步一步的演练可能对一些读者有用。

特别是,这个故事旨在带来:

  • 从到三级理解更新解释:30 秒,3 分钟,全面指导;
  • 涵盖关键要素以充分利用 BN;
  • 在 Google Colab 中使用 Pytorch 实现 BN 层的简单实现,从官方论文中复制基于 MNIST 的实验(随意摆弄笔记本);
  • 理解为什么 BN 仍然不为人所知(甚至在阅读了高质量作者的解释之后!).

让我们投入进去吧!

概观

a)30 秒

B) 再过 3 分钟

— 1.原理

— — 1.1.培训

— — 1.2.评估

— 2.在实践中

— 3.结果概述

C) 了解批量归一化(BN)

— 1.实施

— 2.实践中的 BN

— — 2.1.原文章结果

— — 2.2.正规化,一个 BN 副作用

— — 2.3.评估期间的标准化

— — 2.4.稳定性问题

— — 2.5.递归网络&图层归一化

— — 2.6.非线性之前还是之后?

— 3.BN 为什么管用?

— — 3.1.第一个假设:围绕内部协变量移位(ICS)的困惑

— — 3.2.第二个假设:减轻分布之间的相互依赖性

— — 3.3.第三个假设:使优化前景更加平滑

— 4.总结:我们现在了解了什么

结论

开题

致谢

参考文献

更进一步

A)在 30 秒内

【BN】**是一种算法方法,使深度神经网络【DNN】*训练更快***

它由使用当前批次的第一和第二统计矩(均值和方差)归一化来自隐藏层的激活向量组成。这个归一化步骤正好在非线性函数之前(或之后)应用。****

多层感知器(MLP) 无批量归一化(BN) | 鸣谢:作者-设计:娄高清

多层感知器(MLP)(BN)|鸣谢:作者-设计:娄高清****

所有当前的深度学习框架都已经实现了应用批量规范化的方法。它通常用作模块,可以作为标准层插入到 DNN 中。

备注:对于那些喜欢阅读代码而不是文本的人,我在 这个 repo 中写了一个简单的批量规范化实现。

b)3 分钟后

B.1)原则

在训练和测试阶段,批处理规范化的计算方式不同。

B.1.1)培训

在每个隐藏层,批量标准化将信号转换如下:

**********

BN 层首先使用(1)和(2)确定整批激活值的均值𝜇方差σ* 。*****

然后用(3)归一化激活向量****【z^(i】。这样,每个神经元的输出都遵循一个标准的正态分布。(𝜀是用于数值稳定性的常数)****

****批量归一化第一步。一个 3 神经元隐藏层的例子,批量大小为 b。每个神经元遵循标准正态分布。 | 鸣谢:作者-设计:娄高清

它最终通过应用带有两个可训练参数(4)的 𝛾𝛽 的线性变换来计算层的输出****ẑ(i】。该步骤允许模型通过调整以下两个参数来为每个隐藏层选择最佳分布:****

  • 𝛾 允许调整标准偏差;
  • 𝛽 允许调整偏差,将曲线移向右侧或左侧。

**𝛾和𝛽 参数的好处。修改分布(顶部)允许我们使用非线性函数的不同机制(底部)。 | 鸣谢:作者—设计:娄高清

备注:解释 BN 层有效性的理由容易受到误解和错误的影响(即使在原文中也是如此)。最近的一篇论文[2]反驳了一些错误的假设,提高了社区对这种方法的理解。我们将在第 C.3 节讨论这个问题:“BN 为什么起作用?”。

在每次迭代中,网络计算与当前批次相对应的平均𝜇和标准差σ。然后,它通过梯度下降训练 𝛾𝛽,使用指数移动平均(EMA) 赋予最新迭代更多的重要性。

B.1.2)评估

与训练阶段不同,在评估阶段,我们可能没有完整的批次输入到模型中。****

为了解决这个问题,我们计算( 𝜇 _pop, σ _pop),如:

  • 𝜇 _pop:研究人群的估计均值;
  • σ _pop:研究人群的估计标准差。

使用在训练期间确定的所有( 𝜇 _batch, σ _batch)来计算那些值,并且在评估期间直接馈入等式(3)(而不是调用(1)和(2))。

备注:我们将在第 C.2.3 节“评估期间的标准化”中深入讨论该问题。

B.2)实际上

在实践中,我们将批量归一化视为一个标准层,如感知器、卷积层、激活函数或漏失层。

每个流行的框架都已经实现了批处理规范化层。例如:

****py torch:torch . nn . batch norm 1d, torch.nn.BatchNorm2d , torch.nn.BatchNorm3d

****tensor flow/Keras:TF . nn . batch _ normalization,TF . Keras . layers . batch normalization

所有 BN 实现都允许您独立设置每个参数。然而,输入向量大小是最重要的一个。它应该设置为:****

  • 当前隐层有多少神经元(针对 MLP);
  • 当前隐藏层中有多少个过滤器(对于卷积网络)。

看看你最喜欢的框架的在线文档,并阅读 BN 层页面:它们的实现有什么特别的吗?

B.3)结果概述

即使我们还不理解批处理规范化的所有底层机制(参见 C.3),但有一点大家都同意:它工作****

为了获得第一个洞察力,让我们看看官方文章的结果[1]:

图 1:BN 如何影响训练。ImageNet(2012)验证集上的准确度,相对于训练迭代次数。比较了五个网络:“初始”是标准初始网络[3],“BN-X”是具有 BN 层的初始网络(对于 3 种不同的学习速率:x1,x5,x30,初始最优网络,“BN-X-Sigmoid”是具有 BN 层的初始网络,其中所有的 ReLU 非线性被 Sigmoid 代替。|来源:[1]****

结果很明显:BN 层使训练更快,而允许更大范围的学习速率而不会影响训练的收敛性。****

备注:此时,你应该对 BN 层有足够的了解来使用它们。然而,如果您想从批处理规范化中获得最大收益,您将需要更深入地挖掘!

批量归一化和这张图有什么联系? |信用:达尼洛·阿尔维斯上 Unsplash

c)了解批量标准化(BN)

C.1) 实施

我已经用 Pytorch 重新实现了批处理规范化层,以再现原始的论文结果。代码可以在这个 github 库上找到。

我建议你看看网上的一些 BN 层的实现。看看在自己喜欢的框架里是怎么编码的,很有启发!

实践中的 BN 层

在深入理论之前,让我们先从批处理规范化有哪些确定性开始。

在本节中,我们将看到:

  • BN 如何影响培训绩效?为什么这种方法在如今的深度学习中如此重要?****
  • 我们必须注意哪些副作用?
  • ****我们应该如何使用 BN?

C.2.1)来自原始文章的结果

如前所述,BN 被广泛使用,因为它几乎总是让深度学习模型表现得更好****

官方文章[1]进行了 3 个实验来说明其方法的有效性。

首先,他们在 MNIST 数据集(手写数字)上训练了一个分类器。该模型由 3 个完全连接的层组成,每层 100 个神经元,全部由 sigmoid 功能激活。他们已经使用随机梯度下降(SGD)和相同的学习率(0.01)对该模型训练了两次(有和没有 BN 层)50 000 次迭代。请注意,BN 层正好放在激活函数之前。

您可以轻松地再现这些结果,而无需 GPU,这是一个更熟悉这个概念的好方法!

图 2:BN 如何影响简单多层感知器(MLP)的训练 |左:训练精度 w.r.t .迭代|右:训练损失 w.r.t .迭代|作者****

看起来不错!批处理规范化提高了我们的网络性能,包括损失和准确性。

第二个实验包括查看隐藏层中的激活值。以下是对应于最后一个隐藏层(就在非线性之前)的图:

图 3 : 批量归一化对最后一个隐藏层激活值的影响| 鸣谢:作者

如果没有批处理规范化,激活的值在第一次迭代中会有很大的波动。相反,当使用 BN 时,活化曲线更平滑。

图 4 : 批量标准化对隐藏层激活的影响 |有 BN 的模型比没有 BN 的模型有更平滑的激活曲线| Credit : author

此外,当添加 BN 层时,信号噪声更小。这似乎使模型的收敛更容易。

这个例子没有显示批处理规范化的所有好处。

官方文章进行了第三次实验。他们希望在更大的数据集 ImageNet (2012)上添加 BN 图层时比较模型性能。为此,他们训练了一个强大的神经网络(当时),名为 Inception [3]。最初,这个网络没有任何 BN 层。他们添加了一些,并通过修改其学习率来训练模型(x1,x5,x30 以前的最佳值)。他们还试图在另一个网络中用 sigmoid 替换每个 ReLU 激活功能。然后,他们将这些新网络的性能与原来的进行了比较。

以下是他们得到的结果:

图 5 : 批量归一化对训练的影响(ImageNet) |《盗梦空间》:原网[3];“BX-基线”:与 BN 的 Inception 相同,学习率(LR)相同;“BX-x5”:与 BN、LR x5 的《盗梦空间》相同;“BX-x30”:与 BN 的 Inception 相同,LR x30“BN-x5-Sigmoid”:与 Inception 相同,使用 BN、LR x5 和 Sigmoid 代替 ReLU | Source : [1]

从这些曲线中我们可以得出以下结论:

  • 增加 BN 层导致更快和更好的收敛(其中更好意味着更高的精度);****

在如此大的数据集上,这种改善比在小 MNIST 数据集上观察到的改善要显著得多。

  • 增加 BN 层允许我们使用更高的学习速率(LR)而不影响收敛****

作者已经成功训练了他们的 Inception-with-BN 网络,使用了比原始网络高 30 倍的学习速率。请注意,5 倍大的 LR 已经使普通网络发散了!****

这样,就更容易找到一个“可接受的”学习率:位于欠拟合和梯度爆炸之间的 LR 的间隔要大得多。

此外,较高的学习率有助于优化器避免局部极小值收敛。受到鼓励去探索,优化器将更容易收敛于更好的解决方案****

  • 基于 sigmoid 的模型 达到了与基于 ReLU 的模型的竞争结果

我们需要后退一步,看看更大的图景。我们可以清楚地看到,与 sigmoid 模型相比,基于 ReLU 的模型可以获得略好的性能,但这不是这里的重点。

为了说明为什么这个结果是有意义的,让我重新表述一下 Ian good fellow(GANs[6]的发明者,著名的“深度学习”手册的作者)对此的看法:

在 BN 之前,我们认为在隐藏层中使用 sigmoid 有效地训练深度模型几乎是不可能的。我们考虑了几种解决训练不稳定性的方法,比如寻找更好的初始化方法。这些解决方案很大程度上是启发式的,而且太脆弱,不令人满意。批量归一化使那些不稳定的网络可训练;这个例子说明了这一点。****

——伊恩·古德菲勒(改编自:来源)

现在我们明白了为什么 BN 对深度学习领域有如此重要的影响。

这些结果为提供了批处理标准化对网络性能的益处的概述。然而,有一些副作用,你应该记住,以获得最大的 BN。****

C.2.2)规则化,一个 BN 副作用

BN 依靠批量第一和第二统计矩(均值和方差)来归一化隐藏层激活。然后,输出值与当前批次统计数据紧密相关。根据当前批处理中使用的输入示例,这种转换会增加一些噪声。

添加一些噪声以避免过度拟合…听起来像是一个正则化过程,不是吗?;)****

在实践中,我们不应该依靠批量归一化来避免过拟合,因为正交性很重要。简而言之,我们应该始终确保一个模块解决一个问题。依靠几个模块来处理不同的问题使得开发过程比需要的要困难得多。****

尽管如此,了解正则化效应还是很有趣的,因为它可以解释网络中的一些意外行为(尤其是在健全性检查期间)。

备注:批量越大,正则化越小(因为它减少了噪声影响)。

如果我们想在如此出色的嵌入式系统上部署批量规范化模型,该怎么办? |信用:玛利亚·卡斯特利于 Unsplash

评估过程中的标准化

有两种情况可以在评估模式中调用模型:****

  • 在进行交叉验证测试时,在模型训练和开发过程中;****
  • 部署模型时。****

在第一种情况下,为了方便起见,我们可以使用当前的批处理统计数据来应用批处理规范化。在第二个例子中,使用同样的方法没有意义,因为我们不一定要预测整个批次。****

让我们看一个带有嵌入式摄像头的机器人的例子。我们可以有一个模型,使用当前的框架来预测任何即将到来的障碍的位置。因此,我们希望每次迭代都在单个帧(即一个 rgb 图像)上计算推断。如果训练批量为 N,我们应该为模型期望的(N - 1)个其他输入选择什么来进行前向传播?****

记住,对于每一个 BN 层,( 𝛽𝛾 )都是使用归一化信号训练的。所以我们需要确定 (𝜇,σ) 才能有有意义的结果。****

一种解决方案是选择任意值来完成批量。通过将第一批输入到模型中,我们将获得感兴趣的图像的某个结果。如果我们用其他随机值构建第二批,我们将对同一幅图像有不同的预测。一个输入两个不同的输出不是理想的模型行为****

这一招就是定义( 𝜇 _pop, σ _pop),分别是目标人群的估计均值和标准差。这些参数计算为训练期间确定的所有( 𝜇_ 批次,σ_ 批次)的平均值。****

我们就是这么做的!

备注:这个技巧可能会导致评估阶段的不稳定性:让我们在下一部分讨论它。

C.2.4) BN 层稳定性

尽管批处理规范化工作得很好,但它有时会导致稳定性问题。存在 BN 层在评估阶段使激活值爆炸的情况(使模型返回 loss = NaN)。

我们刚刚提到如何确定( 𝜇 _pop, σ pop),以便在评估期间使用它们:我们计算在训练期间计算的所有( **𝜇 批次,σ_ 批次)的平均值。****

让我们考虑一个只在包含运动鞋的图像上训练的模型。如果测试集中有类似德比的鞋子呢?

如果输入分布从训练到评估变化太大,模型可能对某些信号反应过度,导致活动发散。 |信用:格里夫(左)叶佳(右)在 Unsplash

我们假设隐藏层的激活值在训练和评估期间将具有显著不同的分布——可能太多了。在这种情况下,估计的(𝜇_pop,σ_pop)不能正确估计真实总体均值和标准差。应用( 𝜇 _pop, σ _pop)可能会将激活值推离(𝜇 = 0,σ = 1),导致高估激活值****

备注:训练集和测试集之间分布的移动称为“协变量移动”。我们将在(C.3 .)节中再次讨论这种效应。

BN 的一个众所周知的特性增加了这种效果:在训练期间,激活值使用它们自己的值进行归一化。在推断期间,使用训练期间已经计算的( 𝜇 _pop, σ _pop)对信号进行归一化。因此,用于标准化的系数不考虑实际激活值本身。****

一般来说,训练集必须与测试集“足够相似”:否则,就不可能在目标任务上正确地训练模型。所以在大多数情况下, 𝜇 _pop 和 σ _pop 应该很适合测试集。如果不是,我们可以得出结论,训练集不够大,或者它的质量对于目标任务来说不够好。

但是有时候,就这么发生了。这个问题并不总是有一个干净的解决方案。

我曾亲自面对过一次,在肺纤维化进展卡格尔比赛期间。训练数据集由元数据和与每个患者相关的肺部 3D 扫描组成。这些扫描的内容是复杂多样的,但是我们只有大约 100 名患者来分成训练集和验证集。结果,当模型从训练模式切换到评估模式时,我想用于特征提取的卷积网络返回 NaN。调试愉快。

当您无法轻松获得额外的数据来增强您的训练集时,您必须找到一种变通方法。在上面的例子中,我已经手动强制 BN 层也在验证集上进行计算( 𝜇 _batch, σ _batch)。(我同意,这是一种丑陋的修复方式,但我没有时间了。;) )

在你的网络中增加 BN 层——假设它不会有负面影响——并不总是最好的策略!

C.2.5)递归网络和层标准化

在实践中,人们普遍承认:

  • 对于卷积网络(CNN) : 批量归一化(BN) 比较好
  • 对于递归网络(RNN) : 图层归一化(LN) 比较好

BN 使用当前批次来规格化每个单个值,而 LN 使用所有当前层来进行规格化。换句话说,使用来自单个示例的其他特征来执行归一化,而不是在所有当前批量示例中使用相同的特征。这种解决方案对于循环网络似乎更有效。注意,很难为这些种类的神经元定义一致的策略,因为它们依赖于相同权重矩阵的多次乘法。我们是否应该独立地规范化每一步?或者我们应该计算所有步骤的平均值,然后递归地应用标准化?(直觉论证的来源 : 这里 )

我不会在这个问题上做任何进一步的详述,因为这不是本文的目的。

C.2.6)非线性之前还是之后?

从历史上看, BN 层位于**非线性函数之前,这与作者当时的目标和假设一致:**

他们在文章中指出:

“我们希望确保,对于任何参数值,网络总是产生具有期望分布的激活。”

——谢尔盖·约菲和克里斯蒂安·塞格迪(来源:[1])

一些实验表明,在非线性函数之后立即定位 BN 层会导致更好的结果。这里有一个的例子。****

Keras 的创始人、现任谷歌工程师的 Franç ois Chollet 表示:

“我还没有回去检查他们在原始论文中的建议,但我可以保证克里斯蒂安[塞格迪] 最近写的代码在 BN 之前应用 relu。不过,这偶尔还是一个争论的话题。

—弗朗索瓦·乔莱(来源)

尽管如此,许多常用的迁移学习架构在非线性之前应用 BN(ResNet,mobilenet-v2,…)。

请注意,文章[2]质疑了原文章[1]所捍卫的解释 BN 有效性的假设(见 C.3.3)),将 BN 层放在激活函数之前,但没有给出充分的理由。

据我所知,这个问题还在讨论****

延伸阅读:这里有一个有趣的 reddit 线程——即使有些论点没有说服力——激活后大多赞成 BN。**

我那些乱七八糟的代码到底为什么能工作?| 信用: Rohit 农民上 Unsplash

C.3)批量归一化为什么有效?

在大多数情况下,批处理规范化提高了深度学习模型的性能。太好了。但是我们想知道黑匣子里到底发生了什么。

这就是事情变得有点棘手的地方。

问题是:我们还不确切知道是什么让批处理规范化工作得这么好还是。DL 社区中经常讨论一些假设:我们将一步一步地探索它们。****

在开始讨论之前,我们将看到以下内容:

  • 原文[1]假设 BN 有效性是由于的减少他们称之为内部协变量移位* (ICS)。最近的一篇论文[2]驳斥了这一假设。(参见 C.3.1)*****
  • 另一个假设更加谨慎地取代了第一个假设:BN 减轻了训练过程中各层之间的相互依赖性。(参见 C.3.2)
  • 麻省理工学院最近的一篇论文[2]强调了 BN 对优化景观平滑度的影响,使得训练更加容易。(参见 C.3.3)****

我敢打赌,探索这些假设将有助于您建立一个关于批处理规范化的强大直觉。

我们走吧!

C.3.1)假设 n 1 — BN 减少了内部协方差偏移(ICS)

****批量正常化尽管对 DNN 的表现有着根本性的影响,但仍然会受到误解

关于 BN 的困惑大多是由于原始文章【1】支持的错误假设。****

Sergey Ioffe 和 Christian Szegedy 对 BN 介绍如下:

“在训练过程中,我们将深度网络内部节点分布的变化称为内部协变量移位。[……]我们提出了一种新的机制,我们称之为批量标准化,它向减少内部协变量偏移迈出了*的一步,并在这样做的过程中极大地加速了深度神经网络的训练。”*******

——谢尔盖·约菲和克里斯蒂安·塞格迪(来源:[1])

换句话说,BN 是有效的,因为它部分地解决了内部协变量转移的问题。

****这种说法受到了后来作品的严峻挑战【2】

批注:从现在开始, ICS 指内部协变移位。

为了理解是什么导致了这样的混乱,让我们从讨论什么是协变量移位 i 开始,以及它是如何受到归一化的影响的。

什么是协变量转移(分布稳定性观点)?

[1]的作者明确地定义了它:协变量转移——从分布稳定性的角度——描述了一个模型输入分布的转移。推而广之,内部协变量移位描述了发生在深度神经网络隐层*中的这种现象。*******

让我们通过一个例子来看看为什么它会成为一个问题。

让我们假设我们想要训练一个能够回答以下问题的分类器:这个图像包含一辆汽车吗?如果我们想从一个非常大的无标签数据集中提取所有的汽车图像,这样的模型将会节省我们大量的时间。****

我们会有一个 RGB 图像作为输入,一些卷积层,然后是完全连接的层。输出应该是一个单一的值,输入到一个逻辑函数中,使最终值介于 0 和 1 之间——描述输入图像包含一辆汽车的概率。

图 5 : 一个 简单的 CNN 分类器。| 鸣谢:作者-设计:娄高清

为了训练这样一个模型,我们需要大量带标签的图像。

现在,假设我们只有用于训练的“普通”汽车。如果我们让模型给一级方程式赛车分类,它会有什么反应?

如前所述,协变量转移会使网络激活发散(第 C.2.4 节)。即使没有,也会降低整体性能! |演员表:迪瓦·克里希纳(左)和弗哈特·德尼兹·福斯(右)在 Unsplash

在这个例子中,在培训和测试分布之间有一个转移。更广泛地说,不同的汽车方向、闪电或天气状况足以影响我们的车型性能。这里,我们的模型不能很好地概括。****

如果我们在特征空间中绘制提取的特征,我们将得到如下结果:

图表 6.a : 为什么我们需要归一化模型输入值?案例没有规范化。在训练过程中,输入值是分散的:在点密度较高的地方,近似函数会非常精确。相反,在点的密度较低的情况下,它将是不准确的,并且服从随机性。(例如,近似曲线可以是绘制的 3 条线之一。) | 鸣谢:作者-设计:楼高清

假设十字描述与不包含任何汽车的图像相关的特征,而圆环描述包含汽车图像。在这里,一个函数可以将两个系综分开。但是在图的右上角,函数可能不太准确:没有足够的点来确定一个好的函数。这可能会导致分类器在评估过程中出现许多错误。****

为了有效地训练我们的模型,我们需要许多汽车图像,在任何我们可以想象的可能的环境中。即使这仍然是我们今天训练 CNN 的方式,我们也要确保我们的模型能够使用尽可能少的例子进行很好的概括。

这些问题可以总结如下:

从模型的角度来看,训练图像在统计上与测试图像差别太大。
有一个
协变档
**

我们可以用更简单的模型来面对这个问题。众所周知,线性回归模型在输入值归一化时更容易优化(即使其分布接近( 𝜇 = 0, σ = 1)):这就是为什么我们通常归一化一个模型的输入值。****

图表 6.b : 为什么我们需要归一化模型输入值?规范化案例。在训练期间,标准化输入信号使特征空间中的点彼此更接近:现在更容易找到一个良好的概括函数。 | 鸣谢:作者—设计:楼高清

在 BN 论文发表之前,这种解决方案已经广为人知。对于 BN,[1]的作者希望将这种方法扩展到隐藏层,以帮助训练。

内部协变量转移恶化训练:原始论文假说

图 7:分布稳定性视角下的内部协变量移位(ICS)原理(ICS _ distrib)。 | 鸣谢:作者-设计:楼高清

在我们的汽车分类器中,我们可以将隐藏层视为单元,当它们识别出一些与汽车相关的“概念”特征时,就会被激活:它可能是一个车轮、一个轮胎或一扇门。我们可以假设前面描述的效果会发生在隐藏的单元中。有一定方向角的轮子会激活特定分布的神经元。理想情况下,我们希望让一些神经元对任何车轮方向的可比分布做出反应,这样模型就可以有效地推断出输入图像包含汽车的概率。**

如果输入信号中存在巨大的协变量偏移,优化器将很难很好地推广。相反,如果输入信号总是遵循标准的正态分布,那么优化器将更容易泛化。考虑到这一点,[1]的作者应用了在隐藏层标准化信号的策略。他们假设强制(𝜇 = 0,σ = 1)中间信号分布将有助于网络在特征的“概念”级别上的泛化**

然而,我们并不总是希望隐藏单元中的标准正态分布。这会降低模型的代表性:

图表 8 : 我们为什么不总是要一个标准的正态分布在隐单元中。此处,sigmoid 函数仅在其线性范围内有效。 | 鸣谢:作者-设计:娄高清

最初的文章以 sigmoid 函数为例,说明为什么标准化本身就是一个问题。如果输入信号值介于 0 和 1 之间,非线性函数仅在其线性范围内工作。听起来有问题。**

为了解决这个问题,他们添加了两个可训练参数 𝛽𝛾 ,允许优化器为特定任务定义最佳均值(使用 𝛽 和标准偏差(使用 𝛾 )。

⚠Warning:下面的假设现在已经过时了。许多关于 BN 的伟大内容仍然声称它是使方法在实践中起作用的原因。然而,最近的作品对它提出了严峻的挑战。

在[1]发布后的几年里,DL 社区对 BN 有效性的解释如下:

—假设 1———

BN ➜ 输入信号的标准化在隐藏单元内➜添加两个可训练参数到调整分布并最大限度地利用非线性➜更容易训练**

这里,归一化到(𝜇 = 0,σ = 1)是 BN 有效性的主要解释。这一假设已经受到挑战(见第 C.3.3 节),被另一个假设所取代:**

—假设 2————

隐藏单元内输入信号的 BN ➜归一化➜ 减少隐藏层之间的相互依赖性(从分布稳定性角度看)➜更容易训练

有一个微小但非常重要的区别。这里,规范化的目的是减少层之间的相互依赖性(从分布稳定性的角度来看),因此优化器可以通过只调整两个参数来选择最佳分布!让我们进一步探讨这个假设。**

批量归一化和这张图有什么联系? |信用:达尼洛·阿尔维斯在 Unsplash 上

C.3.2)假设 n 2 — BN 减轻了训练期间隐藏层之间的相互依赖性

关于这一节:我找不到任何关于这一节所讨论的假设的确凿证据。因此,我决定主要依靠 Ian Goodfellow 对那件事的解释(特别是在 这个精彩的视频 )。

考虑下面的例子:

图 9 : 一个简单的 DNN ,它由线性变换组成。|灵感来自 Ian Goodfellow

其中(a)、(b)、(c)、(d)和(e)是网络的顺序层。这里有一个非常简单的例子,所有的层都通过线性变换连接起来。让我们假设我们想要使用 SGD 来训练这样的模型。

为了更新层(a)的权重,我们需要根据网络的输出计算梯度:

我们首先考虑一个没有 BN 层的网络。从上面的等式,我们得出结论,如果所有梯度都很大,grad(a)就会很大。相反,如果所有梯度都很小,grad(a)几乎可以忽略不计。

通过观察隐藏单元的输入分布,很容易看出各层之间的依赖程度:( a)权重的修改将修改(b)权重的输入分布,这将最终修改(d)和(e)的输入信号。这种相互依赖性对于训练稳定性可能是有问题的:如果我们想要* 调整特定隐藏单元的输入分布,我们需要考虑整个层序列。***

然而,SGD 考虑层之间的一阶关系。所以他们没有考虑到上面提到的更高程度的关系!

图解 10 : 假设 n 2 原理。BN 层通过标准化每个隐藏单元内部的信号,使信号调节更加容易,并允许使用 𝛽𝛾 进行分布调节。BN 就像一个阀门,在某些点上使流量控制更容易,而不会恶化网络的潜在复杂性! | 鸣谢:作者-设计:楼高清

添加 BN 层显著降低了训练期间各层之间的相互依赖性(从分布稳定性的角度来看)。批量正常化就像一个阀门,阻止流量,并允许使用 𝛽 et 𝛾* 进行调节。然后,不再需要考虑所有参数来获得隐藏单元内部分布的线索。***

备注:优化器可以进行更大的权重修改,而不会影响其他隐藏层中调整后的参数。它使超参数调谐方式更容易!

这个例子抛开了声称 BN 有效性是由于中间信号分布的归一化到(𝜇 = 0,σ = 1)的假设。
在这里,BN 的目标是
使优化器的工作更容易
,允许它调整隐藏层分布,一次只需两个参数**

然而,请记住这主要是猜测。这些讨论应该被用作建立对 BN 的直觉的见解。我们仍然不知道为什么 BN 在实践中是有效的!**

2019 年,来自麻省理工学院的一组研究人员进行了一些关于 BN 的有趣实验[2]。他们的结果严重挑战了假设 n 1 (仍然被许多严肃的博客帖子和 MOOCS 分享!).

如果我们想避免关于 BN 对训练的影响的“局部极小假设”,我们应该看看这篇论文。)

好吧…你最好初始化好。 |鸣谢:翠西张上 Unsplash

C.3.3)假设 n3-BN 使优化前景更加平滑

关于这一部分:我已经综合了[2]的结果,这些结果可以帮助我们对 BN 建立更好的直觉。我不可能面面俱到,这篇文章很密集,如果你对这些概念感兴趣,我建议你通读一遍。

让我们直接进入[2]的第二个实验。他们的目标是检验 ICS 和 BN 对训练表现的益处之间的相关性(假设 1)。**

符号:我们现在用ICS _ distrib来指代这个协变量移位。

为此,研究人员训练了三个 VGG 网络(在 CIFAR-10 上) :

  • 第一个没有任何 BN 层;
  • 第二个确实有 BN 层;
  • 第三个类似于第二个,除了在激活之前他们已经在隐藏单元中明确添加了一些 ICS_distrib(通过添加随机偏差&方差)。**

他们测量了每个模型达到的精度,以及分布值随迭代的演变。以下是他们得到的结果:

图 6:ICS _ distrib |上的 BN,有 BN 的网络比标准的网络训练速度快;在受管制的网络上明确增加 ICS_distrib 不会损害 BN 的利益。|来源:[2]**

我们可以看到,第三个网络的 ICS 非常高。然而,嘈杂的网络仍然比标准网络训练得更快。其达到的性能可与使用标准 BN 网络获得的性能相媲美。这个结果表明 BN 有效性与 ICS_distrib 无关。哎呀!**

我们不应该太快抛弃 ICS 理论:如果 BN 有效性不是来自 ICS_distrib,它可能与 ICS 的另一个定义有关。毕竟,假设 n 1 背后的直觉是有道理的,不是吗?**

ICS_distrib 的主要问题是它的定义与隐藏单元的输入分布有关。所以和优化问题本身没有直接联系。

[2]的作者提出了 ICS 的另一个定义:

让我们考虑一个固定的输入 x。

我们从优化的角度将内部协变量移位定义为在反向传播误差 L(X)_it 之后在隐藏层 k 上计算的梯度与在权重的迭代=* it 更新之后根据损失 L(X)_it+1 在同一层 k 上计算的梯度之间的差。***

该定义旨在更多地关注梯度而不是隐藏层输入分布,假设它可以为我们提供更好的线索,说明 ICS 如何影响底层优化问题**

符号:ICS _ opti现在指的是从优化角度定义的 ICS。

在下一个实验中,作者评估 ICS_opti 对训练绩效的影响。为此,他们测量了具有和不具有 BN 层的 DNN 在训练期间 ICS_opti 的变化。为了量化 ICS_opti 定义中提到的梯度变化,他们计算:

  • L2 差:在权重更新之前和之后,梯度是否具有接近的范数?理想情况下:0
  • 余弦角度:在权重更新前后,渐变是否具有相近的方向?理想情况下:1

图 7 : BN 对 ICS_opti 的影响 | L2 diff 和余弦角暗示 BN 并没有阻止 ICS_opti(似乎稍微增加了一点,不知怎么的)。|来源[2]

结果有点令人惊讶:依赖于 BN 的网络似乎比标准网络具有更高的 ICS_opti 。记住带 BN(蓝色曲线)的网络比标准网络(红色曲线)训练得快!

ICS 似乎肯定与训练表现无关…至少对于 ICS 的定义是这样的。

不知何故,批量归一化对网络产生了另一个* 的影响,这使得收敛更容易。***

现在,让我们研究一下BN 如何影响* 优化格局。我们可能会在那里找到线索。***

这是这个故事中的最后一个实验:

图 11 : 渐变方向的优化景观探索。论文中进行的实验[2] |灵感来自安德鲁·-设计:娄高清

从单个梯度,我们用不同的优化步骤更新权重(其作用类似于学习率)。直观地说,我们从特征空间中的某个点(即网络配置ω)* 定义一个方向,然后在这个方向上越来越远地探索优化景观。***

在每一步,我们测量坡度损失。因此,我们可以将优化领域的不同点与起点进行比较。如果我们测量大的变化,那么景观非常不稳定并且梯度是不确定的:大的步骤可能会恶化优化。相反,如果测量的变化很小,则景观是稳定的并且梯度是可信的:我们可以应用更大的步长而不损害优化。换句话说,我们可以用一个更大的学习速率,并使收敛得更快(BN 的一个众所周知的性质)。**

让我们来看看结果:

图 8 : BN 对优化景观平滑的影响 |使用 BN 显著减少梯度变化。|来源:[2]

我们可以清楚地看到BN 层的优化前景更加平滑**

我们终于有了可以用来解释 BN 有效性的结果:BN 层在某种程度上使得优化前景更加平滑。这使得优化器的工作更容易:我们可以定义一个更大的学习率,而不会受到梯度消失(权重停留在突然平坦的表面上)或梯度爆炸(权重突然落入局部最小值)的影响。

我们可以知道公式化的第三个假设,由[2]提出:

—假设三 : — — — — — —

BN ➜对隐单元➜内部输入信号的归一化使得优化景观更平滑* ➜更快更稳定的训练***

这又引出了另一个问题:BN 是如何让优化版图变得更加平滑的?****

[2]的作者也从理论的角度探讨了这些问题。他们的工作很有启发性,有助于更好地掌握批处理规范化的平滑效果。特别是,他们表明 BN 使优化景观更加平滑,而保留了正常景观的所有最小值。换句话说, BN 重新参数化底层优化问题,使训练更快更容易**

在额外的研究中,【2】的作者观察到这种效应并不是 BN* 独有的。他们用其他归一化方法(例如 L1 或 L2 归一化)获得了相似的训练性能。这些观察表明 BN 的有效性主要是由于偶然发现,利用了我们还没有完全识别的潜在机制。***

现在是时候设定一个非常高的学习率了。 |信用:寻找丹|丹·格林维斯上 Unsplash

作为本节的总结,本文广为接受的观点提出了严峻挑战,即 BN 的有效性主要是由于 ICS 的减少(从训练稳定性分布的角度,以及从优化的角度)。但是,它强调了 BN 平滑效果对优化前景的影响。**

虽然本文陈述了一个关于 BN 对训练速度影响的假设,但它并没有回答为什么 BN 有助于推广

他们简要地争辩说,使最优化前景更加平滑可以帮助模型收敛于平坦的最小值,后者具有更好的概括属性。不过,没有更多细节了。**

他们的主要贡献是挑战了普遍承认的 BN 效应对 ICS 的影响——这已经很显著了!

C.4)总结:BN 为什么管用?目前我们知道些什么

  • 假设 1 : BN 层减轻内部协变量偏移* (ICS)***

错:【2】表明,在实践中,ics 和训练成绩之间没有相关性**

  • 假设 2 : BN 层通过允许其仅用两个参数调整隐藏单元的输入分布,使优化器的工作更加容易。**

也许:这种假设强调了参数之间的相互依赖性,使得优化任务更加困难。没有确凿的证据,尽管如此。**

  • 假设三 : BN 层重新参数化底层优化问题,使其更加平滑稳定。**

❓:也许吧:他们的结果是最近才有的。据我所知,到目前为止,他们还没有受到挑战。他们提供了经验证明和一些理论论证,但是一些基本问题仍然没有答案(比如“BN 如何帮助一般化?”).

讨论:在我看来,后两种假设是兼容的。直观地说,我们可以把假设 n 2 看作是从一个有许多参数的问题到许多有几个参数的问题的投影;一种降维,这将有助于推广。有什么想法吗?

许多问题仍然悬而未决,批处理规范化仍然是当今的一个研究课题。讨论这些假设仍然有助于更好地理解这种常用的方法,抛弃一些我们已经想了几年的错误说法。

然而,这些问题并不妨碍我们在实践中利用 BN 的优势!

结论

批量归一化 (BN) 是近年来在深度学习* (DL)领域最重要的进展之一。依靠两次连续的线性变换,这种方法使得深度神经网络(DNN) 训练更快更稳定*

关于什么使得 BN 在实践中有效,最广为接受的假设是在训练期间隐藏层之间的相互依赖减少。然而,优化景观平滑度的归一化变换影响似乎是 BN 有效性的重要机制。**

现在许多常用的 DNN 都依赖于 BN(例如:ResNet [4],EfficientNet [5],…)。

如果你对深度学习感兴趣,你肯定要熟悉这种方法!

开放问题

即使 BN 在多年的实践中看起来是有效的,许多关于其潜在机制的问题仍然没有答案。

以下是关于 BN 的未决问题的非详尽列表:

  • BN 如何帮助泛化**
  • BN 是使优化更容易的最佳归一化方法吗?
  • 𝛽 等人 𝛾 如何影响优化景观平滑度?
  • [2]进行的探索优化景观的实验集中在BN 对梯度的短期影响:他们测量了几个步长值的单次迭代的梯度&损失的变化。BN 如何长期影响坡度?权重的相互依赖性对优化前景有其他有趣的影响吗?****

承认

非常感谢 Lou haquet-dele pine 绘制的所有图表,以及她在校对方面的全面帮助!

参考

[1]约夫,s .,&塞格迪,C. (2015)。批量归一化:通过减少内部协变量移位加速深度网络训练, arXiv 预印本 arXiv:1502.03167

[2]桑图尔卡尔、齐普拉斯、易勒雅斯和马德瑞(2018 年)。批量规范化如何帮助优化?、神经信息处理系统的进展

[3] Szegedy,c .,Liu,w .,Jia,y .,Sermanet,p .,Reed,s .,Anguelov,d,…和 Rabinovich,A. (2015)。深入卷积,IEEE 计算机视觉和模式识别会议论文集

[4]何,王,张,徐,任,孙等(2016)。用于图像识别的深度残差学习。在IEEE 计算机视觉和模式识别会议论文集

[5]谭,m .,,乐,2019 . Efficientnet:反思卷积神经网络的模型缩放, arXiv 预印本 arXiv:1905.11946

[6] Goodfellow,I .、Pouget-Abadie,j .、Mirza,m .、Xu,b .、Warde-Farley,d .、Ozair,s .、A. Bengio,Y. (2014),生成对抗网络, 神经信息处理系统进展

更进一步

  • 伊恩·古德费勒的精彩演讲。他在课程开始时谈到了批量标准化:链接
  • 一名作者口头介绍论文[2]。观众提出尖锐的问题,开启关于国阵的精彩辩论:链接
  • "我们应该把 BN 放在激活之前还是之后?"在 stackoverflow 上:链接
  • "我们应该把 BN 放在激活之前还是之后?"在 reddit 上:链接

神经网络中的批量标准化(包括代码)

原文:https://towardsdatascience.com/batch-normalization-in-neural-networks-code-d7c9b88da9f5?source=collection_archive---------26-----------------------

通过 TensorFlow (Keras)实施

克里斯托夫·高尔在 Unsplash 上拍摄的照片

介绍

批量归一化(BN) 是很多机器学习从业者遇到的一种技术。

如果你还没有,这篇文章解释了 BN 背后的基本直觉,包括它的起源以及如何使用 TensorFlow 和 Keras 在神经网络中实现它。

对于那些熟悉 BN 技术并想专注于实现的人来说,你可以跳到下面的代码部分。

对于那些可能对其背后的数学更感兴趣的人,请随意阅读下面的文章。

[## 解释了神经网络中的批量标准化(算法分解)

理解深度神经网络中使用的一种常见转换技术

towardsdatascience.com](/batch-normalization-explained-algorithm-breakdown-23d2794511c)

定义

批次正常化是一种技术,它透过引入额外的层来减轻神经网路内不稳定梯度的影响,该层会对前一层的输入执行作业。这些操作对输入值进行标准化和规范化,然后通过缩放和移位操作转换输入值。

密码

第一步是导入将用于实现或支持神经网络实现的工具和库。使用的工具如下:

  • TensorFlow :一个开源平台,用于机器学习模型的实现、训练和部署。
  • Keras :一个开源库,用于实现运行在 CPU 和 GPU 上的神经网络架构。
import tensorflow as tf
from tensorflow import keras

我们将利用的数据集是普通的时尚-MNIST 数据集。

时尚-MNIST 数据集包含 70,000 幅服装图像。更具体地说,它包括 60,000 个训练样本和 10,000 个测试样本,这些样本都是尺寸为 28×28 的灰度图像,分为十类。

数据集的准备包括通过将每个像素值除以 255.0 来归一化训练图像和测试图像。这将像素值置于范围 0 和 1 之间。

数据集的验证部分也在此阶段创建。这组数据集在训练期间被用来评估网络在各种迭代中的性能。

(train_images, train_labels),  (test_images, test_labels) = keras.datasets.fashion_mnist.load_data()
train_images = train_images / 255.0
test_images = test_images / 255.0
validation_images = train_images[:5000]
validation_labels = train_labels[:5000]

Keras 提供了实现分类模型所需的工具。Keras 提出了一种顺序 API,用于以连续的方式堆叠神经网络的层。

下面是一些层的信息,这些层将被实现以构成我们的神经网络。

  • 展平:取一个输入形状,将输入图像数据展平成一维数组。
  • 密集:密集层中嵌入了任意数量的单元/神经元。每个神经元都是一个感知器。
  • 感知器是人工神经网络的基本组成部分,由弗兰克·罗森布拉特于 1958 年发明。感知器利用基于阈值逻辑单元的操作。
  • 批量规范化:批量规范化层通过对传入的输入数据执行一系列操作来工作。这组操作包括进入 BN 层的输入值的标准化、规范化、重缩放和偏移。
  • 激活层:对神经网络内的输入执行指定的操作。这一层在网络中引入了非线性。本文中实现的模型将利用激活函数:整流线性单元(ReLU)softmax
  • ReLU 对来自神经元的值施加的变换由公式 y=max(0,x)表示。ReLU 激活函数将来自神经元的任何负值钳制为 0,而正值保持不变。该数学变换的结果被用作当前层的激活,并作为下一层的输入。
# Placing batch normalization layer before the activation layers
model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28,28]),
    keras.layers.Dense(300, use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.Dense(200, use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.Dense(100, use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.Dense(10, activation=keras.activations.softmax)
])

让我们来看看 BN 层的内部组件

仅仅访问索引 2 处的层将向第一 BN 层内的变量及其内容提供信息,

model.layers[2].variables

我不会在这里进入太多的细节,但请注意变量名'伽马'和'贝塔',这些变量中的值负责层内激活的重新缩放和偏移。

for variable in model.layers[2].variables:
    print(variable.name)>> batch_normalization/gamma:0
>> batch_normalization/beta:0
>> batch_normalization/moving_mean:0
>> batch_normalization/moving_variance:0

这篇文章详细介绍了 BN 层内的操作。

在密集层中,偏置分量被设置为假。偏差的省略是由于在激活的标准化过程中由于均值相减而发生的常量值的抵消。

下面是特斯拉现任人工智能总监安德烈·卡帕西(Andrej Karpathy)的一篇 twitter 帖子的片段。他的推文是基于经常犯的神经网络错误的主题,而不是在使用 BN 时将 bias 设置为 false。

在下一段代码中,我们设置并指定了用于训练已实现的神经网络的优化算法,以及损失函数和超参数,如学习速率和时期数。

sgd = keras.optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss="sparse_categorical_crossentropy", optimizer=sgd, metrics=["accuracy"])

现在,我们使用模型的顺序 API 的' fit 方法来训练网络。我们将跳过关于如何训练神经网络模型的一些细节。有关神经网络的训练和实现的详细解释的进一步信息,请参考下面的链接。

[## 使用 TensorFlow 2.0 进行(深入)机器学习图像分类

理解实现用于图像分类的神经网络的过程。

towardsdatascience.com](/in-depth-machine-learning-image-classification-with-tensorflow-2-0-a76526b32af8)

model.fit(train_images, train_labels, epochs=60, validation_data=(validation_images, validation_labels))

使用先前搁置的测试数据进行模型性能的评估。

通过评估结果,您可以在观察测试数据集评估的准确性后,决定微调网络超参数或继续生产。

model.evaluate(test_images, test_labels)

在训练阶段,您可能会注意到,与没有批量归一化图层的训练网络相比,每个历元的训练时间更长。这是因为批量标准化增加了神经网络的复杂性,以及模型在训练期间学习所需的额外参数。

尽管每个历元时间的增加与批量标准化减少了模型收敛到最优解所需的时间这一事实相平衡。

本文中实现的模型太浅,我们无法注意到在神经网络架构中使用批处理规范化的全部好处。通常情况下,批量归一化出现在更深层次的卷积神经网络中,如异常、 ResNet50 和 Inception V3 。

额外的

  • 上面实现的神经网络在激活层之前具有批量标准化层。但是在激活层之后添加 BN 层是完全可能的。
# Placing batch normalization layer after the activation layers
model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28,28]),
    keras.layers.Dense(300, use_bias=False),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(200, use_bias=False),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(100, use_bias=False),
    keras.layers.Activation(keras.activations.relu),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(10, activation=keras.activations.softmax)
])
  • 研究人员已经对批量标准化技术做了一些广泛的工作。例如批量重正化和自归一化神经网络

结论

BN 是神经网络中常用的技术,因此理解该技术如何工作以及如何实现将是有用的知识,尤其是在分析大多数神经网络架构时。

下面是 GitHub 到一个笔记本的链接,其中包含了本文中的代码片段。

[## Richmond alake/tensor flow _ 2 _ 教程

github.com](https://github.com/RichmondAlake/tensorflow_2_tutorials/blob/master/04_batch_normalisation.ipynb) [## 你应该读机器学习硕士吗?

包含来自理学硕士毕业生的想法和意见

towardsdatascience.com](/should-you-take-a-masters-msc-in-machine-learning-c01336120466) [## AI 如何检测物体?(技术)

了解如何使用机器和深度学习技术应用和实现对象检测

towardsdatascience.com](/how-does-ai-detect-objects-technical-d8d63fc12881)

实践中的批量规范化:以 Keras 和 TensorFlow 2.0 为例

原文:https://towardsdatascience.com/batch-normalization-in-practice-an-example-with-keras-and-tensorflow-2-0-b1ec28bde96f?source=collection_archive---------2-----------------------

添加和自定义批处理规范化的分步教程

照片由马库斯·温克勒在 Unsplash 上拍摄

在本文中,我们将重点关注在我们的机器学习模型中添加和定制批处理规范化,并查看一个示例,说明我们如何在 Keras 和 TensorFlow 2.0 的实践中做到这一点。

批处理规范化的简明介绍

在深度学习的兴起中,最重要的一个思想一直是一种叫做 批量规格化 (也叫 批量规格化 )的算法。

批量标准化 是一种用于训练深度神经网络的技术,它将每个小批量的输入标准化到一个层。这具有稳定学习过程和显著减少训练深度网络所需的训练时期的效果。

杰森·布朗利

在训练期间,可以通过计算每个小批量层的每个输入变量的平均值和标准偏差,并使用这些统计数据来执行标准化,从而实现批量标准化。

形式上,批处理规范化算法[1]被定义为:

来自原论文:批量归一化:通过减少内部协变量移位加速深度网络训练

在该算法中,*B*被用来表示整个训练集的一个规模为m的小批量。*B*的均值和方差可计算如下:

对于具有 d 维度输入*x* = (*x_1*, …, *x_d*)的层,其输入的每个维度可以单独归一化(重新居中和重新缩放)。因此,一个 d 维输入的归一化可以计算为:

ε加在分母中以保持数值稳定,它是一个任意小的常数。

最后,为了恢复网络的表示能力,变换步骤被定义为:

其中参数β和γ随后在优化过程中被学习。

批量标准化的好处有[2]:

  • 可以更快地训练深度神经网络:虽然由于正向传递期间的额外归一化计算和反向传播期间要训练的额外超参数,每次训练迭代将更慢,但它应该收敛得更快;因此,训练总体上应该更快。
  • 更高的学习率:梯度下降一般需要较小的学习率,网络才能收敛。随着网络变得更深,梯度在反向传播过程中变得更小,因此需要更多的迭代。使用批量标准化允许更高的学习率,从而提高训练速度。
  • 更容易初始化权重:权重初始化可能很困难,尤其是在创建更深层次的网络时。批次标准化降低了对初始起始重量的敏感度。

如果您正在寻找完整的解释,您可能会发现以下资源很有用:

  • 原纸
  • deep learning . ai 中的批量规范化

在下面的文章中,我们将在我们的机器学习模型中添加和定制批处理规范化。

环境设置、源代码和数据集准备

我们将使用与在模型正则化教程中相同的数据集。如果你已经熟悉这一章,你可以跳过它。

为了运行本教程,您需要安装

TensorFlow 2,numpy,pandas,sklean,matplotlib

它们都可以直接安装在 vis PyPI 上,我强烈建议创建一个新的虚拟环境。关于创建 Python 虚拟环境的教程

  • 使用“virtualenv”创建虚拟环境,并将其添加到 Jupyter 笔记本中
  • 使用“conda”创建虚拟环境,并将其添加到 Jupyter 笔记本中

源代码

这是一个循序渐进的教程,所有的说明都在这篇文章中。源代码请查看我的 Github 机器学习报告。

数据集准备

本教程使用安德森鸢尾花(iris) 数据集进行演示。数据集包含五个属性下的一组 150 条记录:萼片长度萼片宽度花瓣长度花瓣宽度、类别(从 sklearn 数据集称为目标)。

首先,让我们导入库并从 scikit-learn 库中获取虹膜数据集。你也可以从 UCI 虹膜数据集下载。

import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split**iris = load_iris()**

为了研究数据,让我们将数据加载到一个数据帧中

# Load data into a DataFrame
**df = pd.DataFrame(iris.data, columns=iris.feature_names)** # Convert datatype to float
**df = df.astype(float)** # append "target" and name it "label"
**df['label'] = iris.target** # Use string label instead
**df['label'] = df.label.replace(dict(enumerate(iris.target_names)))**

并且df应该如下所示:

我们注意到 标签 列是一个分类特征,需要将其转换为一键编码。否则,我们的机器学习算法将无法直接将其作为输入。

# label -> one-hot encoding
**label = pd.get_dummies(df['label'], prefix='label')**
**df = pd.concat([df, label], axis=1)**
# drop old label
df.drop(['label'], axis=1, inplace=True)

现在,df应该是这样的:

接下来,让我们创建Xy。Keras 和 TensorFlow 2.0 只接受 Numpy 数组作为输入,所以我们必须将 DataFrame 转换回 Numpy 数组。

# Creating X and y**X = df[['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']]**
# Convert DataFrame into np array
**X = np.asarray(X)y = df[['label_setosa', 'label_versicolor', 'label_virginica']]** # Convert DataFrame into np array
**y = np.asarray(y)**

最后,让我们使用来自 sklearn 库的**train_test_split()** 将数据集拆分成训练集(80%)和测试集(20%)。

X_train, X_test, y_train, y_test = **train_test_split**(
  **X,
  y,
  test_size=0.20**
)

太好了!我们的数据已经准备好建立一个机器学习模型。

用批量归一化建立神经网络模型

用 Keras 和 TensorFlow 2.0 创建机器学习模型有 3 种方法。由于我们正在构建一个简单的全连接神经网络,为了简单起见,让我们使用最简单的方法:带有Sequential()的顺序模型。

首先,让我们导入SequentialBatchNormalization

from tensorflow.keras.models import **Sequential**
from tensorflow.keras.layers import Dense, **BatchNormalization**

让我们继续创建一个顺序模型

model = Sequential([
    Dense(64, **input_shape=(4,)**, activation="relu"),
    Dense(128, activation='relu'),
    Dense(128, activation='relu'),
    Dense(64, activation='relu'),
    Dense(64, activation='relu'),
    Dense(3, **activation='softmax'**)
]);

我们的型号有以下规格:

  • 第一层(也称为输入层)有input_shape来设置输入尺寸(4,)
  • 输入层有 64 个单元,后面是 2 个密集层,每个层有 128 个单元。然后还有 2 个密度层,每个层有 64 个单元。所有这些层都使用relu激活功能。
  • 输出密集层有 3 个单元和softmax激活功能。

我们可以将批量规范化添加到我们的模型中,添加方式与添加Dense层相同。

model = Sequential([
    Dense(64, input_shape=(4,), activation="relu"),
    **BatchNormalization(),**
    Dense(128, activation='relu'),
    **BatchNormalization(),**
    Dense(128, activation='relu'),
    **BatchNormalization(),**
    Dense(64, activation='relu'),
    **BatchNormalization(),**
    Dense(64, activation='relu'),
    **BatchNormalization(),**
    Dense(3, activation='softmax')
]);

BatchNormalization()在每一批标准化前一层的激活,默认情况下,它使用以下值[3]:

  • 动量默认为0.99
  • 超参数ε默认为0.001
  • 超参数β默认为一个all-zeros向量
  • 超参数γ默认为一个all-ones矢量

这些都可以通过给BatchNormalization()添加可选参数来改变。例如

from tensorflow.keras.initializers import **RandomNormal, Constant**# Model with default batch normalization
model = Sequential([
    Dense(64, input_shape=(4,), activation="relu"),
    BatchNormalization(),
    Dense(128, activation='relu'),
    BatchNormalization(),
    Dense(128, activation='relu'),
    BatchNormalization(),
    Dense(64, activation='relu'),
    BatchNormalization(),
    Dense(64, activation='relu'),
    **BatchNormalization(
        momentum=0.95, 
        epsilon=0.005,
        beta_initializer=RandomNormal(mean=0.0, stddev=0.05), 
        gamma_initializer=Constant(value=0.9)
    ),**
    Dense(3, activation='softmax')
]);

RandomNormal()生成正态分布的张量,而Constant()生成常数值的张量。通过运行model.summary(),您应该会得到一个如下所示的模型摘要:

培养

现在让我们用批处理规范化来编译和拟合我们的模型。我们首先用以下规范编译我们的模型

  • 使用 Adam ( adam)优化算法作为优化器
  • 使用分类交叉熵损失函数(categorical_crossentropy)来解决我们的 多类分类 问题
  • 为简单起见,使用accuracy作为我们在训练和测试期间评估模型的评估指标。
model.compile(
    **optimizer='adam', 
    loss='categorical_crossentropy', 
    metrics=['accuracy']**
)

之后,我们可以调用model.fit()来使我们的模型符合训练数据。

history = model.fit(
    X_train, 
    y_train, 
    epochs=200, 
    validation_split=0.25, 
    batch_size=40, 
    verbose=2
)

如果一切顺利,我们应该得到如下输出

Train on 90 samples, validate on 30 samples
Epoch 1/200
90/90 - 3s - loss: 0.8735 - accuracy: 0.5778 - val_loss: 1.0685 - val_accuracy: 0.6667
Epoch 2/200
90/90 - 0s - loss: 0.1983 - accuracy: 0.9333 - val_loss: 1.0640 - val_accuracy: 0.4667
......
......
Epoch 200/200
90/90 - 0s - loss: 0.0532 - accuracy: 0.9778 - val_loss: 0.1453 - val_accuracy: 0.9333

模型评估

最后,是时候看看这个模型到底有没有用了

  • 绘制训练和验证损失和准确性,以观察我们的模型的准确性如何随着时间的推移而提高。
  • 使用我们之前搁置的测试数据集X_test再次测试我们的模型

让我们创建一个函数plot_metric()来绘制指标。

%matplotlib inline
%config InlineBackend.figure_format = 'svg'
def plot_metric(history, metric):
    train_metrics = history.history[metric]
    val_metrics = history.history['val_'+metric]
    epochs = range(1, len(train_metrics) + 1)
    plt.plot(epochs, train_metrics)
    plt.plot(epochs, val_metrics)
    plt.title('Training and validation '+ metric)
    plt.xlabel("Epochs")
    plt.ylabel(metric)
    plt.legend(["train_"+metric, 'val_'+metric])
    plt.show()

通过运行plot_metric(history, 'accuracy')绘制精度进度。

通过运行plot_metric(history, 'loss')绘制损失进度。

在测试集上评估模型

# Evaluate the model on the test set
model.**evaluate**(**X_test**, **y_test**, verbose=2)

我们应该得到如下所示的输出

30/1 - 0s - loss: 0.1192 - accuracy: 0.9667
[0.11924469470977783, 0.96666664]

好了

感谢阅读。

请在我的 Github 上查看笔记本的源代码。

如果你对机器学习的实用方面感兴趣,请继续关注。

参考资料:

  • [1] 批量归一化:通过减少内部协变量偏移加速深度网络训练
  • [2]深度学习的以人为中心的视觉分析,第 7–8 页
  • [3] 来自 Keras API 文档的批量标准化

批处理规范化:一个非常通用的深度学习工具

原文:https://towardsdatascience.com/batch-normalization-the-greatest-breakthrough-in-deep-learning-77e64909d81d?source=collection_archive---------19-----------------------

来源:创新企业。图片免费分享。

它是如何工作的——又是如何如此有效的?

尽管批处理规范化的概念本身相当简单,但它解决了深度神经网络中许多常见而持久的问题,因此被许多人视为深度学习中最伟大的突破之一。

训练一个卷积神经网络来处理图像在几个问题上非常困难——有大量的参数需要大量的计算,学习目标有许多糟糕的局部最小值,需要大量的训练数据,但最重要的是,特别容易出现消失和爆炸梯度。

消失梯度问题是在训练深度神经网络时经常遇到的不稳定行为的例子,并且当神经网络如此长且复杂以至于神经网络不能将有用的梯度信息反向传播到网络开始处的权重时发生。这通常是因为当信号在整个网络中反向传播时,激活功能会逐渐减弱信号。因此,模型输入附近的图层保持相对不变,提供的值很少,从而限制了模型发挥其真正的预测能力。因此,到目前为止,优化器只能使用它可以访问的权重来优化模型,因此,即使前端结构没有被利用,优化器也会停滞不前,没有任何改进。

由作者创建

另一方面,当大的误差梯度连续累积并导致训练期间神经网络权重的大的、不稳定的、钟摆状的更新时,就会出现爆炸性梯度问题。消失梯度和爆发梯度都提供了经常困扰神经网络的两个巨大问题。为了解决这些梯度问题,用于解决它们的主要方法包括小心地设置学习速率(当模型接近最优值时缓慢地衰减学习速率),设计具有不同激活函数的更好的 CNN 架构,更小心地初始化权重,以及调整数据分布。最有效的解决方案是批量标准化。

批量归一化图层接收流经网络的数据,并输出经过重缩放和归一化的过滤器。这具有改变流经整个网络的输入分布的效果。

作者创建的图像。

最初的批处理规范化论文声称批处理规范化在提高深度神经网络性能方面如此有效是因为一种称为“内部协变量移位”的现象。根据这一理论,当模型参数更新时,深层神经网络中隐含层的输入分布不规则地变化。批量标准化本能地恢复输入的分布,这些输入在通过隐藏层时可能已经移动和伸展,从而防止训练受阻。

在 CIFAR-10 上训练的标准 VGG 网络的(a)训练(优化)和(b)测试(泛化)性能的比较,有和没有批量归一化。(c)使用和不使用批量标准化比较第三层和第十一层的权重。请注意更加集中和正常的分布,与标准的倾斜和不均匀的分布相反。来源— arXiv:1805.11604v5 .图片免费分享。

不幸的是,对内部协变量变化的本能解释被证明是不正确的。事实上,输入通过隐藏层时的分布变化似乎不会对模型的训练产生太大影响。揭示这一真理的开创性论文《批处理规范化如何帮助优化》的作者来自麻省理工学院,进行了一项实验,以衡量内部协变量转移理论的有效性。

实验中,在 CIFAR-10 数据集上训练了一个标准和两个标准+批量归一化标准 VGG16 网络架构。其中一个标准+批次归一化网络在批次归一化层之后注入了完全随机的噪声,导致了大量的内部协变量偏移,而这些偏移无法通过批次归一化层进行“校正”。结果令人着迷——尽管很明显,“嘈杂”批量归一化网络后的权重分布不如常规批量归一化模型中的均匀,但它的表现一样好,两个批量归一化神经网络都优于标准网络。

来源— arXiv:1805.11604v5 .图片免费分享。

相反,作者发现批处理规范化平滑优化景观。当梯度下降优化器试图找到全局最优值时,它需要对当前最优值是局部最优值还是全局最优值做出权衡决定,并牺牲误差的暂时增加以获得更大的下降。通常,在具有许多陡峭山峰、平坦平原和锯齿状山谷的崎岖地形中的优化者发现这项任务很困难,并且变得过度依赖于通常不小心设置的学习速率,从而导致较差的准确性。

来源— arXiv:1805.11604v5 .图片免费分享。

批量归一化大大减少了损失景观、梯度生产率和β平滑度的变化,使得导航地形以找到全局误差最小值的任务变得更加容易。简单地添加批量标准化图层具有几个巨大的优势:

  • 在设置初始学习率时更加自由。大的初始学习率不会导致在优化过程中错过最小值,并且可以导致更快的收敛。
  • 加速学习速度衰减。由于批量标准化使模型对超参数更加稳健,因此除了为最佳训练时间设置更高的初始学习速率之外,还可以加速学习速率衰减的速率。
  • 去掉漏音。当使用批量标准化时,可以不使用漏失层,因为漏失会造成损坏和/或减慢训练过程。批量标准化引入了防止过度拟合的另一种形式。
  • 降低 L2 权重正规化。成功训练一个神经网络的很大一部分是调整权重。虽然使用 L2 正则化(以误差的平方来惩罚对象以强调对较大对象的惩罚)是有效且常用的,但它也带来了自己的一系列问题,包括权重复杂性的增加和过度拟合的趋势。批处理规范化具有正则化属性,这可能是一种更“自然”的正则化形式。
  • 解决消失渐变问题。虽然内部协变量移位可能不会提高精度,但它在某种程度上涉及到消失梯度问题。当输入的分布发生变化时,由于激活函数(例如,sigmoid 将最小值设置为 2.5,或 ReLU 将任何 x < 0 设置为 0),它将倾向于固有的较小梯度更新。批量标准化有助于确保在反向传播过程中,通过将分布从网络的末端转移到起点,信号被听到且不被减弱。
  • 解决爆炸梯度问题。由于批量标准化平滑了优化前景,它消除了累积的极端梯度,从而消除了梯度累积导致的主要重量波动。这极大地稳定了学习。

感谢阅读!

使用 Pillow 在 Python 中批量调整图像大小

原文:https://towardsdatascience.com/batch-resizing-images-in-python-with-pillow-94f558b1759b?source=collection_archive---------21-----------------------

一个重要的 PYTHON 技巧

一步一步的使用 Python 调整图片大小的指南

带枕头的蟒蛇插图作者金彩云

有时你需要为你的项目编辑大量的图片。例如,在 web 开发中,大容量调整图像大小是为了使所有图像变得更小、更亮,以优化通过 web 的传输速度。在数据科学中,您可能需要提高所有图像的 DPI,以便在科学文章中发布。在图像处理软件中自己管理它们可能会很无聊。所以,你可以试着用枕头自动为你做这项工作!

这篇短文将通过一个示例脚本,一步步向您展示如何使用 Python 中的 Pillow ,重点关注批量调整图像大小。即使这个 Pillow 库已经推出很久了,它仍然像在 2020 年一样强大和非常有用。

使用 Python 和 Pillow 调整文件夹中所有图像大小的示例。(作者 gif)

例如,上面的 gif 图像显示,Python with Pillow 只需大约 8-10 行代码就可以调整/重缩放一个文件夹中的所有图像文件。Pillow 可以完成多种操作,如调整大小、重新缩放、旋转、变换、在文件格式之间转换、增强对比度等等。

我们开始吧!

装置

您可以简单地使用**pip** 安装库,如下所示:

**$ pip install pillow**

Python 2.x 不再支持最新的 Pillow。您可以在下面检查 Pillow 版本以匹配您的 Python 版本。

枕头版支持(来源:https://pillow.readthedocs.io/en/stable/installation.html)

基本用法

枕头的概念很简单,有三个步骤

  1. 加载一幅图像(或大量图像)
  2. 进行一些图像编辑/处理操作
  3. 以您喜欢的格式保存编辑过的图像。
**from PIL import Image** # ---- 1 ---- **im = Image.open("*input_path"*)** # ---- 2 ---- **# ... Do some operation** # ---- 3 ---- **im = Image.save("*output_path"*)**

支持格式

枕头支持多种光栅文件格式。图书馆可以识别和阅读 30 多种不同的文件格式。书写支持不太广泛,但支持大多数常见的交换和表示格式。[1]

现在,让我们来看一些真实的例子:

真实实践

您可以使用pathlibos遍历文件夹中的每个图像文件,然后使用 Pillow 加载图像。之后,您可以使用thumbnail命令将图像尺寸缩小到指定的最大宽度或最大高度值,并保留图像的外观。

# Load image 
**im = Image.open(input_img_path)**#Smaller image/ preserve the aspect of the image **resized_im = im.thumbnail(<maxwidth>, <maxheight>)**# Or Resize image to exact specified size **resized_im = im**.**resize(<width>, <height>)** # Then, save the resized image
**resized_im**.**save(<output_img_path>, <file type>, dpi, ...)**

例如,下面的脚本显示了如何调整名为“input”的文件夹中的所有图像的大小,使其最大宽度和高度为 512 像素,并保留图像的外观,并将它们以 300 dpi 的 JPEG 格式保存在“output”文件夹中。这个例子使用pathlib遍历一个文件夹中的所有文件。

resizeImages.py

使用这个脚本,您可以在第 7 行和第 8 行之间添加任何图像操作。如旋转,变换,文件格式之间的转换,增强对比度。您可以从 Pillow 文档中看到可用操作的列表。

此外,还有几个 Python 图像处理工具可以使用,比如 OpenCV 和 scikit Image。

临终遗言

所以,大概就是这样。我希望你喜欢这篇文章,并发现它对你的日常工作或项目有用。如果您有任何问题或意见,请随时给我留言。

关于我&查看我所有的博客内容:链接

安全健康健康!💪

感谢您的阅读。📚

参考

[1]Alex Clarkhttps://Pillow . readthe docs . io/en/stable/handbook/image-file-formats . html(2020),Pillow (PIL 福克)

公共云之王争夺战:AWS vs. Azure

原文:https://towardsdatascience.com/battle-for-the-king-of-public-cloud-aws-vs-azure-9c5505dabb1e?source=collection_archive---------40-----------------------

我应该信任谁来满足我的企业未来十年的软件开发需求?

照片由来自 Pexels 的迈克拍摄

不管你喜不喜欢,公共云正在接管。有什么不喜欢的呢?

云计算使得管理我们所有的计算机系统资源变得非常容易。它提供了一个抽象层,这在 2006 年之前似乎是不可能的。

我们不再需要以物理方式管理我们的底层基础架构。这些发展意味着我们不再需要:

  • 购买不动产来放置我们的服务器。
  • 雇佣工人来处理维护(供暖/制冷、电线等。)
  • 当我们看到使用量激增时,添加新的物理服务器。
  • 受到任何类型的基础设施可用性的限制。

这使我们能够:

  • 尽可能降低我们的成本。
  • 专注于我们的业务,提高功能开发速度
  • 有更好的安全性
  • 通过改进的灾难恢复实现高可用性

我们业务的发展速度是前所未有的。我们从未有过如此快速地从计划到生产的能力。

但是,就像科技世界中的一切一样,一旦有了新的前沿,每个人都必须做出自己的版本。

我们将关注云计算领域的两个领导者:Amazon Web Services 和 Microsoft Azure。

目标

回答问题:我应该选择谁来满足我的企业未来十年的软件开发需求?

AWS 和微软 Azure 已经成为这个领域的两个领导者。所以今天,我们要深入研究这两个,并确定哪个更好。

目录

  • AWS 概述
  • 蔚蓝概述
  • 利弊
  • 培训和认证
  • 结论

AWS 概述

照片由克里斯蒂安·威迪格在 Unsplash 上拍摄

云计算可以追溯到 60 年代,那时首次实现了计算机不同方面的“虚拟化”。所以说亚马逊开创了云计算是不正确的。

但是就基础设施即服务(IaaS) 以及我们今天所知的方式而言,亚马逊在将它推向大众方面发挥了巨大作用。

什么是 IaaS?将原始计算能力作为服务提供的能力,以及通过互联网访问和配置新服务器和存储的能力。

如果不是亚马逊,我们会有云计算吗?很难想象我们会走到这一步。

早在 2006 年,亚马逊就推出了亚马逊网络服务。他们的第一批服务是 S3(简单存储服务)、EC2(弹性云计算)和 SQS(简单队列服务)。

这些服务允许您通过在线 web 服务界面(S3)将数据存储在在线存储中,在 web 应用程序之间进行通信(SQS),以及按需部署新服务器(EC2)。

此后,截至 2020 年,AWS 的服务超过 212 项。这些服务几乎涵盖了您发展 IT 业务所需的一切。服务横跨数据库、网络、移动、开发者工具、物联网(IoT)、机器学习、AR & VR、区块链、量子技术。这个清单还在继续。

随着这些服务的发展,云计算游戏将被永远改变。

Azure 概述

由 Ashkan Forouzani 在 Unsplash 上拍摄

微软 Azure 起步较晚,最初在 2008 年以“Project Red Dog”开始,并在 2010 年正式成为“Windows Azure ”,当时它已投入商业使用。这是它开始获得动力的时候。

Azure 寻求提供许多与 AWS 相同的服务,包括虚拟机、对象存储和内容交付网络。然而,这些服务是专门为微软产品设计的。

也就是说,如果您的企业是使用 Windows 堆栈(Microsoft SQL Services、Microsoft。网络服务、实时服务、Sharepoint 等。),Azure 会对你有帮助。

意识到他们需要超越 Windows 堆栈,Azure 开始提供对更多编程语言、框架和操作系统的支持。

因为它不再只是 Windows 的工具,2014 年,他们更名为“微软 Azure”

与 AWS 类似,Azure 提供基础设施即服务(IaaS)、软件即服务(SaaS)和平台即服务(PaaS)。

利弊

赞成的意见

骗局

培训和认证

怎么才能入门?

获得其中任何一种云技术的认证对你和你的职业生涯来说都是非常有价值的,并且对于任何想要了解更多关于云的知识的人来说都是一个很好的起点。

微软目前提供三种认证:

  • Azure 管理员助理
  • Azure 解决方案架构师专家
  • Azure 安全工程师助理

AWS 提供了更多(以及许多专业):

  • 云从业者(基础)
  • 开发人员(助理)
  • 系统运行管理员(助理)
  • DevOps 工程师(专业)
  • 解决方案架构师(助理和专业人员)

试图在解决方案架构师和开发人员认证之间做出选择?点击这里看我对两者的对比。

如果你已经知道你想追求哪种认证,我已经写了一些关于如何开始获得解决方案架构师和开发人员认证的文章。

查看 AWS 和 Azure 的完整认证列表。

结论

我想谈谈定价,并做一个功能细分;然而,这些云提供商中的每一个都在不断地重新思考他们的价格模型并发布新功能。今天在价格和功能可用性方面是正确的,明天可能就不正确了。

但是回到我们的问题:我应该选择谁来托管我的企业未来十年的软件开发需求?

当然,要看情况。如果你正在处理一个已经存在的微软堆栈,我会推荐 Azure。

但如果我要从零开始创业,并且只能选择一个,我会选择 AWS。为什么?因为 AWS 的成熟程度和培训机会。我觉得使用 AWS 作为我的云提供商会更安全。

如果我让一名新工程师入职,而他们对云一无所知,他们可以通过 AWS 认证快速学习。目前最热门的认证是 AWS 解决方案架构师和 AWS 开发人员,他们的需求量很大。

这并不是说微软不提供认证。他们是。他们只是还没有达到 AWS 的成熟水平。

不成熟也延伸到文档和技术支持。由于 AWS 自身和社区的大力支持,学习如何在 AWS 中使用新功能或故障排除变得更加简单。

当然,你可以一直使用多云策略,并两者并用。你不必只选择一个。

但是为了这个讨论,如果我必须选择一个,我会选择 AWS,因为它们目前的成熟度。

赖安·格里森报道

[## Node.js 与 Spring Boot——你该选择哪一个?

轻松点。Spring Boot。对吗?没那么快…

medium.com](https://medium.com/better-programming/node-js-vs-spring-boot-which-should-you-choose-2366c2f76587) [## 是时候忘记反应,加入苗条的潮流了吗?

一场真正的泰坦之战(苗条还能算泰坦吗?)

medium.com](https://medium.com/better-programming/is-it-time-we-forget-react-and-jump-on-the-svelte-bandwagon-4848bb5d0839) [## 解决方案架构师与开发人员:AWS 认证细分

哪个适合你?

towardsdatascience.com](/solutions-architect-vs-developer-an-aws-certification-breakdown-4a7a28a8d7bd)

助推器之战

原文:https://towardsdatascience.com/battle-of-the-boosters-8ffd0671e56b?source=collection_archive---------56-----------------------

梯度助推器

最后一名支持者站在一场激烈的打斗比赛中

在梯度推进领域,我们已经取得了长足的进步。如果您已经阅读了整个系列,那么您应该对这个领域中主要算法的理论和实践方面有更好的理解。在对这些算法背后的数学和理论进行了一番严肃的研究后,我认为在一篇高度实用的博客文章中看到它们的实际应用会是一个有趣的改变。

所以,我向你们展示,助推器之战。

出席在 Unsplash 上的照片

数据集

我从 Kaggle 数据集中选择了几个数据集进行回归,主要是因为它在 Google Colab 中易于设置和运行。另一个原因是,我不需要在数据预处理上花很多时间,相反,我可以选择一个公共内核并开始破解。我还将分享我们选择的数据集的 EDA 的一个内核。所有的笔记本也会被分享,博客底部有链接。

  1. auto pgg—数据是来自 UCI 机器学习库的汽车技术规格。
    外形:(398,9), EDA 内核,数据量:低
  2. 房价:高级回归技术—Ames 住房数据集由 Dean De Cock 编制,用于数据科学教育。对于寻找经常被引用的波士顿住房数据集的现代化和扩展版本的数据科学家来说,这是一个令人难以置信的替代方案。有 79 个解释变量描述了(几乎)爱荷华州埃姆斯住宅的每个方面,这个比赛挑战你预测每个家庭的最终价格。
    外形:(1460,81), EDA 内核,数据量:中等
  3. 电动机温度 —数据集包括从部署在测试台上的永磁同步电动机(PMSM)收集的几个传感器数据。PMSM 代表了德国 OEM 的原型模型。
    外形:(998k,13), EDA 内核,数据量:高

实验装置

竞争中的算法

  1. XGBoost
  2. LightGBM
  3. 正则贪婪森林
  4. NGBoost

数据预处理

这里没什么特别的。只是做了一些基本的数据清理和缩放。大部分代码来自某个随机内核。唯一的一点是,相同的预处理应用于所有算法

交叉验证设置

我选择了交叉验证,以确保不同算法之间的比较更具普遍性,而不是针对某个特定的数据分割。在这个练习中,我选择了一个简单的 5 折 K 折。

估价

评估指标:均方误差

为了对所有算法进行标准评估(幸好它们都是 Sci-kit Learn api),我定义了几个函数。

默认参数:首先用模型的默认参数拟合 CV 分割。我们记录 CV 分数的平均值和标准偏差,然后拟合整个训练分割以预测测试分割。

使用超参数调整:与上一个非常相似,但是增加了一个 GridSearch 步骤来查找最佳参数。

超参数调优并不详尽,但相当不错。

我们针对不同算法运行 GridSearch 的网格有

XGBoost :

{ "learning_rate": [0.01, 0.1, 0.5], "n_estimators": [100, 250, 500], "max_depth": [3, 5, 7], "min_child_weight": [1, 3, 5], "colsample_bytree": [0.5, 0.7, 1], }

灯 GBM :

{ "learning_rate": [0.01, 0.1, 0.5], "n_estimators": [100, 250, 500], "max_depth": [3, 5, 7], "min_child_weight": [1, 3, 5], "colsample_bytree": [0.5, 0.7, 1], }

RGF :

{ "learning_rate": [0.01, 0.1, 0.5], "max_leaf": [1000, 2500, 5000], "algorithm": ["RGF", "RGF_Opt", "RGF_Sib"], "l2": [1.0, 0.1, 0.01], }

NGBoost :

因为 NGBoost 有点慢,我没有为所有实验定义一个标准的网格,而是沿着每个参数独立地搜索,并根据实验的直觉决定一个网格

结果

我已经列出了所有三个数据集的训练 CV 分割的 RMSEs 的平均值和标准偏差。对于电动马达,我没有调整数据,因为它的计算成本很高。

自动编程

自动 MPG 数据集结果

自动 MPG 平均值与 SD (RMSE)散点图

4 次 CV 分割和 1 次测试分割的执行时间

房价:高级回归技术

房价数据集结果

房价均值与标准差(RMSE)散点图

4 次 CV 分割和 1 次测试分割的执行时间

电机温度

电机温度数据集结果

电机温度平均值与标准差(RMSE)散点图

4 次 CV 分割和 1 次测试分割的执行时间

最后的话

免责声明 :这些实验绝不是完整的。人们需要更大规模的实验来得出哪个算法做得更好的结论。此外,我们还需要记住没有免费的午餐定理。

马上,NGBoost 似乎是这个领域的一个强有力的竞争者。在 AutoMPG 和房价数据集中,NGBoost 在所有其他助推器中表现最好,无论是在平均 RMSE 还是在 CV 分数的标准差上,都是如此,而且差距很大。NGBoost 还显示了默认版本和优化版本之间相当大的差距。这表明,要么默认参数没有设置好,要么数据集的每次调整都是从 NGBoost 获得良好性能的关键因素。但是该算法的致命弱点是运行时间。这些巨大的横条高耸在其他横条之上,我们可以看到,与其他加速器相比,运行时实际上处于不同的规模。特别是在像电机温度数据集这样的大型数据集上,运行时间非常大,因此我也没有调整算法。在竞争中,它在其他支持者中排名最后。

另一个突出的算法是正则化贪婪森林,它的性能与 XGBoost 一样好,甚至更好。在中低数据设置下,运行时间也堪比在位王者 XGBoost。

在低数据设置下,XGBoost 和 LightGBM 等流行算法表现不佳。并且 CV 值的标准差较高,特别是 XGBoost,表明它过拟合。XGBoost 在三个例子中都有这个问题。在运行时方面,LightGBM 是王者(尽管我没有针对计算性能进行过调整),在所有三个例子中都击败了 XGBoost。在高数据设置中,它通过比其他竞争对手低得多的 RMSE 和运行时间,击败了其他一切。

带实验的 Colab 笔记本

  • 自动 MPG
  • 房价
  • 电机温度

其他文章 渐变增强器

  • 良好的旧梯度增强
  • 正规化的贪婪森林
  • XGBoost
  • LightGBM
  • CatBoost
  • 自然渐变
  • NGBoost

我们已经在梯度增强领域取得了长足的进步,我希望至少对你们中的一些人来说,梯度增强并不意味着 XGBoost。这个世界上有很多算法都有自己的特点,其中很多算法的性能与 XGBoost 相当或者更好。另一个令人兴奋的领域是概率回归。我希望 NGBoost 变得更加高效,跨越计算效率障碍。一旦发生这种情况,NGBoost 是概率回归空间中一个非常强的候选者。

原载于 2020 年 7 月 1 日 http://deep-and-shallow.com

邻里之战

原文:https://towardsdatascience.com/battle-of-the-neighborhoods-b72ec0dc76b5?source=collection_archive---------46-----------------------

照片由 Pixaby 提供

使用数据科学在多伦多寻找最佳社区

作者:乌马尔·汗

这个项目旨在利用在 IBM 数据科学专业课程中学到的所有数据科学概念。我们定义一个业务问题,将被利用的数据,并使用这些数据,我们能够使用机器学习工具来分析它。在这个项目中,我们将一步一步地经历从问题设计、数据准备到最终分析的所有过程,并最终提供一个商业利益相关者可以用来做决策的结论。

目录

  1. 介绍
  2. 目标受众
  3. 数据概述
  4. 方法学
  5. 讨论
  6. 结论

1。识别业务问题(简介):

多伦多是加拿大人口最稠密的地区之一。作为充满机会的土地,它将来自不同种族背景的各种各样的人带到了加拿大的核心城市多伦多。作为加拿大最大的城市,估计人口超过 600 万,人口的多样性是毋庸置疑的。多元文化体现在各个社区,包括:唐人街、Corso Italia、小印度、肯辛顿市场、小意大利、韩国城等等。多伦多市中心是不同种族之间互动的中心,为企业家提供了许多创业或发展业务的机会。这是一个人们可以尝试各种文化精华的地方,无论是在工作时还是只是路过。多伦多以其美食而闻名。

这个项目的目标是使用 Foursquare 的位置数据和场地信息的区域聚类来确定多伦多开设餐馆的“最佳”社区。比萨和意大利面是多伦多最受欢迎的菜肴之一,源自意大利。多伦多是意大利人的第四大家园,人口超过 50 万,有很多机会开一家新的意大利餐厅。通过这个项目,我们将为一位企业家在加拿大多伦多开设一家新的意大利餐厅找到最合适的地点。

Pablo 在 Unsplash 拍摄的照片

2.目标受众

这个项目是针对那些想开一家新的意大利餐馆或扩大现有业务的企业家或企业主的。分析将提供目标受众可以使用的重要信息

3.数据概述

将需要的数据将是已准备好的 CSV 文件的组合,用于从多个来源进行分析,这些来源将提供多伦多的街区列表(通过维基百科)、街区的地理位置(通过地理编码器包)和与意大利餐馆有关的地点数据(通过 Foursquare)。场地数据将有助于找到哪个街区最适合开设意大利餐厅。

3.1 —数据采集:

来源 1:通过维基百科的多伦多社区

图 1:维基百科页面显示了多伦多的居民区列表以及各自的邮政编码

  1. https://en . Wikipedia . org/wiki/List _ of _ postal _ codes _ of _ Canada:_ M

上面显示的维基百科网站提供了几乎所有关于社区的信息。它包括邮政编码,行政区和多伦多的街区名称。由于数据的格式不适合分析,所以从这个站点收集数据(如图图 2 所示)。

图 2:从维基百科网站收集的数据放入熊猫数据框

来源 2:使用地理编码器包的地理位置数据

2.【https://cocl.us/Geospatial_data

第二个数据来源为我们提供了带有各自邮政编码的街区的地理坐标。该文件是 CSV 格式的,所以我们必须将其附加到 Pandas 数据框中(如图 3 所示)。

来源 3:使用 Foursquare 的场馆数据

我们进行了一些数据清理。从图 5(上图)中可以看出,邻域是按照邻域的名称进行分组的,因此以后的数据聚类更加容易。

4.方法学

4.1 —数据清理

在收集所有数据并将其放入数据框后,需要清理和合并数据以开始分析过程。从维基百科获取数据时,有些行政区未被分配到任何街区。因此,做出了以下假设:

1.只会处理具有指定区的像元。未分配的行政区会被忽略。

2.一个邮政编码区中可以有多个居民区。例如,在维基百科页面的表格中,您会注意到 M5A 被列出了两次,并且有两个街区:Harbourfront 和 Regent Park。这两行将合并成一行,相邻行用逗号分隔,如图图 2 第 4 行所示。

3.如果一个像元有一个区,但没有分配邻域,那么邻域将与区相同。

在实现以下假设后,根据区对行进行分组,如下所示。

使用从 Geocoder 包中收集的纬度和经度,我们根据邮政编码将两个表合并在一起。

之后,从 Foursquare API 中提取的场地数据与上表合并,为我们提供了 500 米半径内的本地场地,如下所示。

4.2 —数据探索

清理完数据后,下一步是分析数据。然后我们用叶子制作了一张地图,并根据每个街区所在的行政区对其进行了颜色编码。

这段代码为我们提供了下面的地图:

接下来,我们使用 Foursquare API 获得多伦多所有场所的列表,包括公园、学校、咖啡馆、亚洲餐馆等。获得这些数据对于分析多伦多的意大利餐馆数量至关重要。多伦多总共有 45 家意大利餐馆。然后,我们将 Foursquare 地点数据与邻近地区数据合并,这样我们就可以得到每个邻近地区最近的地点。

4.3 —机器学习

然后,为了分析数据,我们执行了一项技术,将分类数据转换为机器学习算法的数值数据。这种技术叫做 One hot encoding 。对于每一个街区,单个场馆被转换成每个街区有多少个场馆的频率。

然后,我们根据邻近地区对这些行进行分组,并取每个场馆类别出现频率的平均值

之后,我们创建了一个新的数据框,它只存储街区名称以及该街区意大利餐馆的平均出现频率。这使得数据可以基于每个单独的邻域进行汇总,并使数据分析更加简单。

k 均值聚类

为了使分析更有趣,我们希望根据附近意大利餐馆的平均数量对附近进行聚类。为此,我们使用了 K-Means 聚类。为了得到我们的最佳 K 值,既不过度拟合也不欠拟合模型,我们使用了肘点技术。在这种技术中,我们使用不同数量的 K 值进行测试,测量精确度,然后选择最佳的 K 值。最佳 K 值选择在直线具有最大转弯的点上。在我们的例子中,我们的肘点在 K = 4。这意味着我们总共有 4 个集群。

然后,我们使用一个模型,准确地指出最佳 K 值。我们从 Yellowbrick 包中导入了“ KElbowVisualizer ”。然后,我们将上面的 K-Means 模型与 Elbow visualizer 进行拟合。

这给出了下面的模型:

我们只是整合了一个模型来拟合误差并计算失真分数。从虚线中,我们可以看到弯头位于 K=4 处。此外,在 K-Means 聚类中,基于某个变量相似的对象被放入同一聚类中。具有相似的意大利餐馆平均频率的街区被分成 4 组。这些簇中的每一个被标记为从 0 到 3,因为标记的索引从 0 而不是 1 开始。

之后,我们将场地数据与上表合并,创建了一个新表,作为分析在多伦多新开一家意大利餐厅的新机会的基础。然后,我们使用 Python 中的 Folium 包创建了一个地图,并根据聚类标签对每个邻域进行了着色。

  • 集群 1 —红色
  • 集群 2 —紫色
  • 第 3 组——蓝绿色
  • 第 4 组—深卡其色

上图显示了意大利餐馆平均出现频率相似的不同聚类。

4.4 —数据分析

我们总共有 4 个聚类(0,1,2,3)。在我们逐一分析它们之前,让我们检查每个聚类中的街区总数以及该聚类中的平均意大利餐馆数。从使用 Matplotlib 制作的条形图(图 18)中,我们可以比较每个集群的邻域数量。我们看到,聚类 1 的邻域最少(1),而聚类 2 的邻域最多(70)。簇 3 有 14 个街区,而簇 4 只有 8 个。然后我们比较了每个集群的平均意大利餐馆。

聚类分析

这一信息至关重要,因为我们可以看到,尽管聚类 1 中只有 1 个邻域,但其意大利餐馆的数量最多(0.1304),而聚类 2 中的邻域最多,但意大利餐馆的平均数量最少(0.0009)。普通意大利餐馆的平均值构成了图 18 的数据。此外,从地图上,我们可以看到集群 2 中的居民区是人口最稀少的。现在让我们单独分析这些集群(注意:这些只是数据的片段)。

聚类 1(红色):

第一组位于北约克地区。贝德福德和劳伦斯庄园东是该集群中的两个社区。集群 1 有 19 个独特的地点,其中只有 3 个是意大利餐馆。聚类 1 具有最高的意大利餐馆平均值,相当于 0.130435。意大利餐厅的平均水平最高的原因是,所有这些餐厅都在贝德福德和劳伦斯庄园东两个街区。

集群 2(蓝色):

总共有 70 个街区,229 个不同的场地,只有一家意大利餐馆。因此,在第 2 组中靠近场馆的意大利餐馆的平均数量是最低的,为 0.01。在地图上,我们可以看到集群 3 的节点分散在整个多伦多,使其成为人口最稀少的集群之一。

集群 3(青绿色):

集群 3 拥有第二低的意大利餐馆平均数。第 3 组主要位于市区,但也有一些在西多伦多,东多伦多和北约克的居民区。像瑞尔森,多伦多统治中心,唐米尔斯,花园区,女王公园和更多的街区都包括在这个集群中。总共有 176 个独特的场馆,其中 27 个是意大利餐厅。

聚类 4(深卡其色):

第 4 组场馆位于多伦多市区、西部、东部和中部以及斯卡伯勒。中央湾街、多伦多大学、中央湾街和河谷镇等街区构成了这个集群。第 4 组共有 91 个独特的场馆,16 家意大利餐厅。这是该集群中意大利餐馆的第二高平均值,约为 0.063。

因此,每个聚类中的普通意大利餐馆的排序如下:

1.聚类 1 (≈0.1304)

2.聚类 4 (≈0.0632)

3.聚类 3 (≈0.0317)

4.聚类 2 (≈0.0009)

5.讨论:

大多数意大利餐馆都在由红色聚类表示的聚类 1 中。位于北约克区的意大利餐馆平均数量最高的街区是贝德福德公园和劳伦斯庄园东。尽管在集群 2 中有大量的社区,但是几乎没有意大利餐馆。我们看到,在多伦多市区(集群 3)有倒数第二的意大利餐馆。看看附近的场地,多伦多市中心是开设新意大利餐厅的最佳地点,因为该地区有许多社区,但几乎没有意大利餐厅,因此消除了任何竞争。拥有巨大机会的第二好的社区是在阿德莱德和国王、美景镇等地区。也就是第二组。该地区有 70 个街区没有意大利餐馆,这给了开一家新餐馆的好机会。这种分析的一些缺点是——聚类完全基于从 Foursquare API 获得的数据。此外,该分析没有考虑邻近地区的意大利人口,因为这在选择开设新意大利餐厅的地点时会起到很大的作用。这总结了该项目的最佳发现,并建议企业家在这些地方开设一家正宗的意大利餐厅,几乎没有竞争。

6.结论

总之,为了结束这个项目,我们有机会解决一个业务问题,解决这个问题的方式与真正的数据科学家相似。我们利用大量 Python 库来获取信息、控制内容、分解和可视化这些数据集。我们利用 Foursquare API 调查了多伦多附近的环境,从维基百科获得了大量数据,这些数据是我们用 Beautifulsoup 网络抓取库抓取的。我们还利用 seaborn 和 Matplotlib 库中的不同绘图进行了可视化。类似地,我们应用人工智能策略来预测给定信息的错误,并利用 follow 将其描绘在地图上。

有改进空间或某些缺点的地方让我们知道,这个项目可以在更多信息和独特的机器学习策略的帮助下进一步改进。此外,我们可以利用这一风险来调查任何情况,例如,开一家替代餐馆或开一家电影院等等。理想情况下,这项任务充当使用数据科学解决更复杂的现实生活问题的初始方向。

代码可以在 Github 上找到,也可以在 T2 的 Linkedin 上找到我!!!

进入下一个问题:)

变形金刚之战:伊莱克特拉,伯特,罗伯塔,还是 XLNet

原文:https://towardsdatascience.com/battle-of-the-transformers-electra-bert-roberta-or-xlnet-40607e97aba3?source=collection_archive---------11-----------------------

伊莱克特拉是新来的。让我们来看看它是如何对抗老守卫的!

图片由 272447 来自 Pixabay

Transformer 模型成功背后的“秘密”之一是迁移学习技术。在迁移学习中,一个模型(在我们的例子中是一个 Transformer 模型)使用一个无监督的预训练目标在一个巨大的数据集上预训练同样的模型然后在手头的实际任务中进行微调(通常是监督训练)。这种方法的美妙之处在于微调数据集可以小到 500–1000 个训练样本!如果称之为深度学习,这个数字小到可能会被嗤之以鼻。这也意味着昂贵且耗时的流水线部分预训练只需进行一次,并且预训练模型可在此后的任意数量的任务中重复使用。因为预先训练的模型通常是公开的🙏,我们可以获取相关模型,在自定义数据集上对其进行微调,几个小时后就有一个最先进的模型可以使用了!

如果您有兴趣了解预训练如何工作,以及如何在单个 GPU 上训练一个全新的语言模型,请查看下面链接的我的文章!

[## 理解 ELECTRA 并训练一个 ELECTRA 语言模型

变形金刚模型如何学习语言?伊莱克特拉有什么新消息?你如何在一个…

towardsdatascience.com](/understanding-electra-and-training-an-electra-language-model-3d33e3a9660d)

ELECTRA 是谷歌发布的预训练变形金刚模型的最新类别之一,与大多数其他版本相比,它有所改变。在很大程度上,Transformer 模型遵循了人们熟知的深度学习路径,更大的模型、更多的训练和更大的数据集等于更好的性能。然而,ELECTRA 通过使用更少的计算能力、更小的数据集、更少的训练时间,超越了早期的模型,如 BERT,从而扭转了这种趋势。(如果你想知道,伊莱克特拉和伯特的“尺寸”是一样的)。

在这篇文章中,我们将看看如何使用一个预训练的 ELECTRA 模型进行文本分类,并在此过程中与其他标准模型进行比较。具体来说,我们将比较下面列出的每个模型的最终性能(马修斯相关系数 (MCC) )和训练时间。

  • electra-小型
  • 电子基础
  • 伯特基础案例
  • 蒸馏底壳的
  • 蒸馏贝塔碱
  • 罗伯塔基地
  • xlnet-base-cased

和往常一样,我们将使用简单变形金刚库(基于拥抱脸变形金刚库)来完成这项工作,并且我们将使用权重&偏差进行可视化。

您可以在库的示例目录中找到这里使用的所有代码。

装置

  1. 从这里安装 Anaconda 或 Miniconda 包管理器。

  2. 创建新的虚拟环境并安装软件包。
    conda create -n simpletransformers python pandas tqdm
    conda activate simpletransformers

  3. 如果您使用 fp16 培训,请安装 Apex。请遵循此处的说明。

  4. 安装简单变压器。

数据准备

我们将使用 Yelp 评论极性数据集,这是一个二元分类数据集。下面的脚本将下载它并存储在data目录中。或者,您可以从 FastAI 手动下载数据。

超参数

一旦数据在data目录中,我们就可以开始训练我们的模型。

简单的变压器模型可以进行广泛的配置(见文档),但是我们将只进行一些基本的、“足够好的”超参数设置。这是因为我们更感兴趣的是在平等的基础上相互比较模型,而不是试图优化每个模型的绝对最佳超参数。

考虑到这一点,我们将把train_batch_size增加到128,并且我们将把num_train_epochs增加到3,这样所有的模型都将有足够的训练来收敛。

这里需要注意的是,XLNet 的train_batch_size减少到了64,因为它不能在 RTX 泰坦 GPU 上用train_batch_size=128进行训练。但是,通过将gradient_accumulation_steps设置为2,将有效批量更改为128,可以将这种差异的影响降至最低。(每两步只计算一次梯度并更新一次模型权重)

影响训练的所有其他设置都保持默认值不变。

训练模型

设置培训流程非常简单。我们只需要将数据加载到数据帧中并定义超参数,然后我们就可以开始比赛了!

为了方便起见,我使用相同的脚本来训练所有模型,因为我们只需要在每次运行之间更改模型名称。模型名称由 shell 脚本提供,该脚本还会自动为每个模型运行训练脚本。

培训脚本如下所示:

注意,Yelp 评论极性数据集使用标签 *[1, 2]* 分别表示正极和负极。我把这个改成 *[0, 1]* 分别表示否定和肯定。简单变形金刚要求标签从 *0* (咄!)而负面情绪的一个标签 *0* 就直观了很多(在我看来)。

可以自动化整个过程的 bash 脚本:

注意,您可以通过向 bash 脚本添加 *rm -r outputs* 来删除每个阶段保存的模型。如果你没有足够的磁盘空间,这可能是个好主意。

训练脚本还将记录权重和偏差的评估分数,让我们可以轻松地比较模型。

有关训练分类模型的更多信息,请查看简单转换程序文档。

结果

你可以在这里找到我所有的结果。尝试使用不同的图表和信息!

让我们回顾一下重要的结果。

最终分数

这些是每个模型获得的最终 MCC 分数。如你所见,所有型号的分数都非常接近。

为了更好地了解差异,下面的图表放大到 X 轴,只显示范围 0.88-0.94。

请注意,放大视图虽然有助于发现差异,但会扭曲对结果的感知。因此,下表仅用于说明目的。 当心隐藏了零的图!

roberta-base型号领先,xlnet-base紧随其后。接下来是distilroberta-baseelectra-base车型,它们之间几乎没有任何区别。老实说,在这种情况下,两者之间的差异可能更多地是由于随机机会而不是其他任何东西。最后,我们分别有bert-base-caseddistilbert-base-casedelectra-small

查看实际值会发现它们非常接近。

在这次实验中,罗伯塔似乎比其他模特表现得更好。然而,我敢打赌,通过一些技巧,如超参数调整和集成,ELECTRA 模型能够弥补这一差异。这一点得到了当前 GLUE 基准排行榜的证实,在该排行榜中,伊莱克特拉位于罗伯塔之上。

重要的是要记住,与 RoBERTa 相比,ELECTRA 模型所需的预培训资源要少得多(大约四分之一)。对于distilroberta-base也是如此。尽管distilroberta-base模型相对较小,但在提取到distilroberta-base之前,您需要原始的roberta-base模型。

XLNet 模型几乎与 RoBERTa 模型并驾齐驱,但它比这里显示的所有其他模型需要更多的计算资源(参见训练时间图)。

古老的(虽然不到两年)BERT 模型开始显示出它的年龄,并且被除了electra-small模型之外的所有模型超越。

https://imgflip.com/i/40s1sv

虽然不完全符合其他型号的标准,但electra-small型号的性能仍然令人钦佩。正如所料,它训练速度最快,内存需求最小,推理速度最快。

说到训练时间…

训练的速度主要由模型的大小(参数的数量)决定,XLNet 的情况除外。与 XLNet 一起使用的训练算法使得它比比较的 BERT、RoBERTa 和 ELECTRA 模型慢得多,尽管具有大致相同数量的参数。与这里测试的其他模型相比,XLNet 的 GPU 内存需求也更高,因此需要使用更小的训练批量(如前所述,64 比 128)。

推断时间(此处未测试)也应遵循这一总体趋势。

最后,另一个重要的考虑因素是每个模型收敛的速度。所有这些模型都训练了 3 个完整时期,没有使用早期停止。

显然,在收敛需要多少训练步骤方面,模型之间没有可辨别的差异。所有的模型似乎都集中在 9000 步左右。当然,收敛所需的时间会因训练速度的不同而不同。

结论

很难在不同的变压器型号之间做出选择。然而,我们仍然可以从我们看到的实验中获得一些有价值的见解。

  • 根据具体情况,旧型号可能会超过 ELECTRA 型号。但是,它的优势在于它能够以明显更少的用于预训练的计算资源达到有竞争力的性能水平。
  • ELECTRA 论文指出electra-small模型明显优于类似规模的 BERT 模型。
  • 为了更快的训练和推断,Transformer 模型的精华版本牺牲了一些精度点。在某些情况下,这可能是一种理想的交换。
  • XLNet 牺牲了训练和推理的速度,以换取在复杂任务上可能更好的性能。

基于这些见解,我可以提供以下建议(尽管应该有所保留,因为不同数据集之间的结果可能会有所不同)。

  • 对于大多数任务来说,这似乎仍然是一个很好的起点。根据结果,您可以决定超参数调整,变大,或变小!
  • 如果你正在训练一个新的语言模型,或者如果你想微调一个语言模型,我推荐使用 ELECTRA 方法。尤其是在计算资源和/或可用数据有限的情况下。

看看大型车型是否也追随这一趋势会很有趣。我希望在以后的文章中测试这一点(T5 也可能会加入进来)!

如果你想看到一些关于不同模型的训练和推理速度的更深入的分析,请查看下面链接的我的早期文章(很遗憾,没有 ELECTRA)。

[## 蒸馏还是不蒸馏:伯特、罗伯塔和 XLNet

变形金刚是自然语言处理中无可争议的王者。但是有这么多不同的模型,它可以…

towardsdatascience.com](/to-distil-or-not-to-distil-bert-roberta-and-xlnet-c777ad92f8)

作为一名大学生,与数据科学领域的新冠肺炎展开较量

原文:https://towardsdatascience.com/battling-covid-19-with-data-science-as-a-university-student-ffcb9304b4c?source=collection_archive---------40-----------------------

利用简历来照亮大学同学的就业前景

科尔·凯斯特在 Unsplash 上的照片

随着新冠肺炎给全球经济带来厄运,世界正面临一个不确定的时期。

作为一名本科生,当可能的流行病传播的消息开始涌入时,我的实习/工作前景肯定受到了打击。几周之内,这个雪球越滚越大,变成了疫情,几乎让整个世界陷入了停顿。就目前的情况来看,求职者尤其是新加入劳动大军的人的前景变得相当暗淡。

动机:

随着疫情的持续,受伤的经济是理所当然的;但是,亲眼目睹我的朋友、队友和学长们失去工作和实习机会是令人心痛的。因此,作为应对措施,我开始在 LinkedIn 上搜索空缺职位和实习生,并疯狂地向大学校友发送大量联系请求。

就在那时,我产生了这个想法。在这些痛苦的时刻,最有可能帮助我们的是我们的校友。因此,由于未能找到一个联系校友的机构门户,我决定自己动手。

首选武器(闪亮):

我心里很清楚我想要的是什么,我想向我的队友们提供关于我们校友的有见地的和可操作的信息。这让我陷入了困境,因为我对 web 开发不是很精通,但已经和 R 一起工作了一段时间。

所以,我有两个选择:

  • 参加一些在线课程,温习我的 HTML、CSS、JS 知识,可能还有 MongoDB,在 web 开发方面提高一些水平,然后处理这个项目。
  • 利用我在 R 方面更好的水平,用我的方式构建了一个可以托管的 R 闪亮应用。

因为时间是至关重要的,而且考虑到我的不安,这个选择是显而易见的。

整装待发:

尽管我对 R 有丰富的工作知识,但 R 闪亮的开发对我来说是一个完全陌生的领域。所以我决定完成一个关于 R Shiny 开发的快速课程并继续我的项目。

多亏了 Datacamp 讲师简洁明了的解释,我才得以顺利通过课程,同时对开发这种令人难以置信的工具(如 Shiny)的人充满敬畏。

这个项目终于开始了:

构建校友数据集:

这是我马上面临的第一个问题。为了收集我大学校友的数据,我不得不从 LinkedIn 上搜集数据,LinkedIn 对发现搜集者非常警惕。

所以我在网上做了一些调查,发现每天 150 个个人资料是安全的。超过这个限制意味着我的个人资料很有可能被标记。此外,我必须使用我自己的个人资料,否则大多数校友将显示为“LinkedIn 会员”,这是一个没有很多联系的虚拟个人资料。因此,最初的目标是 400-500 份档案,我开始着手工作。

数据木工:

一旦数据被抓取并存储在一个. csv 文件中,我就有了清理数据的任务。在下面给出的代码中,我采取了以下步骤:

  1. 已删除任何重复条目。
  2. 从数据中删除了所有不必要的字段。
  3. 识别学生(因为他们不与任何组织相关联),并将他们从数据集中删除。
  4. 现在,数据已经清理完毕,可以使用了。

应用程序的布局:

为了美观,我决定用“Shinydashboard”而不是普通的闪亮。在任何类型的开发活动中,在开始编码之前,拥有最终产品的草图是至关重要的。我设想我的应用程序具有以下功能:

  1. 用户应该能够直观地检查所有的组织,地点和行业的大学(IIIT 布巴内斯瓦尔)校友就业。
  2. 然后,用户应该能够选择一个特定的组织,位置和行业,以查看与之相关的所有校友。
  3. 然后,用户应该能够按姓名搜索校友的所有详细信息。

ui。r 和服务器。r:

考虑到布局,我开始编码。以下是我在我的界面中采取的步骤。R 文件,以及代码(完整的代码可以从我的 Github repo 中获得,文章末尾给出了链接):

  1. 已加载所有必需的库。
  2. 给了一个合适的标题。
  3. 在侧边栏菜单中,添加了应用程序布局中提到的所有搜索功能。
  4. 在仪表板主体中,创建了与侧边栏菜单功能相关的所有组件。

代表性代码。如需完整代码,请访问我的 github repo。

以下是我在我的服务器上采取的步骤。R 文件,以及代码(完整的代码可以从我的 Github repo 中获得,文章末尾给出了链接):

  1. 创建函数来帮助从数据加工后获得的原始数据集准备不同的数据集。
  2. 创建了辅助函数来生成图和表。
  3. 渲染了所有相关组件。

代表性代码。如需完整代码,请访问我的 github repo。

部署应用程序:

使用“r studio”和“ Shinyapps.io ”部署应用程序相当容易。注册和创建账户只需几分钟。更多信息可以在这里找到。

以下是我最终作品的片段(IIIT·布巴内斯瓦尔校友墙):

最终产品片段:IIIT-Bh 校友墙

结论:

如果你对代码感兴趣,这里是。

如果你想看看我最终部署的产品,这里是。但是请记住以下几点:

  • 在您的笔记本电脑/台式机上查看该应用程序以获得所涉及的图表/绘图的清晰视图。如果由于某种原因无法使用,请在移动设备上使用横向模式。
  • 此应用程序在您的浏览器中的最佳观看效果**为 80%缩放比例**而非 100%默认比例,按“Ctrl”+“-”缩小。这很可能是由于一些固有的闪亮问题。**
  • 我还是一名学生,所以我使用免费的 Shinyapp 托管层,因此应用加载会很慢。此外,积极观看的时间有限也是一个额外的缺点。

我缺乏 CSS 技能,这让我很不满意,但是如果你有不错的 CSS 和/或 JS 技能,你可以利用这个教程为你的学院设计一个更好的“校友墙”版本。所以我现在就要结束了,祝你一切顺利,用你的技能去改善和帮助你所关心的人。

你也可以给我买杯 T21 咖啡来支持我的工作。

谢谢你,祝你成功。

贝叶斯法则及简单实用的例子

原文:https://towardsdatascience.com/bayes-rule-with-a-simple-and-practical-example-2bce3d0f4ad0?source=collection_archive---------4-----------------------

我们用 Python 代码演示了简单而实用的贝叶斯规则应用示例。

贝叶斯法则

贝叶斯定理(或称贝叶斯定律或贝叶斯法则)被称为概率统计中最强有力的规则。它描述了一个事件发生的概率,基于可能与该事件相关的条件的先验知识。

例如,如果疾病与年龄有关,那么使用贝叶斯定理,与在不知道人的年龄的情况下做出的疾病概率的评估相比,可以使用人的年龄来更准确地评估他们患有疾病的概率。

这是一个强有力的概率法则,它将“主观性”或“信任度”的概念引入到冰冷、生硬的统计建模中。随着证据或数据按顺序收集,贝叶斯规则是唯一可用于逐步更新事件概率的机制。

历史

图片来源:维基百科

贝叶斯定理是以牧师托马斯·贝叶斯的名字命名的,他首先使用条件概率提供了一种算法(他的命题 9),这种算法使用证据来计算未知参数的极限,发表为 一篇旨在解决机会主义 中一个问题的论文(1763)。在他所谓的“训诂学”中,Bayes 将他的算法扩展到任何未知的先验原因。

独立于贝叶斯,皮埃尔·西蒙·拉普拉斯在 1774 年,以及后来在他的 1812théOrie analytique des probabilityés在给定证据的情况下,使用条件概率来从先验概率制定更新后验概率的关系。**

这是一个强有力的概率法则,它将“主观性”或“信任度”的概念引入到冰冷、生硬的统计建模中。

现代数据科学的逻辑过程

这是进行数据科学的逻辑方法。

我们从一个假设和对该假设的信任度开始。这意味着,基于领域专长或先验知识,我们为该假设分配一个非零概率。

然后,我们收集数据,更新我们最初的信念。如果数据支持假设,那么概率上升,如果不匹配,那么概率下降。

听起来简单又符合逻辑,不是吗?

****但是传统上,在大多数统计学习中,先验的概念没有被使用或者看起来不太好。此外,贝叶斯学习的计算复杂性使其在超过两百年的时间里无法成为主流。

但是随着贝叶斯推理的出现,事情正在发生变化…

如果数据支持假设,那么概率上升,如果不匹配,那么概率下降。

贝叶斯推理

随着人工智能和数据驱动的机器学习系统在商业、科学和技术的各个方面的全球兴起,贝叶斯统计和建模最近重新兴起。

贝叶斯推理正被应用于遗传学、语言学、图像处理、脑成像、宇宙学、机器学习、流行病学、心理学、法医学、人类物体识别、进化、视觉感知、生态学以及知识发现和预测分析发挥重要作用的无数其他领域。

随着人工智能和数据驱动的机器学习系统在全球的兴起,贝叶斯统计和建模最近有了复兴

Python 代码的实际例子

药物筛选

图片来源: Pixabay

我们将把贝叶斯规则应用于药物筛选问题(例如,对联邦政府或许多其他承诺无毒品工作环境的工作进行强制性检测)。

假设使用特定药物的测试灵敏度为 97%,特异性为 95%。也就是说,对于吸毒者,测试将产生 97%的真阳性结果,而对于非吸毒者,测试将产生 95%的真阴性结果。这些是任何筛查测试都会有的测试历史数据。贝叶斯法则允许我们使用这种数据驱动的知识来计算最终的概率。

假设,我们也知道普通人群中有 0.5%的人是该药物的使用者。随机选择的测试呈阳性的个人是吸毒者的概率是多少?

****请注意,这是“先验”的关键部分,它是关于常见患病率的一项概括知识。这是我们对随机测试对象成为吸毒者的概率的先验信念。这意味着如果我们从普通人群中随机选择一个人,没有任何测试,我们只能说这个人有 0.5%的几率是吸毒者

在这种情况下,如何使用贝叶斯法则呢?

我们将编写一个自定义函数,该函数接受测试能力和吸毒者百分比的先验知识作为输入,并根据阳性结果生成考生成为吸毒者的输出概率。

这是根据贝叶斯法则计算的公式…

实际的 代码在这里是

如果我们用给定的数据运行函数,我们会得到下面的结果,

这里有什么迷人之处?

即使一项检测对阳性病例的正确率为 97%,对阴性病例的正确率为 95%,结果呈阳性的吸毒者的真实概率也只有 8.9%!

如果你看一下计算,这是因为流行率极低。假阳性的数量超过真阳性的数量。****

例如,如果测试 1000 个人,预计有 995 个非用户和 5 个用户。从 995 个非用户中,预计有 0.05 × 995 个≃ 50 假阳性。从这 5 个用户中,预计有 0.95 × 5 ≈ 5 个真阳性。55 个阳性结果中,只有 5 个是真实的!

我们来看看概率是如何随患病率变化的。 代码在这里

注意,你的决定取决于概率阈值。目前,该值设定为 0.5。必要的话可以降低。但是,在 0.5 的阈值处,你需要有一个几乎 4.8%的流行率来抓住一个测试结果为单一阳性的用户。****

改进这个场景需要什么水平的测试能力?

我们看到,测试的灵敏度和特异性强烈影响这一计算。因此,我们可能想看看需要什么样的能力来提高抓住吸毒者的可能性。

Python 代码在这里

****

上面的图清楚地表明,即使接近 100%的灵敏度,我们也没有获得多少。然而,相对于测试的特异性而言,概率响应是高度非线性的,当它达到完美时,我们得到概率的大幅增加。因此,所有的研发努力都应该集中在如何提高检测的特异性上

这一结论可以从概率低的主要问题是流行率低这一事实中直观地得出。因此,正确捕捉非用户(即提高特异性)是我们应该关注的领域,因为他们在数量上比用户多得多。

在这个问题中,反面例子的数量比正面例子多得多。所以测试真正的阴性表现应该是优秀。

链式贝叶斯规则

贝叶斯推理最好的一点是能够在贝叶斯定理的分子中以先验概率项的形式使用先验知识

在这种药物筛选的背景下,先验知识只不过是一个测试的计算概率,然后反馈到下一个测试

这意味着,在这些病例中,一般人群中的患病率极低,如果第一次检测结果为阳性,增加信心的一种方法是规定后续检测。

第一次测试的后验概率成为第二次测试**的先验,即 P(用户) 不再是第二次测试的一般患病率,而是第一次测试的概率。**

下面是演示链接的简单代码。

当我们运行这段代码时,我们得到如下结果,

**The test-taker may not be an user
Probability of the test-taker being a drug user, in the first round of test, is: 0.089

The test-taker could be an user
Probability of the test-taker being a drug user, in the second round of test, is: 0.654

The test-taker could be an user
Probability of the test-taker being a drug user, in the third round of test, is: 0.973**

当我们第一次运行测试时,输出(后验)概率很低,只有 8.9%,但随着第二次测试,这一概率显著上升到 65.4%,第三次阳性测试的后验概率为 97.3%。

因此,第一次无法筛选用户的测试可以多次使用,以通过连续应用贝叶斯规则来更新我们的信念。

贝叶斯推理最好的一点是使用先验知识的能力,先验知识是贝叶斯定理分子中的先验概率项。

摘要

在本文中,我们展示了最强大的统计定律之一——贝叶斯定理的基础和应用。近年来,利用这一定律的高级概率建模和推理过程已经占据了数据科学和分析的世界。

我们使用一个非常简单但实用的药物筛选测试示例和相关的 Python 代码演示了贝叶斯规则的应用。我们展示了测试限制如何影响预测的概率,以及对于高置信度的筛选,测试的哪一方面需要改进。

我们进一步展示了如何将多个贝叶斯计算链接在一起,以计算总体后验概率和贝叶斯推理的真实能力。

进一步的阅读和资源,可以参考这些优秀的文章,

  1. https://www.mathsisfun.com/data/bayes-theorem.html
  2. https://better explained . com/articles/an-intuitive-and-short-explain-of-Bayes-theorem/

如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。此外,您可以查看作者的 GitHub 资源库中的代码、想法和机器学习和数据科学方面的资源。如果你和我一样,对人工智能/机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。

** [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…

通过写作使数据科学/ML 概念易于理解:https://medium.com/@tirthajyoti 开源和有趣…

www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)**

贝叶斯定理 101 —示例解决方案

原文:https://towardsdatascience.com/bayes-theorem-101-example-solution-ff54147d6c7f?source=collection_archive---------3-----------------------

数据科学的数学

举例说明贝叶斯定理的一种简单方法

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

条件概率是数据科学和统计学的必要条件。条件概率和贝叶斯定理有很多有用的解释和例子。在这篇文章中,我将用简单的数学知识举例说明贝叶斯定理的背景。

贝叶斯定理在数学表达式中看起来很简单,比如;

P(A|B) = P(B|A)P(A)/P(B)

数据科学中重要的一点不是方程本身,把这个方程应用到语言问题中比记住方程更重要。所以,我将用贝叶斯定理和逻辑来解决一个简单的条件概率问题。

问题 1:

让我们用贝叶斯定理来解决一个简单的 NLP 问题。通过使用 NLP,我可以检测收件箱中的垃圾邮件。假设在我的帐户中,80%的垃圾邮件中都出现了“offer”这个词。另外,让我们假设“要约”出现在我想要的 10%的电子邮件中。如果收到的电子邮件中有 30%被认为是骗局,而我将收到一封包含“offer”的新邮件,那么它是垃圾邮件的概率是多少?

现在,我假设我收到了 100 封电子邮件。垃圾邮件占整个电子邮件的百分比是 30%。所以,我在 100 封邮件中有 30 封垃圾邮件和 70 封想要的邮件。单词“offer”在垃圾邮件中出现的百分比是 80%。这意味着 30 封电子邮件中的 80%会变成 24 封。现在,我知道 100 封邮件中有 30 封是垃圾邮件,其中 24 封包含“offer ”, 6 封不包含“offer”。

单词“offer”在期望的电子邮件中出现的百分比是 10%。这意味着其中 7 封(70 封想要的邮件中的 10%)包含单词“offer ”, 63 封不包含。

现在,我们可以在一个简单的图表中看到这个逻辑。

作者图片

问题是,当邮件中包含单词“offer”时,垃圾邮件的概率是多少:

  1. 我们需要找到包含“offer”的邮件总数;

24 +7 = 31 邮件包含“报价”一词

2.如果邮件包含“offer ”,找出垃圾邮件的概率;

在 31 封邮件中,24 封包含“提供”意味着 77.4% = 0.774(概率)

注意:在这个例子中,我选择计算后给出整数的百分比。一般来说,你可以认为我们在开始时有 100 个单元,所以如果结果不是整数,也不会产生问题。因此,我们不能说是 15.3 封电子邮件,但我们可以说是 15.3 个单位。

贝叶斯方程解:

A =垃圾邮件

B =包含“要约”一词

作者图片

p(包含 offer|spam) = 0.8(问题中给定)

p(垃圾邮件)= 0.3(问题中给定)

现在我们会发现带有‘offer’这个词的电子邮件的概率。我们可以通过在垃圾邮件和想要的电子邮件中添加“offer”来计算。使得;

p(含报价)= 0.30.8 + 0.70.1 = 0.31

作者图片

从两方面来看,结果是一样的。在第一部分,我用一个简单的图表解决了同样的问题,在第二部分,我用贝叶斯定理解决了同样的问题。

问题二:

我想从新冠肺炎这个热门话题中再解决一个例子。如你所知,新冠肺炎测试现在很普遍,但有些测试结果是不真实的。我们假设:诊断测试有 99%的准确率,60%的人患有新冠肺炎。如果一个病人检测呈阳性,那么他真的患病的可能性有多大?

作者图片

有阳性结果的总单位数= 59.4 + 0.4 = 59.8

59.4 单位(真阳性)是 59.8 单位意味着 99.3% = 0.993 概率

用贝叶斯;

作者图片

p(正|covid19) = 0.99

P(covid19) = 0.6

p(正)= 0.60.99+0.40.01=0.598

作者图片

同样,我们在图表中找到了相同的答案。有很多例子可以学习贝叶斯定理的应用,例如蒙蒂霍尔问题,这是一个小难题,你有三扇门。在门后面,有两只山羊和一辆汽车。要求您选择一个门来查找汽车。选择一扇门后,主人打开一扇没被选择的门,露出山羊。然后,你被要求切换门或坚持你的第一选择。通过运行这个过程一千次并进行模拟,您可以找到获胜的概率,并通过 Monty Hall 问题大致了解贝叶斯定理和贝叶斯统计的思想。

当我们想到机器学习概念中的贝叶斯定理时,它提供了一种通过使用数据和假设之间的关系来基于条件计算假设的概率的方法。此外,这也是理解数据科学分类问题和朴素贝叶斯分类器中的真阳性、假阳性、真阴性和假阴性概念的第一步。

如果你喜欢这篇文章,并想分享你的想法或提出问题,请随时通过 LinkedIn 与我联系。

其他资源:

如果您想深入了解这些资源:

[## 贝叶斯定理

在概率论和统计学中,贝叶斯定理(或者贝叶斯定理、贝叶斯定律或贝叶斯法则)…

en.wikipedia.org](https://en.wikipedia.org/wiki/Bayes'_theorem) [## 1.9.朴素贝叶斯-sci kit-学习 0.23.1 文档

朴素贝叶斯方法是一组监督学习算法,基于应用贝叶斯定理和“朴素”学习理论

scikit-learn.org](https://scikit-learn.org/stable/modules/naive_bayes.html) [## 机器学习的贝叶斯定理简介——机器学习掌握

贝叶斯定理提供了一种计算条件概率的原则方法。这是一个看似简单的…

machinelearningmastery.com](https://machinelearningmastery.com/bayes-theorem-for-machine-learning/) [## 贝叶斯信念网络简介-机器学习掌握

概率模型可以定义变量之间的关系,并用于计算概率。比如说…

machinelearningmastery.com](https://machinelearningmastery.com/introduction-to-bayesian-belief-networks/)

贝叶斯定理实际上是一个直观的分数

原文:https://towardsdatascience.com/bayes-theorem-is-actually-an-intuitive-fraction-5f2803998006?source=collection_archive---------26-----------------------

不使用术语,把定理拆开

贝叶斯定理是概率领域最著名的定理之一,它经常被用作机器学习的基线模型。然而,它经常被那些并不真正知道P(B|E) = P(E|B) * P(B) / P(E)实际上做什么的人背诵和吟诵。这篇短文将剖析贝叶斯定理,并展示它如何简化为我们都常用的直观分数。

首先,一些基本的概率背景。

信念是一种我们想要验证其正确或不正确的陈述,比如“一个人是男性”或“一个人有长头发”。证据是已知的关于信念主体的信息。最后,|竖线用作单词“给定…”。你会经常看到(B|E)是‘给定证据 e,概率信念 B 为真’

让我们看看下面这张假设高中的学生表。

我们想找出一个人是女性的概率(信念)给定长发(证据)。这可以表示为(female|long hair)。即使没有这个定理,这也很容易计算,很直观。我们只需要用留长发的女性人数除以留长发的总人数,这就是350/400=0.875

探究一下我们为什么会有这种直觉是值得的。因为我们知道这个人有长头发,所以我们在“长头发”一栏中查找,并在该类别中分成两类(男性或女性)。那么,我们的公式就是女性和留长发的人除以所有留长发的人。

因此,我们可以自信地说,如果你有一头长发,你有 87.5%的机会在假设的高中成为女性。

让我们用贝叶斯定理来解决这个问题——你会意识到它只是把这种直觉用严格的数学术语表达出来!

a - i的变量名将用于表示不同的量。记得我们直观的公式是e/h,或者说是女性留长发的人数除以留长发的总人数。

贝叶斯公式说明如下:

P(B|E) = P(E|B)*P(B) / P(E)

这在我们的场景中转化为:

P(Female|Long Hair) = P(Long Hair|Female)*P(Female)/P(Long Hair)

让我们用变量来表示这些。例如,假设某人是女性,那么她留长发的概率是e/f,因为e代表留长发的女性数量,而f代表女性总数。P(Female)f/i,因为f是女性人数,i是总人数(男女)。

P(Female|Long Hair) = (e/f)*(f/i) / (h/i) = (e/f)*(f/i)*(i/h)

通过一些简单的代数运算,我们认识到(e/f)*(f/i)导致(e/i),并且(e/i)*(i/h)等于(e/h)——我们的直观公式!

所以,贝叶斯定理实际上是一种迂回的方式来表达一个简单的想法。至少在我们的分数操作上下文中,P(B)只是作为一座桥梁来抵消倒数。所以,当使用贝叶斯定理计算P(B|E)时,你实质上是在计算以下内容:

# items that are B and E / total # items that are E

如果通过使用其他更容易获得的概率来直接计算这个概率是困难或棘手的,贝叶斯定理对于计算这个概率是有用的。当计算三个独立的概率比计算一个主要概率更便宜时,这可能是有用的。

在更高的层次上,人们可能倾向于说,贝叶斯定理揭示了概率本质中的关系。在一个较低的层次上,也许是更实际的层次上,贝叶斯定理是一种巧妙的方法,可以绕过用其他概率和链乘法直接计算一个概率。

[## 统计学和数据科学中最基本也是最有争议的争论

频繁主义者-贝叶斯之争

towardsdatascience.com](/the-most-fundamental-and-controversial-debate-in-statistics-and-data-science-e8dd1bad737a)

所有图片由作者创作。

贝叶斯定理:朴素贝叶斯算法背后的思想

原文:https://towardsdatascience.com/bayes-theorem-the-idea-behind-naive-bayes-algoritm-f7068834a4d7?source=collection_archive---------63-----------------------

你认为今天会下雨吗?

在 Unsplash 上由 Ed Leszczynskl 拍摄的照片

今天下雨的可能性有多大?在你回答之前,你考虑的事情可能是季节,城市的一般天气情况,以及天空中云的密度。考虑到这些迹象,你可以做出一个有根据的猜测。贝叶斯定理遵循类似的方法。根据贝叶斯定理,事件的概率是根据先验知识或相关的给定条件来描述的。

贝叶斯定理建立在概率和条件概率的基础上。因此,最好先了解一下这些主题。

概率只是指事件发生的可能性,通常取 0 到 1 之间的值(0 和 1 包括在内)。事件 A 的概率被表示为 p(A) ,并且被计算为期望结果的数量除以所有结果的数量。例如,当你掷骰子时,得到小于 3 的数字的概率是 2 / 6。期望结果的数量是 2 (1 和 2);总结果数为 6。

条件概率是在与事件 A 相关的另一事件已经发生的情况下,事件 A 发生的可能性。假设我们有 6 个蓝色球和 4 个黄色球放在两个盒子里,如下图所示。我让你随机选一个球。得到蓝球的概率是 6 / 10 = 0,6。

假设球是从盒子 A 中取出的,选择黄色球的概率是多少?这是一个条件概率,表示为 P(黄色|方框 A)。

在介绍贝叶斯定理之前,还有一个概念需要学习。联合概率是两个事件一起发生的概率,表示为 p(A 和 B) 。对于独立的事件,联合概率可以写成:

p(A 和 B) = p(A)。p(B)…………(1)

假设我掷骰子,掷硬币。得到 1 和正面的概率是:

(1 / 6).(1/2) = 1/12 = 0.08

为了使计算正确,事件必须独立于。抛硬币的结果对掷骰子的结果没有任何影响,所以这些事件是独立的。让我们也举一个依赖事件的例子。我从一副牌中选了一张,又从同一副牌中选了第二张。在第二次选择中某一特定观察值肯定受第一次选择影响的概率。在非独立事件的情况下,等式 1 无效。应该稍微修改一下,使其适用于任何两个事件:

p(A 和 B) = p(A)。p(B | A)…………(2)

等式(1)是等式(2)对于独立事件的特例,因为如果事件 B 和事件 A 独立, p(B|A) = p(B)。

贝叶斯定理

我们将从任意两个事件的联合概率是可交换的这一事实开始。那就是:

p(A 和 B) = p(B 和 A)…………(3)

从等式 2 中,我们知道:

p(A 和 B) = p(A)。p(B|A)

p(B 和 A) = p(B)。p(A|B)

我们可以将等式 3 改写为:

p(一)。p(B|A) = p(B)。p(A|B)

用 p(B)除两边给出了贝叶斯定理:

因此,根据贝叶斯定理,假设事件 B 已经发生,则事件 A 的概率可以使用事件 A 和事件 B 的概率以及假设事件 A 已经发生的事件 B 的概率来计算。

贝叶斯定理是如此的基本和普遍,以至于一个叫做“贝叶斯统计”的领域存在了。在贝叶斯统计中,作为证据的事件或假设的概率开始起作用。因此,先验概率和后验概率因证据而异。

朴素贝叶斯算法是通过结合贝叶斯定理和一些朴素假设而构造的。朴素贝叶斯算法假设特征是相互独立的,并且特征之间没有相关性。然而,现实生活中并非如此。这种特征不相关的天真假设是这种算法被称为“天真”的原因。

使用连续变量的贝叶斯 A/B 测试——包括 Python 代码

原文:https://towardsdatascience.com/bayesian-a-b-testing-with-continuous-variables-including-python-code-133b74c7bd20?source=collection_archive---------23-----------------------

本文讨论如何在您的数字实验方法中实现贝叶斯估计,特别关注连续的、非离散的度量的计算

作者创建的数字(弗兰克·霍普金斯,2020)

当你网站上的一个实验被暂停时,有可能你的 MVT 平台没有捕捉到接受或拒绝你的假设所需的所有信息。如果是这种情况,您可能需要对原始实验和用户级数据进行某种形式的事后显著性测试。

如果您正在处理一个连续的指标,即在给定测量的最低点和最高点之间取值范围无限的变量,那么 T 检验可能是您最熟悉的。然而,T 检验和更广义的频率主义方法在实际应用中可能存在缺陷。首先,frequentist 方法依赖于预先确定的功效分析来计算所需的样本量,并随后计算在比较组间差异之前实验应该运行的期望时间长度。这种推理形式的问题是,它无法在动态或特别的环境中工作,如果没有达到样本大小的要求,您可能会得到不重要的发现。如果你在你的站点或平台上实现了相对较大的样本规模,这可能不是一个大问题,但是你仍然会有麻烦,必须将你的发现翻译给利益相关者(和 frequentist 统计,这是有问题的)。值得注意的是,试图向非技术人员解释置信区间和 p 值可能是棘手的,p 值经常(错误地)被解释为实验条件“优于”对照的概率。幸运的是,贝叶斯等价于这种形式的显著性测试为我们提供了这些信息,这在商业环境中非常有用,因为这正是利益相关者想要知道的信息。

本文将讨论一种由 Kruschke (2013) 描述的被称为 BEST 的方法(贝叶斯估计取代 T 检验),该方法使用预先确定的模型参数结合我们已知的(后验)数据,使用马尔可夫链蒙特卡罗模拟和【pymc 3】生成可信的后验分布。虽然我建议阅读 Kruschke 的学术论文(链接如上)来温习传统的零假设显著性检验(NHST)和贝叶斯方法(细致入微且不“用户友好”)之间的各种技术细节和差异,但本文将重点关注如何使用 Python 中的几行代码实现最佳方法。将提供有用的计算,这些计算产生的结果容易被利益相关者理解。

演练(使用 Python 代码)

首先,您需要导入所有必要的包和模块进行分析:

import pandas as pd
import requests
import numpy as np
import pymc3 as pm
import scipy.stats as stats
import matplotlib.pyplot as plt
%matplotlib inline
from IPython.core.pylabtools import figsize
import theano.tensor as tt
from scipy.stats.mstats import mquantiles

接下来,您将需要导入您的数据(应该是用户级别的),但是我随机生成了一些数据,以便强调分析所需的正确数据结构和一些分析的基本概念。我模拟了每个变体的每个浏览器的页面浏览量( pvs_pb )指标:

rng **=** np.random.default_rng()df_control **=** pd.DataFrame(rng.integers(1, 100, size**=**(500, 1)), columns**=**['pvs_pb'])df_control['variant'] **=** 'control'df_variant **=** pd.DataFrame(rng.integers(60, 120, size**=**(500, 1)), columns**=**['pvs_pb'])df_variant['variant'] **=** 'variant'df **=** df_control.append(df_variant)

虽然在贝叶斯推理中,通常不需要具有相同权重的组,但是检查控制和实验条件之间的流量是否均匀分布可能是有用的:

df.groupby(['variant']).count()

您还可以检查我们的 pvs_pb 指标的平均值,在我们执行完推理测试后可以参考这些平均值:

df.groupby([‘variant’]).mean()

现在,您可以在我们的模型中使用这些关于我们数据的信息来进行模拟。注意,在这个例子和 Kruschke 的方法中,数据都是用一个 Student-t 分布来描述的。虽然这并不总是合适的,但是利用 t 分布可能比正态分布更能提供信息,因为它将数据描述为与尾部相关;这通常是从 web 数据推断出的连续指标的情况(即“超级用户”经常存在)。值得指出的是,如果下面的代码不适用于您的数据,您可能需要调整它。

为了描述 Student-t 分布,您需要均值 μ (正态分布)和标准差 σ (均匀分布)输入。您还需要指定自由度 ν,,它遵循一个移位的指数分布。数据的正态性由 ν调节。如果 ν = > 30,则计算出的分布接近正态分布;因此,1/29 的值被用作正常阈值。

现在,您可以分别为控件和变体创建两个单独的数据框:

control = df[(df['variant'] == 'control')]
variant = df[(df['variant'] == 'variant')]

设置集合平均值、标准差和自由度参数:

pooled_mean = np.r_[control.pvs_pb, variant.pvs_pb].mean()
pooled_std = np.r_[control.pvs_pb, variant.pvs_pb].std()
variance = 2 * pooled_std with pm.Model() as model_1:
    mu_A = pm.Normal("mu_A", pooled_mean, sd = variance)
    mu_B = pm.Normal("mu_B", pooled_mean, sd = variance)
    std_A = pm.Uniform("std_A", 1/100, 100)
    std_B = pm.Uniform("std_B", 1/100, 100)
    nu_minus_1 = pm.Exponential("nu-1", 1.0/29)

将模型拟合到您的数据中,并运行 MCMC 模拟来计算一系列后验分布:

with model_1:
    obs_A = pm.StudentT("obs_A", mu = mu_A, lam = 1.0/std_A**2, nu = nu_minus_1+1, observed=control.pvs_pb)
    obs_B = pm.StudentT("obs_B", mu = mu_B, lam = 1.0/std_B**2, nu=nu_minus_1+1, observed=variant.pvs_pb)
    start = pm.find_MAP()
    step = pm.Metropolis(vars =[mu_A, mu_B, std_A, std_B, nu_minus_1])
    trace_1 = pm.sample(25000, step = step)
    burned_trace_1 = trace_1[10000:]

现在,您可以看到组均值的后验分布:

 control_mean = burned_trace_1[‘mu_A’]
variant_mean = burned_trace_1[‘mu_B’]
plt.hist(control_mean, bins = 40, label=r’Posterior distribution of $\mu_{Control}$’, color = ‘grey’)
plt.hist(variant_mean, bins = 40, label=r’Posterior distribution of $\mu_{Variant}$’, color = ‘orange’)
plt.title(‘Posterior distributions for each respective group mean’)
plt.legend()
plt.show()

图一。两组平均值的后验分布。作者创作(弗兰克·霍普金斯,2020 年)

标准偏差:

control_std = burned_trace_1[‘mu_A’]
variant_std = burned_trace_1[‘mu_B’]
plt.hist(control_std, bins = 40, label=r’Posterior distribution of $\sigma_{Control}$’, color = ‘grey’)
plt.hist(variant_std, bins = 40, label=r’Posterior distribution of $\sigma_{Variant}$’, color = ‘orange’)
plt.title(‘Posterior distributions of standard derivation derived from PyMC3’)
plt.legend()
plt.show()

图二。两组标准差的后验分布。作者创作(弗兰克·霍普金斯,2020 年)

如你所见,两组之间不存在后验分布的重叠。但是,我们现在可以绘制组间差异的后验分布图:

difference = variant_mean - control_mean # Difference of the meanshdi = pm.stats.hpd(difference, hdi_prob = 0.95) # The 95% HDI interval of the differencerope = [30,35] #the ROPE regionplt.hist(difference, bins=50, density=True, label='Differene of the mean salaries', color = 'orange')
plt.title('Posterior distribution of the the difference of the means')
plt.vlines(hdi[0], 0,0.6, linestyle='--', color='red', label='HDI')
plt.vlines(hdi[1], 0, 0.6, linestyle='--', color='red')
plt.vlines(rope[0], 0, 0.6, linestyle='--', color='black', label='ROPE')
plt.vlines(rope[1], 0, 0.6, linestyle='--', color='black')
plt.title('Posterior distribution of the the difference of mean for Metric 1')
plt.legend(loc='upper right')
plt.show()

图 3。两组平均值的后验分布。作者创作(弗兰克·霍普金斯,2020 年)

图 3 为我们提供了一些可用于分析的有用参数。首先,我们用红线表示我们的最高密度区间(HDI ),它包含了具有最大概率密度的点(即比通过参数之外的样本更有可能的样本)。尽管不要与置信区间混淆,这个 95%的区间可以调整到任何给定的范围。第二,我们有我们的实际等效区域(ROPE ),它是实验组之间抽样差异的预定范围。该价值可能由利益相关者和/或分析师事先确定,并且将是我们希望超过的价值。为了实现这一点,我们希望整个绳索范围都落在我们的 95% HDI 之外,因为这是最有可能出现结果的地方。

最后,我们可以绘制实验条件之间相对差异的后验分布:

rel_difference = 100 * (variant_mean-control_mean)/variant_mean prob = len(rel_difference[rel_difference > 40])/len(rel_difference)
plt.hist(rel_difference, bins=50, density=True, label=’Relative differene of the mean metric’, color = ‘orange’)
plt.title(‘Posterior distribution of the the relative difference of mean values’)
plt.vlines(40, 0,0.5, linestyle=’ — ‘, color=’red’, label=’HDI’)
print(f”The probability that the variant performed 40% greater than the control is: {round(prob*100,2)}%”)
plt.show()

图 4。对照和变异体之间的相对差异。作者创作(弗兰克·霍普金斯,2020 年)

The probability that the variant performed 40% greater than the control is: 99.57%

从上面的代码和图 4 中可以看出,我们还可以确定变体以某个阈值击败对照的概率。可以确定,变异比基线大 40%的概率约为 99.6%。这个门槛可以被改变为对你的涉众/更广泛的团队实际上重要的任何东西,这在商业环境中是无价的,而使用频繁的方法是无法达到的。

值得考虑的是,由于 MCMC 模拟执行的工作量很大,在比本文中显示的数据集更大的数据集上执行这种分析可能计算量很大。因此,不要在你的实验中定期进行这种分析,而是在头脑中有一个时间周期来进行分析。此外,如果您希望定期执行此操作,请考虑使用 pandas 对数据样本进行分析。

总之,最佳分析是 T-检验的一个非常有用的贝叶斯替代方法,它提供了一些宝贵的信息和输出,这些信息和输出在进行频率分析时是不容易得到的。使用 PYMC3 这样的软件包,生成可信的后验样本是一个相当简单的过程,前提是您认真选择先前的输入和用于建模的分布。

贝叶斯决策理论

原文:https://towardsdatascience.com/bayesian-decision-theory-81103a68978e?source=collection_archive---------3-----------------------

在 Unsplash 上由 Clark Van 拍摄的照片

哦!如果不是模式,我们是什么?

令人惊讶的是,我们如何轻松地完成如此多复杂的任务,却又渴望教机器如何去做。对我们来说,区分苹果和橘子是很简单的事情,但是把这个教给一个只懂“0”和“1”的人是很麻烦的。现在,使用一个非常熟悉的数学公式,看似艰巨的任务可以变得容易(或者至少可行)。但问题是: 公式直观吗?

贝叶斯定理就像概率论的 E=mc 。每个人都看过了,但只有少数人理解它。如果我不得不为它选择一个形容词,那就是革命性的!它改变了我们以前摆弄的许多应用程序的进程。但是在深入算法的细节之前,我们需要先理清我们的基本原理。

附注:为了解释这些概念,为了简单起见,但不失一般性,我举了二进制分类的例子。

边际概率、条件概率和联合概率

边缘概率

当我们通常谈论事件的概率时,我们关心的是边际概率。换句话说,它是不考虑任何其他因素/事件/环境的事件发生的概率。基本上,你“边缘化”了其他事件,因此得名。用 P(A) 表示,读作“A 的概率”。

条件概率

条件概率是指一个事件的发生完全或部分受到其他事件的影响。换句话说,它是当一个事件 B 已经发生时,另一个事件 A 发生的概率。用 P(A|B) 表示,读作“给定 B 的概率”。

联合概率

当我们对两个不同事件的同时发生感兴趣时,计算联合概率。它也经常被称为两个事件相交的概率。用 P(A,B) 表示,读作“A 和 B 的概率”。

概率和可能性

可能性和概率之间有一个非常微妙的区别,也许这就是为什么人们经常认为它们相似,如果不是相同的话。

要了解它们之间的区别,我们首先需要了解什么是模型,更具体地说,是统计模型。

模型可以被看作是理解和描述数据的过程、关系、等式或近似值中的任何一个。

考虑下图:

这可能是一个模型,因为它为我们提供了关于我们的数据看起来如何的“描述”。我们可以在上图中看到特征(x 和 y)之间的关系,即特征之间的变化。

现在,如果我试图用一个数学公式来近似T2,我会得到:

y = 1.3055 * x - 5.703

绘制时给出:

这个等式也是一个模型,因为它给出了数据的更具体的描述(更具体地说是特征之间的关系)。

许多统计学致力于确定一个模型是数据的好的还是坏的近似。

既然我们有了统计模型背后的直觉,我们就可以解决可能性和概率之间的差异。

每当我们计算随机过程中某一事件的概率时,它取决于我们用来描述我们的过程的 模型 的参数。也就是说,是过程的观察结果, θ 是描述底层模型的参数。那么我们感兴趣计算的 概率P(O|θ) 表示,即“给定用于描述过程的模型的参数,特定结果的概率”。****

但是我们很少会事先知道 θ 的值。我们简单地观察 O ,然后目标是得出 θ 的估计,这将是给定观察结果 O 的一个合理选择。我们对参数的最佳估计是给出发生结果 的最大概率的值。然后我们可以将*函数 定义为 L(θ|O) 即它是 θ 函数对于给定的集合的结果,然后用它来寻找参数 的最优值*

图形解释:

考虑如上图所示的高斯分布。设 X 为相关过程的随机变量。然后,

**Probability of the random variable equals x given the underlying model is Gaussian:
P(X = x | *N*(μ, σ)) = 0 # For continous random variable, but can be closely approximated to the dark pink areaProbability of the random variable to be greater than x given the underlying model is Gaussian::
P(X > x | *N*(μ, σ)) = (Pink + Dark Pink) areaLikelihood of the random variable at x:
L(*N*(μ, σ) | X = x) = y**

简单来说,可能性是模型(在这种情况下,高斯分布)的参数(在这种情况下, μσ )描述结果的程度(在这种情况下, X )。具有最优参数的模型最大化了概率。另一方面,概率是对于所用模型的给定参数,事件或观察的可能性有多大。

既然我们已经学习了基本原理,我们终于可以深入到贝叶斯决策理论的工作中了。

贝叶斯决策理论

贝叶斯决策理论是解决模式分类问题的基本统计方法。它被认为是理想的模式分类器,并经常被用作其他算法的基准,因为它的决策规则自动最小化其损失函数。现在可能没什么意义,所以等一下,我们会解开的。

它假设决策问题是以概率的形式提出的,并且所有相关的概率值都是已知的。

贝叶斯定理

贝叶斯定理的推导;

**We know from the conditional probability:P(A|B) = P(A, B) / P(B)
=> P(A, B) = P(A|B) * P(B) ... (i)Similarly,
P(A, B) = P(B|A) * P(A) ... (ii)From equation (i) and (ii):P(A|B) * P(B) = P(B|A) * P(A)
=> P(A|B) = [P(B|A) * P(A)] / P(B)**

对于分类的情况,假设:

  • A ≡ ω(条目的性质或类别的状态)
  • b≦x(输入特征向量)

代入后我们得到:

**P(ω|**x**) = [P(**x**|ω) * P(ω)] / P(**x**)which becomes:P(ω|**x**) = [p(**x**|ω) * P(ω)] / p(**x**)because,* P(ω|**x**) ≡ called the **posterior**, it is the probability of the predicted class to be ω for a given entry of feature (x). Analogous to P(O|*θ*), because the classis the desired outcome to be predicted according to the datadistribution (model). Capital 'P' because **ω** is a discrete random variable.* p(**x**|ω) ≡ class-conditional probability density function for the feature. We call it ***likelihood*** *of* ω with respect to x, a term chosen to indicate that, other things being equal, the category (or class) for which it is large is more "likely" to be the true category. It is a function of parameters within the parameteric space that describes the probability of obtaining the observed data (x). Small 'P' because **x** is a continous random variable. We usually assume it to be following Gaussian Distribution.* P(ω)≡ a **priori** **probability** (or simply prior) of class ω. It is usually pre-determined and depends on the external factors. It means how probable the occurence of class ω out of all the classes.* p(**x**) ≡ called the **evidence**, it is merely a scaling factor that guarantees that the posterior probabilities sum to one. p(x) = sum(p(x|ω)*P(ω)) over all the classes.**

因此,最终我们得到以下等式来构建我们的决策规则:

贝叶斯分类公式

决策规则

上面的等式是我们决策理论的支配公式。规则如下:

对于每个样本输入,它计算其后验概率,并将其分配给与后验概率的最大值对应的类别。

数学上它可以写成:

贝叶斯决策规则

现在你知道贝叶斯规则是什么,它是如何工作的,你可能想知道这里有什么特别的?这个算法非常出色,因为它的优雅和接近理想的结果。贝叶斯决策理论被认为是其他分类算法的基准。

根据贝叶斯定理,没有理论是完美的。相反,它是一项正在进行的工作,总是要接受进一步的完善和测试。

让我们试着理解为什么贝叶斯的分类器是最好的分类器!**

**(假设贝叶斯决策理论要求的所有假设都为真)

损失函数

{ ω 1、 ω 2、ω3、…、ωc }c 范畴和 {通过一个动作,我指的是所有可能决策中的一个特定决策,例如,一个动作可以是将一个输入特征向量分配给类别(以下称为类别 3),另一个动作可以是将一个输入分配给类别 7**

我们可以将损失函数( λ )概括如下:

可以这样理解:

λ 是当其真实类别为 ω j 时,将特征向量分配给类别 ω i 所产生的损失。换句话说,它是在采取行动 α 将一个输入分配给类 ω i 时遭受的损失,而该输入本应在类 ω j 中。

例如,在二进制分类的情况下,如果我们采取行动将输入特征向量分类到类别 1 中,而它本应在类别 2 中,我们招致以下损失:

如果I=j,那么我们得到的损失值比备选情况下的小,因为它对应于正确的决策。

但是,如果接受这是我们为自己的损失寻求的全部功能,那就太天真了。可以看出,损失是有条件的,它取决于在任何特定时间所关注的类。为了更好地理解它,请回答这个问题:

损失是否与输入特征向量的分类概率无关?

如果你认为答案是肯定的,让我解释一下为什么答案是否定的!

*Say the posterior probability of class 2 is more than that of class 1 for a given feature vector, i.e.,*

*and let's consider an action of assigning x to class 1.Since **λ** is the loss associated with one particular action (here, assigning x to class 1) we get its two values:*

现在这两个损失值相等吗?

没有后验概率的知识,你无法回答这个问题。您需要知道一个类成为真实类的可能性有多大,以便计算与之相关的损失。这将我们的损失修改如下:

贝叶斯分类器的损失函数

这就解释了为什么叫条件损失。

λ可以是任何合适的函数。例如,它可以是对称零一函数。**

决策的预期损失:

现在,我们可以在所有类别中定义特定决策(或行动)的预期损失。也就是说,我在采取特定行动后会招致的损失,以及它将如何受到所有类别而不仅仅是真实类别的“存在”的影响。

条件风险

我们可以通过选择最小化条件风险的行动来最小化我们的预期损失。我们现在将展示这个贝叶斯决策过程实际上提供了最佳性能。

我们的问题是找到一个最小化整体风险的决策规则。一个通用的决策规则是一个函数 α(x) ,它告诉我们对每一个可能的观察值( x )采取哪一个动作。更具体地说,对于每一个 x 决策函数 α(x) 假设其中一个 aα 1、α2、*α**3、…, 因为条件风险与动作 α i 相关联,并且因为决策规则指定了动作,所以总体风险由下式给出:***

所有观察的行动的总体风险

如果选择 α(x) 使得每个行动的条件风险最小化,那么整体风险也将最小化。这证明了贝叶斯决策规则。

也许举个例子会更好…

*Let **λ** be symmetrical or zero-one loss function,*

零一损失

那么条件风险就变成了:

贝叶斯分类器的决策规则自动最小化与动作相关的条件风险。

这就是贝叶斯的决策理论!

我希望这篇文章能帮助你理解这个算法。请随意在下面留下您的建议和疑问。如果你喜欢,就砸了那个按钮!

如果你心中有任何主题,并希望在这里看到它,请在评论区留下它。这将是我的荣幸!

一路平安!

(除缩略图外,所有图片均由作者创作。)

贝叶斯高斯混合模型(没有数学)使用推断。网

原文:https://towardsdatascience.com/bayesian-gaussian-mixture-models-without-the-math-using-infer-net-7767bb7494a0?source=collection_archive---------20-----------------------

Infer 中高斯混合模型编码的快速实用指南。网

(图片作者)

T 他的帖子提供了贝叶斯高斯混合模型的简要介绍,并分享了我在微软的 Infer.NET概率图形模型框架中构建这类模型的经验。由于熟悉 k-means 聚类和 Python,我发现学习 c#、inference 和概率推理中使用的一些底层贝叶斯原理很有挑战性。也就是说,Python 程序员有一个集成的方法。NET 组件和服务,我将在后续文章中介绍。我希望这篇文章的内容可以节省你的时间,消除理论可能带来的任何威胁,并展示所谓的基于模型的机器学习方法的一些优势。请遵循Infer.NET 文档 中提供的指南来设置 Infer.NET 框架。

贝叶斯高斯混合模型构成了一种无监督学习的形式,并且可用于为诸如聚类、数据压缩、离群点检测或生成分类器之类的任务拟合多模态数据。每个高斯分量通常是具有均值向量和协方差矩阵的多元高斯分量,但为了说明起见,我们将考虑一个不太复杂的单变量情况。

我们首先从单变量高斯分布中采样数据,并使用 Python 代码将数据存储在一个. csv 文件中:

这是我们数据的样子:

左图:从均值=5、精度=10 的高斯分布中采样的 100 个数据点的图。右图:数据的直方图。(作者图片)

让我们暂时假设我们不知道产生我们的数据集的分布。我们将数据可视化,并假设数据由高斯分布生成。换句话说,我们希望高斯分布能够充分描述我们的数据集。然而,我们不知道这个高斯分布的位置或范围。高斯分布可以通过均值和方差参数被参数化。有时使用平均值和精度在数学上更容易,因为精度只是方差的倒数。我们将坚持精度,因为直觉上精度越高,高斯分布的范围就越窄(或更“确定”)。

首先,我们感兴趣的是找到这个高斯分布的均值参数,并将假装我们知道它的精度的值(我们设置精度=1)。换句话说,我们认为我们的数据是高斯分布的,我们不确定它的均值参数是多少,但我们确信它的精度=1。我们能从数据中学习它的平均参数吗?我们需要第二个高斯分布来描述第一个高斯分布的平均值。这被称为共轭先验。以下是学习未知均值的图形表示(使用参数均值=0,精度=1 的高斯先验):

用于学习已知精度的数据均值的贝叶斯网络。(图片作者)

请注意图中平均随机变量和已知精度之间的差异。下面是 Infer 中的代码。网络:

后验高斯(高斯均值):高斯(4.928,0.009901)

在只观察了 100 个数据点后,我们现在有了一个后验高斯分布,它描述了我们数据的平均值 x 。我们从数据中学到了一些有用的东西!但是等等…我们也可以了解一下它的精度,不必假装它固定在 1。怎么会?我们对均值做同样的事情,并在精度上放置一个分布(通过用类似于我们的“不确定性”的东西来代替它,有效地消除了我们“无限确信”它等于 1 的知识)。精度的共轭先验是伽马分布。我们通过在新的精度随机变量上包括伽马分布(先前参数 shape=2,rate=1)来更新模型的图形表示:

学习数据的均值和精度的贝叶斯网络。(作者图片)

下面是 Infer 中的代码。网络:

后验高斯(高斯均值):高斯(4.971,0.001281)
后验伽马(高斯精度):伽马(52,0.1499)【均值=7.797】

到目前为止,我们的假设概述如下(参考下图):

  1. 数据 x 呈高斯分布,
  2. 我们假装完全知道它的精度(精度=1)并通过使用高斯先验来学习它的平均值,
  3. 然后,我们不再假装“知道”精度,而是通过使用伽玛先验来学习精度。请注意下图中的不同之处。由于我们施加的限制,第一个模型无法学习精度(显示为绿色)。
  4. 未知平均值和未知精度的参数为高斯-伽马分布。从 100 个数据点中学习后,这些参数的先验分布(以红色显示)更新为后验分布(在右下图中以蓝色显示)。

左图:已知精度(绿色)和未知精度(蓝色)的高斯分布。右图:平均值和精度参数的先验高斯-伽马分布(红色)和从 100 个数据点学习后的后验分布(蓝色)。(作者图片)

推断。NET 可以在设置 ShowFactorGraph = true 时生成我们模型的因子图。因子节点显示在黑色方框中,变量节点显示在白色方框中。这个图显示了我们的数据 x (底部观察到的变量数组),它依赖于一个高斯因子。高斯因子取决于一个叫做均值的随机变量和一个叫做精度的随机变量。这些随机变量分别依赖于高斯先验和伽马先验。两个先前分布的参数值显示在图表的顶部。

推断。我们模型的净生产因子图。(图片由作者通过推断生成。网)

为了了解高斯分布的均值和精度,我们做了一些假设。在 MBML 中,学习和推理本质上是一样的。你可以在这里 阅读更多关于支持的 inference 推理技术及其差异 。本文中的例子使用了变量消息传递 (VMP)。为了学习更复杂的分布(即,多模态密度),该模型不够有表现力,应该通过引入更多假设来扩展。准备好混合东西了吗?

正如生活中的许多事情一样,如果一个高斯是好的,那么更多应该更好,对吧!首先,我们需要一个新的数据集,并使用本文开头介绍的 Python 代码。唯一不同的是我们设置 p=[0.4,0.2,0.4]。这意味着 80%的数据应从第一个和第三个高斯分布中采样,而 20%的数据应从第二个高斯分布中采样。数据可以可视化:

左图:从三个不同的高斯分布中采样的 100 个数据点的图,平均值=[1,3,5],精度=[10,10,10]。右图:数据的直方图。(作者图片)

为了创建模型,我们将使用 k =3 数量的高斯分布,也称为分量,来拟合我们的数据集。换句话说,我们有三个 均值 随机变量和三个 精度 随机变量需要学习,但是我们还需要一个潜在随机变量 z 。该随机变量具有离散分布,并负责选择最能描述其相关观察值 x 的分量。例如,如果观察到的₀最好用高斯分量一来解释,则应该将更多的权重分配给状态一 z ₀。在本例中,我们将假设知道所有数据点的混合权重,并使用统一分配(w₀=1/3、w₁=1/3、w₂=1/3),如下图所示。

学习已知混合权重的混合高斯分布的贝叶斯网络。(图片作者)

下面是 Infer 中的代码。网络:

后验高斯(高斯均值):高斯(1.008,0.003284)
后验伽马(高斯精度):伽马(25.43,0.2547)
后验高斯(高斯均值):高斯(5.045,0.004061)
后验伽马(高斯精度):伽马(17,0.4812)【均值= 8.178】
后验高斯(高斯均值):高斯(2

从数据中学习到的三个高斯分布/分量绘制如下:

已知权重设置为 1/3 的三个学习到的高斯分布及其总和。(图片作者)

等等…我们声称完全了解组件重量,但如果我们不知道呢?我们也可以从数据中学习权重吗?确实,但是我们需要一个先验!狄利克雷分布是离散/分类分布的共轭先验。下图已更新,显示了未知权重的随机变量及其附带的 Dirichlet 先验。

学习混合权重未知的混合高斯分布的贝叶斯网络。(图片作者)

下面是 Infer 中的代码。网络:

后验高斯(高斯均值):高斯(0.9955,0.003208)
后验伽马(高斯精度):伽马(25.04,0.2663)【均值= 6.667】
后验高斯(高斯均值):高斯(2.719,0.02028)
后验伽马(高斯精度):伽马(10.1,0.3655)【均值= 3.693】
后验高斯(高斯均值):高斯(4.55

从数据中学习到的三个高斯分布/分量及其学习到的权重如下所示:

三个学习到的高斯分布和未知权重的和= {0.45,0.16,0.37}。(图片作者)

总之,我们从假设我们的第一个数据集可以用高斯分布充分描述开始了这个旅程。我们能够利用 inference 的观测数据和 VMP 推断来学习高斯分布的均值参数和精度参数。我们的第二个数据集使用了更复杂的生成机制,这需要一个更具表现力的模型。然后,我们引入了一个潜在变量 z 和狄利克雷先验,这允许我们学习混合高斯分布及其混合权重。所有步骤均使用 Infer.NET 以 c#代码提供,可在此 处 访问。

对于更正式的治疗,推荐以下书籍和链接:

  1. https://dotnet.github.io/infer/InferNet101.pdf
  2. 模式识别和机器学习。斯普林格,2006 年。
  3. 机器学习:一个概率的观点。麻省理工学院出版社,2012 年。
  4. http://mbmlbook.com/index.html
  5. http://www.jmlr.org/papers/volume6/winn05a/winn05a.pdf
  6. https://en.wikipedia.org/wiki/Exponential_family

这篇文章中没有提到的重要概念:

  1. 适当的先验参数,
  2. 可识别性,
  3. 预测分布,
  4. 打破对称,
  5. 消息传递(变分消息传递(VMP)和期望传播(EP)),
  6. 逆协方差矩阵的 Wishart 共轭先验,
  7. 奥卡姆剃刀和狄利克雷先验。

带 Pyro 的贝叶斯广义线性模型

原文:https://towardsdatascience.com/bayesian-generalized-linear-models-with-pyro-b80bc08d7b75?source=collection_archive---------12-----------------------

照片由负空间从像素拍摄

实践教程

使用线性模型和 Pyro 预测房价,实现完全透明的方法

面对预测或分析数据项目时,最常见的“第一攻击线”之一是广义线性模型(GLMs),最常见的是线性或逻辑回归。

GLMs 试图将响应变量 y 建模为特征的线性组合 X 的函数。线性组合的原因主要是为了便于解释;我们希望不仅能够很好地预测 y ,而且能够解释每个特征对我们反应的影响。

因此,我们通常指定 GLM 作为我们的响应,它是如下特征和系数的组合:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

其中 f 是我们的线性组合的函数,系数用希腊字母 β 表示

虽然像sklearn这样的库提供了丰富多样的回归模型,但是它们有一个主要的缺点,那就是它们创建了 β 的点估计,而没有考虑不确定性。也就是说,虽然我们可以找出该系数最可能的值,但我们不会估计该系数的其他值的可能性有多大。其他软件包如statsmodels提供了一些不确定性的度量,但是是在一系列分析师可能无法验证(或了解)的隐含假设下提供的。

在本文中,我们将讨论如何利用 PyTorch 和 Pyro 来生成 GLM 模型,这些模型创建参数和预测的不确定性估计,并通过一组非常明确的假设来实现。

采用 Scikit-learn 的线性回归

我们将从探索一个来自sklearn的简单线性回归开始,看看它在一个内置数据集上的表现,即加州住房数据集。

我们将从导入所有需要的库开始:

现在,让我们导入住房数据集,并探索其功能:

>>> Data shape is (20640, 8)
>>> Target shape is (20640,)

许多库中的基本线性回归模型假设响应正态分布在预测平均值周围。但是,一般来说房价不会呈正态分布。在这个数据集中,价格的分布也是不正常的,它更接近于一个伽马分布(实际上,我们不会总是直接从数据中获得,但可能必须查看残差,但这个简单的替代方案在我们的情况下是有效的)。因此,如果我们能够建立模型,将这一点考虑在内,那就太好了。

首先,让我们探索一下sklearn线性回归对这些数据的表现。我们可以将数据分为训练集和测试集,以估计我们的算法将如何工作:

>>> (16512, 8) (16512,)
>>> (4128, 8) (4128,)

让我们来拟合我们的线性回归:

>>> beta_intercept: -3664645.74
>>> beta_MedInc: 44223.44
>>> beta_HouseAge: 944.77
>>> beta_AveRooms: -11532.16
>>> beta_AveBedrms: 66340.59
>>> beta_Population: -0.16
>>> beta_AveOccup: -411.33
>>> beta_Latitude: -41808.42
>>> beta_Longitude: -43108.51

让我们定义一个函数来绘制我们的预测和持续测试集的真实值:

我们的数据中有一些观察结果是经过审查的。也就是说,他们的标签似乎是 50 万美元以上的房子。我们可以定义另一个函数,它只画出未被删除的点:

虽然这种方法可以产生令人满意的结果,但它有几个主要缺点:

  • 首先,线性模型通常忽略价格来自伽玛分布的事实。它对每个点的期望值的计算是基于来自正态分布的平均值。
  • 第二,对于每个系数,我们只能得到其最可能值的点估计。然而,我们可能对考虑不确定性的范围感兴趣。例如,我们可能想知道每增加一间卧室,价格上涨的幅度是多少。

为了解决这些问题,我们可以使用 Pyro 和 PyTorch 来构建我们自己的线性模型,这将解决刚才提到的所有痛点。

用 Pyro 重建线性模型

首先,让我们尝试用 Pyro 复制简单线性回归的结果。这将让我们直观地了解不同的火焰元素是如何工作的:

首先,我们将在 Pyro 中定义我们的模型。Pyro 模型被定义为函数(实际上它们被定义为可调用的,但最简单的可调用是函数)。该函数将接受我们的特征𝑋、我们的目标𝑦,以及更容易命名先验的特征名称:

本质上,我们在这里所做的是将我们的线性回归定义为以下参数的线性组合

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

然而,与传统的线性回归不同,我们将每个β系数以及误差项定义为一个分布,而不是单个值。也就是说,对于每个系数,我们可以问,在给定我们观察到的数据的情况下,该系数可以假设的可能值的范围是什么。我们给每一个发行版起了一个名字(例如“beta_intercept”),以便以后参考。

我们必须定义每个系数的先验。先验是我们对这一价值的“最佳猜测”。我们选择的优先顺序是:

使用https://www.codecogs.com/latex/eqneditor.php准备的配方

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

这些不是非常有用的先验知识,但它们通常用于回归系数和误差项。

需要注意的重要一点是,在构建模型时,我们必须明确这些选择。也就是说,我们必须清楚什么是系数值、误差项以及预测值周围值的分布的合理先验。

一旦先验被定义,我们可以要求 Pyro 通过 MCMC 采样器的魔力将它们更新为越来越好的猜测:

>>> Sample: 100%|██████████| 3100/3100 [22:45,  2.27it/s, step size=7.72e-04, acc. prob=0.955]>>> Inference ran for 22.75 minutes

如果您对这里发生的事情感兴趣,我建议您查看我以前的文章,其中探讨了使用 MCMC 方法优化单个参数。

我们可以使用.summary()方法研究 MCMC 采样器为每个系数找到的估计值:

>>> mean    std   median    5.0%   95.0% n_eff r_hat
 beta_intercept   1.58   0.01    1.58   1.56   1.59   9.48  1.21
    beta_MedInc   1.96   0.02    1.96   1.93   1.98   2.83  2.28
  beta_HouseAge   0.80   0.09    0.80   0.68   0.93   2.41  3.00
  beta_AveRooms  -1.88   0.02   -1.87  -1.90  -1.86   2.56  2.53
 beta_AveBedrms   1.63   0.01    1.64   1.61   1.65   4.59  1.45
beta_Population  81.19  18.19   87.50  71.45  87.91   9.00  1.13
  beta_AveOccup  -0.56   0.01   -0.56  -0.57  -0.55   4.61  1.97
  beta_Latitude  -0.57   0.04   -0.58  -0.63  -0.52   2.39  3.23
 beta_Longitude  -2.37   3.30   -2.12  -7.11   1.80   2.44  2.82
      sigma  15062.73 460.33 14933.00 14908.34  15057.25  12.98 1.09

Number of divergences: 0

这些看起来不太对…平均值似乎与sklearn回归发现的点估计值非常不同。

让我们从采样器中获取单个样本,并将它们转换成数据帧(它们作为字典返回)。我们可以获取每个分布的平均值作为系数点估计,然后为我们的数据点计算一组预测。然后,我们可以将它们与我们已知的房价值进行比较:

让我们绘制结果并计算我们预测的𝑅值:

那看起来像一场灾难!发生了什么事?

让我们定义一个函数,当给定一个系数数据帧时,它将为我们画出系数的分布:

那些情节看起来不像是融合了。

对于这个问题,MCMC 方法很难处理不同尺度的数据。当我们的特征和目标被缩放时,它们工作得更好。让我们通过数据缩放来探索相同方法的性能

扩展我们的数据

我们将使用来自sklearn的标准缩放器来缩放我们的 X 和 y 数据。标准缩放器将缩放 X 轴上的每个要素,使其平均值为 0.0,标准差为 1.0。为此,它将采用每个变量的平均 x̅和标准差𝑠

这意味着,不是试图在原始数据上找到一组系数

使用 https://www.codecogs.com/latex/eqneditor.php配制的配方

我们将在缩放后的数据上找到一组系数:

使用 https://www.codecogs.com/latex/eqneditor.php配制的配方

在哪里

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

也就是说,y 被缩放到 0–1 之间,X 的列已经标准化。

>>> Sample: 100%|██████████| 3100/3100 [05:27,  9.46it/s, step size=1.71e-02, acc. prob=0.926]>>> Inference ran for 5.46 minutes

我们的算法现在运行得更快了,但如果我们恢复算法找到的系数,这些将是缩放数据的系数。我们希望将它们转换回未缩放的数据,这样我们就可以问这样的问题:“房子里每多一间卧室,对价格会有什么影响?”

幸运的是,我们可以操纵我们的方程来检索未缩放数据的系数。我们从原始方程开始

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

我们展开每一部分:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

然后,我们可以将等式重新排列如下:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

忆及

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

我们最终可以将公式改写如下:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

我们可以创建一个函数来执行从缩放数据到未缩放数据的系数处理

然后,在我们再次从字典中检索系数之后,我们只对检索到的系数使用该函数:

我们来对比一下预测结果:

这些值似乎更接近于通过sklearn的线性回归得到的值。

看起来我们的表现不相上下。这些分布看起来接近于我们从 scikit-learn 获得的值。我们还得到了每个系数的概率分布,这样我们就可以看到我们找到的值的置信度。

然而,我们实际上可以使用 Pyro 做得更好!回想一下,我们看到我们的房价不是正态分布,而是遵循伽玛分布。我们可以修改代码以在模型中反映出来。

使用伽马分布改进我们的预测

为了更好地反映房屋分布,我们可以对目标值采用伽玛分布。与由其平均值和标准偏差定义的正态分布不同,伽马分布由两个正参数定义,即形状和比率。

当构建非正态分布的模型时,我们需要使用一个链接函数,它会将我们参数的线性组合转换为分布的期望值或平均值。我们还想知道平均值和分布参数之间的关系。幸运的是,对于伽马分布,这被定义为:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

然而,如果形状和速率参数都是正的,这意味着平均值也必须是正的。我们需要确保我们的链接函数能够捕捉到这一点。因此,我将对线性方程使用以下链接函数:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

或者

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

熟悉statsmodels包的读者会知道它有一个 GLM 模块(关于statsmodels GLMs 的更多细节,我推荐这篇文章),它可以通过使用statsmodels.genmod.families.family.Gamma族和statsmodels.genmod.families.links.log链接函数来对这里提出的关系进行建模。然而,出于本文的目的,我想展示在贝叶斯框架中重现这一功能的过程。

有趣的是,为了恢复未缩放数据的系数,除了常数之外,数学计算非常相似。请记住:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

而且

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

我们可以发现我们的方程可以写成:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

或者

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

让我们定义我们的模型,但是现在使用伽马分布:

你会注意到我们的代码略有不同,但我们仍然在计算我们的 X 数据和我们的系数的线性组合,只是现在我们取该组合的exp来获得我们的数据点的平均值。我们还对速率参数进行采样,并使用平均值和速率来计算适当的形状参数。

给定我们的形状和速率参数,我们可以定义一个伽马分布,并要求 Pyro 优化我们的系数和速率参数,以便建立一个最有可能基于我们的数据的模型。

让我们优化这个新模型,看看结果:

>>> Sample: 100%|██████████| 3100/3100 [11:08,  4.64it/s, step size=1.47e-02, acc. prob=0.930]>>> Inference ran for 11.14 minutes

我们也可以从这个采样器中获取系数。但是,这一次我们要稍微区别对待y_max的值。

让我们通过计算预测值并将其与观测值进行比较来比较该模型的性能

我们如何解释这些系数?

嗯,他们现在用一个系数来修改我们的价格。回想一下,我们的等式现在是:

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

这相当于

使用https://www.codecogs.com/latex/eqneditor.php制备的配方

所以x_1每增加一个单位,房价就会增加e^{x_1}倍。

例如,beta_AvgRooms的平均值约为 0.007,因此每增加一个房间,房价平均会增加 e^0.007 = 1.007 的系数(因此,如果一栋房子的价格为 250,000 美元,增加一个房间将使其价值为 251,756 美元)。

这两个模型之间的其他参数似乎在定性上一致,但采用伽马分布的模型为我们提供了对未知数据的更好预测。

然而,仍然存在运行时间的问题。一般来说,如果我们想在合理的时间内进行推理,就不得不求助于变分推理的方法。

更快的 SVI 运行时间

Pyro 实现了随机变分推理(SVI ),以加快推理速度。在 SVI 方法中,我们不是试图直接从后验分布中取样,而是简单地优化一些预定义分布的参数,以匹配我们的观察数据。

例如,我们可以选择将所有系数和比率表示为正态分布。通过这种方式,SVI 只需找到每个正态分布的适当均值和标准差,使其尽可能与我们的数据一致。

>>> iter: 0, normalized loss:5.28
>>> iter: 250, normalized loss:-0.64
>>> iter: 500, normalized loss:-0.68
>>> iter: 750, normalized loss:-0.68
>>> iter: 1000, normalized loss:-0.68
>>> iter: 1250, normalized loss:-0.69
>>> iter: 1500, normalized loss:-0.69
>>> iter: 1750, normalized loss:-0.68
>>> iter: 2000, normalized loss:-0.68
>>> iter: 2250, normalized loss:-0.69
>>> iter: 2500, normalized loss:-0.69
>>> iter: 2750, normalized loss:-0.69
>>> iter: 3000, normalized loss:-0.69
>>> iter: 3250, normalized loss:-0.68
>>> iter: 3500, normalized loss:-0.69
>>> iter: 3750, normalized loss:-0.68
>>> iter: 4000, normalized loss:-0.68
>>> iter: 4250, normalized loss:-0.69
>>> iter: 4500, normalized loss:-0.68
>>> iter: 4750, normalized loss:-0.68>>> Inference ran for 0.74 minutes

从 SVI 样本中获取结果比从 MCMC 样本中获取结果要复杂一些,因为样本返回的是一个具有梯度的张量字典,并且它还返回了一个名为obs的附加关键字,该关键字与我们的系数分析无关(它是一组对训练数据的估计)。

我们开始吧。我们现在可以使用 Pyro 构建定制的 GLMs,使用 MCMC 采样方法或 SVI 优化方法。

Pyro 的一个重要特性是它迫使作者非常明确地说明他们的假设和他们对数据生成过程的理解。这对于在进行任何建模之前促进对数据的深入探索非常有用,有助于更深入地理解所有重要因素。

如需本文的 Colab 笔记本版本,请访问此链接

结果摘要

在完成了这个博客的笔记本版本之后,我开始描绘我观察到的运行时和性能结果。通过运行相同的代码 40 次,每次都有不同的训练/测试分割,我能够对我在本文中展示的结果有信心。

就 R 性能而言,伽玛分布始终优于正态分布模型,如下图所示。

使用 Plotly 准备的图像

值得注意的是,线性回归模型(sklearn的线性回归)的 R 值中明显的高标准偏差,以及在缩放数据并采用 MCMC 方法后产生的模型是单次训练/测试分割的结果,这导致了数据系数的严重错误估计。基于伽马分布的方法更适用于误导性的训练/测试分割。

此外,我还分析了每种方法的运行时间,结果如下图所示:

如您所见,虽然sklearn的线性回归始终优于所有其他方法,但采用基于 SVI 的方法是一种相对较快的解决方案,它结合了自定义指定 GLM 的灵活性和许多问题所需的快速运行时间。

此外,如果我们愿意,我们也可以编写我们自己的自定义指南,使用系数的正态分布以外的分布。

总的来说,我们可以看到 Pyro 提供了一套丰富的方法来为不同的问题建立线性模型,它结合了概率规划中涉及的明确性和最近成为焦点的可解释性。我希望这篇文章能为希望利用即将到来的概率编程语言的分析师和科学家提供很好的指导。

贝叶斯分层建模(或者“autoML 还不能取代数据科学家的更多原因”)

原文:https://towardsdatascience.com/bayesian-hierarchical-modeling-or-more-reasons-why-automl-cannot-replace-data-scientists-yet-d01e7d571d3d?source=collection_archive---------8-----------------------

从频率主义到贝叶斯主义

贝叶斯网络允许对变量之间的因果关系进行建模,弥补数据提供的信息的不足。

阿丽娜·格鲁布尼亚在 Unsplash 上的照片

在本文中,我们将使用一个为 python 开发的概率编程 pymc3 。对贝叶斯方法在基本统计学中的效率和 pymc3 的初步介绍可以在这里的和那里的中找到。****

S 自 2018 年初以来,自动化机器学习已经成为数据科学中最时尚的话题之一。仅举几个例子,亚马逊的 Sagemaker 或谷歌 AutoML 现在对大多数数据科学家来说都是可访问的,以至于一些人倾向于认为探索和理解数据不再是建立机器学习模型的必要条件。

AutoML 的承诺可以这样总结:

高度自动化允许非专家利用机器学习模型和技术,而不需要首先成为特定领域的专家。

推理很简单;不再需要专业知识,只需将数据交给 AutoML 算法,在测试固定数量的预定义模型后,它会返回最好的一个。**

但是这里有一个问题… **AutoML 算法忽略了最佳对我们来说意味着什么,而仅仅是试图最小化经验误差**。仍然需要知识和专业技能来理解这个误差真正意味着什么,以及它在多大程度上不同于我们实际上希望最小化的误差。**

我们应该考虑什么样的误差度量?

1.经验误差

给定 n 个数据点,经验误差由下式给出

对于特征 xi 和目标 yi 的所有可观测值上的特定函数 fn,其中 V 表示损失函数。

它通常通过交叉验证或训练/测试过程来计算。缺少协变量和目标之间的一些联系将产生偏差,常常导致欠拟合/过拟合,并最终导致更高的测试/交叉验证误差。

数据科学家(以及 autoML 引擎)常常错误地只考虑这一点。

2.泛化误差

泛化误差(也称为样本外误差 r)是一种衡量算法能够多准确地预测先前未见过的数据的结果值的方法。其定义如下:****

对于特征 x 和目标 y 的所有可能值上的特定函数 fn,其中 V 表示损失函数,ρ(x,y)是 x 和 y 的未知联合概率分布

显然,在训练我们的模型时,它通常是我们希望最小化的。不幸的是,它不能直接从数据中计算出来,不像经验数据那样仅仅是对前者的估计。

有了足够多的高质量数据,我们就可以交换这些数据。现在想象一下,在训练时只有部分信息可用,或者根本没有足够的数据,就像机器学习中经常出现的情况一样。然后,我们的模型将在不同的分布 ρ(x,y) 上进行训练,该分布不同于稍后运行的分布,因此,经验误差将偏离广义误差。

有偏差的数据导致有偏差的经验误差。

我们已经可以看出这是一个多么大的问题:经验误差不再估计期望的数量,而是我们唯一可以从数据中计算出来的。我们需要确保它在某种程度上仍然是可靠的。这是人类专业知识发挥作用并展示其全部潜力的地方。

同样,当变量之间的关系明确时,参数方法比非参数方法更受青睐,来自研究领域的知识通过显式建模一些相关性来弥补数据信息的不足。

我们的模型从部分或截断分布中推断得越好,经验和泛化误差就越接近。

3.混杂误差

"相关性并不意味着因果关系."

所有数据科学家都至少听过这句话一次,但事实证明,在实际建模时,只有少数人真正意识到其中的含义。因果关系的话题实际上大多数时候都被忽略了,有时是错误的,有时是合理的,但很少是故意的。

  • A 混杂因素 是与协变量和利益结果都有因果关系的变量。作为一个因果概念,它不能用相关性来描述。

因果图:混杂因素 W 影响因变量 Y 和自变量 X

由混杂因素产生的误差不能用传统的统计方法完全测量,因为它本身不是统计误差。

有人可能会争辩说,当经验误差很低,甚至是泛化误差时;那么我们不应该关心我们的模型是利用了真正的因果关系还是虚假的相关性。在某些情况下这可能是真的,但是除非我们明确知道为什么,否则这种情况不应该被忽视。

一个令人困惑的例证:辛普森悖论

By Pace~svwiki —自己的作品,CC BY-SA 4.0,https://commons.wikimedia.org/w/index.php?curid=62007681

辛普森悖论由 Edward Simpson 在 1951 年和 George Udny Yule 在 1903 年描述,是一个悖论,当数据被分割成单独的组时,统计趋势出现,但当组被组合时,趋势发生逆转。

当因果关系被忽略时,通常在存在混杂变量(这里用不同的颜色组表示)的情况下观察到。

辛普森悖论对机器学习的影响是,当涉及到决策时,我们可以选择应该考虑哪些数据来采取行动,是聚合还是分割?

不幸的是,答案通常不能从数据本身推断出来。事实上,根据变量之间的因果关系,对于完全相似的值,我们可以有不同的答案 **。真正的误差来源于数据本身之外,最终测试或交叉验证误差有多低并不重要。除非我们能够首先正确地对环境建模,否则我们无法避免做出完全错误的决策。******

空间混杂和贝叶斯分层建模

我们现在将通过一个具体的例子来说明在分层依赖的具体情况下如何处理这种情况。

通常,数据科学家必须处理地理数据,这些数据的缺点是不容易被经典的机器学习模型利用。位置要素通常具有很高的基数,并且经常是不平衡的。然而,很明显,模型的参数会因地区而异,取决于当地的变量,但仍然密切相关,因为它们对不同地方的相同现象进行建模。

通过下面的例子,我们将看到处理这种空间相关性的方法,从而最小化上面列出的所有类型的误差。

问题陈述

我们考虑估计孟加拉国避孕药具使用情况的问题,为此,我们使用了来自 1988 年孟加拉国生育率调查的数据。它包括分组在 60 个区的 1934 名妇女的子样本,变量定义如下:

  • 地区:每个地区的识别码。
  • LC:调查时存活儿童的数量。
  • 年龄:调查时妇女的年龄。
  • 城市:居住区域的类型。

我们将考虑 3 个具有不同特征的逻辑贝叶斯回归来模拟不同的可能方法。

1:合并测量

汇集模型

在这里,我们简单地通过不使用区域变量来忽略它的作用。结果是只有 4 个参数的简单逻辑回归,包括截距。位置不被看作是一个混杂因素,每个区域被假定为行为相似。

2:非池化回归

无池模型

对于每个地区,我们拟合了不同的逻辑回归,导致总共 60 个模型,每个模型有 4 个参数。即使我们假设不同地区的行为有所不同,我们也没有利用它们之间的相似性。

无泡 pymc 模型

3:贝叶斯分层逻辑回归

****贝叶斯分层建模是一种以多层编写的统计模型,使用贝叶斯方法估计后验分布的参数。子模型组合起来形成分层模型,贝叶斯定理用于将它们与观察到的数据相结合,并考虑所有存在的不确定性。⁴

我们假设当 𝛽 s 对于每个区域是不同的,如在未轮询的情况下,现在系数都共享相似性。我们可以通过假设每个单独的系数来自共同的组分布来对此建模:

随着

虽然在分析上很难处理,但概率规划允许我们使用马尔可夫链蒙特卡罗(MCMC)从后验分布中采样来计算所有参数的后验。【pymc3 再次提供了一个非常直观的方法来建模我们的网络和计算后验概率!

我们还可以轻松计算贝叶斯网络的图形表示:

逻辑回归的分层贝叶斯网络

参数估计

首先,让我们试着了解一下我们的模型之间的差异。

受https://docs.pymc.io/notebooks/GLM-hierarchical.html,的启发,我们可以可视化不同回归中回归参数的演变。

****

后验平均收缩率

我们显示了每个地区的非等级后验均值、等级后验均值和混合后验均值的系数。区一级可用的少量数据导致非 pool 后验分布很广,因此收缩效应非常重要,然而,分级模型中平均值之间的差异仍然很大,因为区与区之间的贝塔值在数量级上有所不同。****

模型误差

我们使用 ROC 曲线 (AUC) 下的 面积作为我们比较模型的误差度量。它可以被看作是我们的模型对随机选择的正类的评分高于随机选择的负类的概率。我们对此特别感兴趣,因为它的优点是不需要设置阈值来分配标签。****

为了测量性能,我们考虑了两个测试集,一个是按地区分层的测试集,一个是非分层的测试集。非分层测试集的使用更能代表泛化误差与经验模型误差显著不同的情况,因为训练集和测试集之间的区域特征分布会显著不同!

为了更好地代表真实性能,针对测试集采样的多个种子对测量值进行了平均。

结果

┌───────────────────┬────────┬──────────┬──────────────┐
│                   │ POOLED │ UNPOOLED │ HIERARCHICAL │
├───────────────────┼────────┼──────────┼──────────────┤
│ Train             │  0.632 │    0.818 │        0.726 │
│ Stratified Test   │  0.623 │    0.618 │        0.668 │
│ Unstratified Test │  0.634 │    0.603 │        0.663 │
└───────────────────┴────────┴──────────┴──────────────┘

分层集合

  • 正如训练和测试 AUC 之间的巨大差距所表明的,未规划的模型严重过度拟合。
  • 另一方面,集合模型有很强的偏向性,并且明显对数据进行了欠拟合。
  • 最后,通过利用参数地理相似性,我们的层次模型比其他模型表现得更好。

收缩效应为我们提供了一个改进的统计能力,也可以被看作是一个聪明的调整方法。

非分层的

一些地区只有极少数的个体可以训练,因此,对于未规划的模型,这些地区的非分层测试误差变得更大。部分汇集考虑了参数之间的相似性,为低密度区提供来自其他区的信息,同时保持其特殊性。

因此,对于非分层测试集,模型之间的差异甚至更加显著,向我们展示了其泛化能力更大,因为性能几乎不受分层策略的影响。

= > 当我们有多组我们期望具有相似性的测量时,多级分层贝叶斯模型优于基本方法。

将这种贝叶斯方法与其他经典的数据预处理方法(区域变量的不同编码)或算法(梯度推进、随机森林等)进行比较会很有趣。).

结论

  • AutoML 还不能取代数据科学家,因为它不能从实际业务目标中区分经验误差度量,也不能正确建模协变量和目标之间的依赖关系。
  • 专家们仍然需要理解数据并正确地模拟问题。为此,他们可以使用一系列数学和信息工具,包括 pymc3 库和贝叶斯分层模型,从而可以在分层结构数据的常见情况下轻松建模和计算分布

[1]:维基百科贡献者。“自动化机器学习。”维基百科,免费百科。维基百科,免费的百科全书,2020 年 2 月 18 日。网络。2020 年 3 月 1 日。

[2,3]:维基百科贡献者。(2020 年 2 月 22 日)。泛化错误。在维基百科,免费百科。2020 年 3 月 1 日 16:40 从https://en.wikipedia.org/w/index.php?检索 title = Generalization _ error&oldid = 942140633

[4]:维基百科贡献者。“贝叶斯分层建模。”维基百科,免费百科。维基百科,免费百科,2019 年 12 月 12 日。网络。2020 年 3 月 1 日。

参考

  • 因果关系:模型、推理和推论,剑桥大学出版社(2000 年,2009 年第二版)。国际标准书号0–521–77362–8。
  • https://docs.pymc.io/notebooks/GLM-hierarchical.html
  • n . m . huq 和 j . Cleland,1990 年。1989 年孟加拉国生育率调查(主要报告)。达卡:国家人口研究和培训研究所
  • 空间自相关:麻烦还是新范例?生态学。1993;74:1659–1673.

贝叶斯超参数优化:神经网络、张量流、相预测示例

原文:https://towardsdatascience.com/bayesian-hyper-parameter-optimization-neural-networks-tensorflow-facies-prediction-example-f9c48d21f795?source=collection_archive---------12-----------------------

自动调整神经网络的超参数(学习率、密集层和节点数以及激活函数)

这项工作的目的是优化神经网络模型超参数,以根据测井曲线估计相类。我将在本文中包含一些代码,但对于完整的 jupyter 笔记本文件,您可以访问我的【Github】

注意:如果你是 TensorFlow 的新手,杰夫·希顿会详细介绍它的安装。

在机器学习中,模型参数可以分为两大类:
1- 可训练参数:如训练算法学习到的神经网络中的权值,且用户不干预过程,
2- 超参数:用户可以在训练操作前设置,如学习率或模型中的密集层数。
如果您手动尝试,选择最佳超参数可能是一项繁琐的任务,如果您处理两个以上的参数,几乎不可能找到最佳超参数。
一种方法是将每个参数分成一个有效的均匀范围,然后简单地让计算机循环参数组合并计算结果。这个方法叫做网格搜索。虽然是机器做的,但会是一个耗时的过程。假设您有 3 个超参数,每个超参数有 10 个可能的值。在这种方法中,您将运行 10 个神经网络模型(即使有合理的训练数据集大小,这项任务也是巨大的)。
另一种方法是随机搜索方法。事实上,它不是使用有组织的参数搜索,而是遍历参数的随机组合,寻找优化的参数。您可能会估计,对于较大的超参数调整,成功的几率会降低到零。

Scikit-Optimize,skopt,我们将在这里使用它来完成相估计任务,它是一个简单而高效的库,用于最小化昂贵的噪声黑盒函数。贝叶斯优化构建了另一个参数搜索空间模型。高斯过程就是这些模型中的一种。这将生成模型性能如何随超参数变化而变化的估计。

正如我们在图中看到的,真正的目标函数(红色虚线)被噪声(红色阴影)包围。红线显示 scikit optimize 如何对超参数(一维)的搜索空间进行采样。Scikit-optimize 使用高斯过程(绿线)填充样本点之间的区域,并估计真实的真实适合度值。在低样本或缺乏样本的区域(如两个红色样本之间的图片左侧),存在很大的不确定性(红色和绿色线条之间的巨大差异导致绿色阴影区域的巨大不确定性,如两个标准差的不确定性)。在这个过程中,我们要求一组新的超参数来探索更多的搜索空间。在最初的步骤中,它以稀疏的精度进行,但是在后来的迭代中,它集中在采样点更符合适应度函数和真实目标函数的地方(图中的波谷区域)。
要了解更多信息,您可以参考 Scikit 优化文档。

资料回顾 康瑟尔格罗夫气藏位于堪萨斯州。从这个碳酸盐储层中,有九口井可用。从每半英尺的岩心样本中研究岩相,并与井位的测井数据相匹配。特征变量包括来自电缆测井测量的五个变量和来自地质知识的两个地质约束变量。更多详情请参考此处。对于数据集,您可以从这里下载。这七个变量是:

  1. GR :这种电缆测井工具测量伽马辐射
  2. ILD_log10 :这是电阻率测量
  3. PE :光电效应测井
  4. δφ:φ是岩石物理学中的孔隙度指标。
  5. PNHIND :中子和密度测井的平均值。
  6. NM_M :非海相-海相标志
  7. RELPOS :相对位置

九个离散相(岩石类别)是:

  1. (SS) 陆相砂岩
  2. (CSiS) 非海相粗粉砂岩
  3. (FSiS) 非海相粉细砂岩
  4. (SiSH) 海相粉砂岩和页岩
  5. (MS) 泥岩(石灰岩)
  6. (WS) 瓦克斯通(石灰岩)
  7. (D) 白云石
  8. (PS) 细粒砂岩(石灰岩)
  9. (BS) 叶状藻障石(石灰岩)

将数据集读入 python 后,我们可以保留一口井的数据作为盲集,以备将来模型性能检查之用。我们还需要将相数转换成数据集中的字符串。参考完整的笔记本。

df = pd.read_csv(‘training_data.csv’)

blind = df[df['Well Name'] == 'SHANKLE']
training_data = df[df['Well Name'] != 'SHANKLE']

特征工程 相类应转换为虚拟变量,以便在神经网络中使用;

dummies = pd.get_dummies(training_data[‘FaciesLabels’]) 
Facies_cat = dummies.columns 
labels = dummies.values                   *# target matirx**# select predictors* 
features = training_data.drop(['Facies', 'Formation', 'Well Name',                                 'Depth','FaciesLabels'], axis=1)

预处理(制作标准)

当我们处理各种各样的数据时,为了使网络有效,让我们将它标准化。

**from** **sklearn** **import** preprocessing
scaler = preprocessing.StandardScaler().fit(features)
scaled_features = scaler.transform(features)**#Data split
from** **sklearn.model_selection** **import** train_test_split
X_train, X_test, y_train, y_test = train_test_split(
        scaled_features, labels, test_size=0.2, random_state=42)

超参数

在这项工作中,我们将使用 Tensorflow 中的深度学习从测井记录中预测相。我们可以为深度学习调整几个超参数。我将尝试找出以下各项的最佳参数:

  1. 学习率
  2. 密集层数
  3. 每层节点数
  4. 哪个激活功能:“relu”或 sigmoid

为了详细说明这个搜索维度,我们将使用 scikit-optimize(skopt)库。从 skopt 来看,实函数会为学习率定义我们喜欢的范围(下界= 1e-6,上界= 1e-1),并且会使用对数变换。层数(我们看起来在 1 到 5 之间)和每层的节点数量(在 5 到 512 之间)的搜索维度可以用 skopt 的整数函数来实现。

dim_learning_rate = Real(low=1e-6, high=1e-1, prior='log-uniform',
                         name='learning_rate')dim_num_dense_layers = Integer(low=1, high=10, name='num_dense_layers')dim_num_dense_nodes = Integer(low=5, high=512, name='num_dense_nodes')

对于激活算法,我们应该使用分类函数进行优化。

dim_activation = Categorical(categories=['relu', 'sigmoid'],
                             name='activation')

将所有搜索维度放在一个列表中:

dimensions = [dim_learning_rate,
              dim_num_dense_layers,
              dim_num_dense_nodes,
              dim_activation]

如果你已经为一个特定的项目进行了深度学习,并且手动找到了那个项目的超参数,你就知道优化有多难。您也可以使用自己的猜测(像我一样默认)来比较贝叶斯调优方法的结果。

default_parameters = [1e-5, 1, 16, ‘relu’]

超参数优化

创建模型

像 Tneseflow 开发的一些例子一样,我们也需要先定义一个模型函数。在定义了模型的类型(这里是顺序的)之后,我们需要在第一行引入数据维度(数据形状)。层数和激活类型是我们寻求优化的两个超参数。Softmax 激活应用于分类问题。那么另一个超参数是应该在 Adam 函数中定义的学习率。当我们处理分类问题(相预测)时,应考虑损失函数应为“分类 _ 交叉熵”来编译模型。

**def** create_model(learning_rate, num_dense_layers,
                 num_dense_nodes, activation):

    model = Sequential()

    model.add(InputLayer(input_shape=(scaled_features.shape[1])))

    **for** i **in** range(num_dense_layers):
        name = 'layer_dense_**{0}**'.format(i+1)

        *# add dense layer*
        model.add(Dense(num_dense_nodes,
                        activation=activation,
                        name=name))

    *# use softmax-activation for classification.*
    model.add(Dense(labels.shape[1], activation='softmax'))

    *# Use the Adam method for training the network.*
    optimizer = Adam(lr=learning_rate)

    *#compile the model so it can be trained.*
    model.compile(optimizer=optimizer,
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    **return** model

训练和评估模型

该功能旨在使用给定的超参数创建和训练网络,然后使用验证数据集评估模型性能。它返回数据集的适应值,即负分类精度。它是负的,因为 skopt 执行最小化而不是最大化。

@use_named_args(dimensions=dimensions)
**def** fitness(learning_rate, num_dense_layers,
            num_dense_nodes, activation):
    *"""*
 *Hyper-parameters:*
 *learning_rate:     Learning-rate for the optimizer.*
 *num_dense_layers:  Number of dense layers.*
 *num_dense_nodes:   Number of nodes in each dense layer.*
 *activation:        Activation function for all layers.*
 *"""*

    *# Print the hyper-parameters.*
    print('learning rate: **{0:.1e}**'.format(learning_rate))
    print('num_dense_layers:', num_dense_layers)
    print('num_dense_nodes:', num_dense_nodes)
    print('activation:', activation)
    print()

    *# Create the neural network with these hyper-parameters.*
    model = create_model(learning_rate=learning_rate,
                         num_dense_layers=num_dense_layers,
                         num_dense_nodes=num_dense_nodes,
                         activation=activation)

    *# Dir-name for the TensorBoard log-files.*
    log_dir = log_dir_name(learning_rate, num_dense_layers,
                           num_dense_nodes, activation)

    *# Create a callback-function for Keras which will be*
    *# run after each epoch has ended during training.*
    *# This saves the log-files for TensorBoard.*
    *# Note that there are complications when histogram_freq=1.*
    *# It might give strange errors and it also does not properly*
    *# support Keras data-generators for the validation-set.*
    callback_log = TensorBoard(
        log_dir=log_dir,
        histogram_freq=0,
        write_graph=**True**,
        write_grads=**False**,
        write_images=**False**)

    *# Use Keras to train the model.*
    history = model.fit(x= X_train,
                        y= y_train,
                        epochs=3,
                        batch_size=128,
                        validation_data=validation_data,
                        callbacks=[callback_log])

    *# Get the classification accuracy on the validation-set*
    *# after the last training-epoch.*
    accuracy = history.history['val_accuracy'][-1]

    *# Print the classification accuracy.*
    print()
    print("Accuracy: **{0:.2%}**".format(accuracy))
    print()

    *# Save the model if it improves on the best-found performance.*
    *# We use the global keyword so we update the variable outside*
    *# of this function.*
    **global** best_accuracy

    *# If the classification accuracy of the saved model is improved ...*
    **if** accuracy > best_accuracy:
        *# Save the new model to harddisk.*
        model.save(path_best_model)

        *# Update the classification accuracy.*
        best_accuracy = accuracy

    *# Delete the Keras model with these hyper-parameters from memory.*
    **del** model

    *# Clear the Keras session, otherwise it will keep adding new*
    *# models to the same TensorFlow graph each time we create*
    *# a model with a different set of hyper-parameters.*
    K.clear_session()

    *# NOTE: Scikit-optimize does minimization so it tries to*
    *# find a set of hyper-parameters with the LOWEST fitness-value.*
    *# Because we are interested in the HIGHEST classification*
    *# accuracy, we need to negate this number so it can be minimized.*
    **return** -accuracy
*# This function exactly comes from :Hvass-Labs, TensorFlow-Tutorials*

运行这个:

fitness(x= default_parameters)

运行超参数优化

我们已经检查了默认的超参数性能。现在我们可以检查 scikit-optimize 库中的贝叶斯优化。这里,我们使用 40 次运行作为适应度函数,尽管这是一个昂贵的操作,并且需要在数据集上小心使用。

search_result = gp_minimize(func=fitness,
                            dimensions=dimensions,
                            acq_func='EI', *# Expected Improvement.*
                            n_calls=40,
                            x0=default_parameters)

只是一些最后运行显示如下:

进度可视化

使用 skopt 的 plot_convergence 函数,我们可以在 y 轴上看到优化过程和找到的最佳适应值。

plot_convergence(search_result) 
*# plt.savefig("Converge.png", dpi=400)*

最佳超参数

使用 serach_result 函数,我们可以看到贝叶斯优化器生成的最佳超参数。

search_result.x

优化后的超参数依次为:学习速率、密集层数、每层节点数、最佳激活函数。

我们可以看到 40 次呼叫的所有结果,以及相应的超参数和适合度值。

sorted(zip(search_result.func_vals, search_result.x_iters))

有趣的一点是‘relu’激活功能几乎占主导地位。

情节

首先,让我们看看两个优化参数的 2D 图。在这里,我们为每层中的学习速率和节点数量的估计适应值制作了一个景观图。贝叶斯优化器建立了一个搜索空间的代理模型,并在这个维度而不是真正的搜索空间内搜索,这就是为什么它更快的原因。在图中,黄色区域较好,蓝色区域较差。黑点是优化器的采样位置,红星是找到的最佳参数。

**from** **skopt.plots** **import** plot_objective_2D
fig = plot_objective_2D(result=search_result,
                        dimension_identifier1='learning_rate',
                        dimension_identifier2='num_dense_nodes',
                        levels=50)
*# plt.savefig("Lr_numnods.png", dpi=400)*

点点:

  1. 代理模型可能是不准确的,因为它仅从对适应度函数的 40 个调用样本中构建
  2. 由于神经网络中的随机噪声和训练过程,每次重新运行优化时,图可能会发生变化
  3. 这是 2D 图,而我们优化了 4 个参数,可以想象 4 个维度。
*# create a list for plotting*
dim_names = ['learning_rate', 'num_dense_layers', 'num_dense_nodes', 'activation' ]fig, ax = plot_objective(result=search_result, dimensions=dim_names)
plt.savefig("all_dimen.png", dpi=400)

在这些图中,我们可以看到优化是如何发生的。贝叶斯方法试图在采样密度较高的点用先验信息拟合模型参数。如果学习率约为 0.003,密集层的数量为 6,每层中的节点数量约为 327,并且激活函数为“relu”,则将所有四个参数收集到 scikit 优化方法中将在本次运行中引入最佳结果。

用盲数据优化超参数评估模型

这里也需要同样的数据准备步骤。我们在这里跳过重复。现在我们可以用优化的参数做一个模型来看预测。

opt_par = search_result.x
 *# use hyper-parameters from optimization* 
learning_rate = opt_par[0]
num_layers = opt_par[1] 
num_nodes = opt_par[2] 
activation = opt_par[3]

创建模型:

**import** **numpy** **as** **np**
**import** **tensorflow.keras**
**from** **tensorflow.keras.models** **import** Sequential
**from** **tensorflow.keras.layers** **import** Dense, Activation
**from** **tensorflow.keras.callbacks** **import** EarlyStopping

model = Sequential()
model.add(InputLayer(input_shape=(scaled_features.shape[1])))
model.add(Dense(num_nodes, activation=activation, kernel_initializer='random_normal'))
model.add(Dense(labels.shape[1], activation='softmax', kernel_initializer='random_normal'))

optimizer = Adam(lr=learning_rate)

model.compile(optimizer=optimizer, loss='categorical_crossentropy',  metrics=['accuracy'])

monitor = EarlyStopping(monitor='val_loss', min_delta=1e-3, patience=20, 
                        verbose=1, mode='auto', restore_best_weights=**True**)

histories = model.fit(X_train,y_train, validation_data=(X_test,y_test),
          callbacks=[monitor],verbose=2,epochs=100)

让我们看看模型精度的发展:

plt.plot(histories.history['accuracy'], 'bo')
plt.plot(histories.history['val_accuracy'],'b' )
plt.title('Training and validation accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.savefig("accu.png", dpi=400)
plt.show()

训练和验证精度图显示,几乎在 80%的精度(迭代 10)之后,模型开始过度拟合,因为我们看不到测试数据预测精度的提高。

让我们用一个尚未见过的数据集(盲井)来评估模型性能。我们总是预测,如果数据集很小或者特征没有大到足以覆盖数据维度的所有复杂性,则机器学习模型使用盲数据进行预测的准确性会低于训练过程。

result = model.evaluate(scaled_features_blind, labels_blind)
print("**{0}**: **{1:.2%}**".format(model.metrics_names[1], result[1]))

预测盲井数据和绘图

y_pred = model.predict(scaled_features_blind) *# result is probability array*y_pred_idx = np.argmax(y_pred, axis=1) + 1
*# +1 becuase facies starts from 1 not zero like index*blind['Pred_Facies']= y_pred_idx

要绘制的函数:

**def** compare_facies_plot(logs, compadre, facies_colors):
    *#make sure logs are sorted by depth*
    logs = logs.sort_values(by='Depth')
    cmap_facies = colors.ListedColormap(
            facies_colors[0:len(facies_colors)], 'indexed')

    ztop=logs.Depth.min(); zbot=logs.Depth.max()

    cluster1 = np.repeat(np.expand_dims(logs['Facies'].values,1), 100, 1)
    cluster2 = np.repeat(np.expand_dims(logs[compadre].values,1), 100, 1)

    f, ax = plt.subplots(nrows=1, ncols=7, figsize=(12, 6))
    ax[0].plot(logs.GR, logs.Depth, '-g', alpha=0.8, lw = 0.9)
    ax[1].plot(logs.ILD_log10, logs.Depth, '-b', alpha=0.8, lw = 0.9)
    ax[2].plot(logs.DeltaPHI, logs.Depth, '-k', alpha=0.8, lw = 0.9)
    ax[3].plot(logs.PHIND, logs.Depth, '-r', alpha=0.8, lw = 0.9)
    ax[4].plot(logs.PE, logs.Depth, '-c',  alpha=0.8, lw = 0.9)
    im1 = ax[5].imshow(cluster1, interpolation='none', aspect='auto',
                    cmap=cmap_facies,vmin=1,vmax=9)
    im2 = ax[6].imshow(cluster2, interpolation='none', aspect='auto',
                    cmap=cmap_facies,vmin=1,vmax=9)

    divider = make_axes_locatable(ax[6])
    cax = divider.append_axes("right", size="20%", pad=0.05)
    cbar=plt.colorbar(im2, cax=cax)
    cbar.set_label((5*' ').join([' SS ', 'CSiS', 'FSiS', 
                                'SiSh', ' MS ', ' WS ', ' D  ', 
                                ' PS ', ' BS ']))
    cbar.set_ticks(range(0,1)); cbar.set_ticklabels('')

    **for** i **in** range(len(ax)-2):
        ax[i].set_ylim(ztop,zbot)
        ax[i].invert_yaxis()
        ax[i].grid()
        ax[i].locator_params(axis='x', nbins=3)

    ax[0].set_xlabel("GR")
    ax[0].set_xlim(logs.GR.min(),logs.GR.max())
    ax[1].set_xlabel("ILD_log10")
    ax[1].set_xlim(logs.ILD_log10.min(),logs.ILD_log10.max())
    ax[2].set_xlabel("DeltaPHI")
    ax[2].set_xlim(logs.DeltaPHI.min(),logs.DeltaPHI.max())
    ax[3].set_xlabel("PHIND")
    ax[3].set_xlim(logs.PHIND.min(),logs.PHIND.max())
    ax[4].set_xlabel("PE")
    ax[4].set_xlim(logs.PE.min(),logs.PE.max())
    ax[5].set_xlabel('Facies')
    ax[6].set_xlabel(compadre)

    ax[1].set_yticklabels([]); ax[2].set_yticklabels([]); ax[3].set_yticklabels([])
    ax[4].set_yticklabels([]); ax[5].set_yticklabels([]); ax[6].set_yticklabels([])
    ax[5].set_xticklabels([])
    ax[6].set_xticklabels([])
    f.suptitle('Well: **%s**'%logs.iloc[0]['Well Name'], fontsize=14,y=0.94)

运行:

compare_facies_plot(blind, 'Pred_Facies', facies_colors)
plt.savefig("Compo.png", dpi=400)

结论

在这项工作中,我们使用贝叶斯方法和名为 skopt 的 scikit-learn 库优化了超参数。这种方法优于随机搜索和网格搜索,特别是在复杂的数据集中。使用这种方法,我们可以摆脱手动调整神经网络的超参数,尽管在每次运行中,您将面临新的参数。

贝叶斯推理算法:MCMC 和 VI

原文:https://towardsdatascience.com/bayesian-inference-algorithms-mcmc-and-vi-a8dad51ad5f5?source=collection_archive---------9-----------------------

直觉和诊断

与机器学习(ML)的其他领域不同,贝叶斯 ML 要求我们知道输出何时不可信。当您定型一个回归或 xgboost 模型时,在给定设置和数据的情况下,可以从表面上接受该模型。使用贝叶斯 ML,不能保证输出是正确的。

贝叶斯工作流程可以分为三个主要部分:建模、推理和批评。即使我们已经编写了一个合理的概率模型,由于推理算法,无论是因为算法失败还是因为我们选择了一个不合适的算法,结果都可能是误导的。本文将解释每种算法的工作原理,讨论每种算法的优缺点,以及如何诊断它们的性能。

贝叶斯计算的主要目标是找到贝叶斯定理中分母的变通方法:

除了最简单的模型,这个积分是不可能计算的。推理算法是获得 p(θ|X)的方法,而无需对积分求值。

MCMC

马尔可夫链蒙特卡罗,顾名思义,使用必须满足某些条件的马尔可夫链来运行蒙特卡罗模拟,因此无论起点如何,我们总是以我们期望的平稳分布(后验分布)结束。

想象后验分布是某种丘陵地形。你想要探索地形,并在与土堆高度成比例的任何地点花费时间。需要注意的是,雾太大了,你什么也看不见。即使你站在山顶上,你也不知道与其他山相比,这是一座高的山还是一座矮的山。你可以知道你站在海拔 2 千米的地方,但是其他的山只有 1 千米高,还是有 5 千米高的山?只配备了一个测量高度的装置,你需要想出一个规则来实现你的目标。

马尔可夫链必须具有:

  • 遍历性 。你可以在有限的时间内从任何状态到达一个状态(因此可以回到你的初始状态)。没有确定的循环。
  • 明细平衡 。p(x|y)q(y) = p(y|x)q(x)

有些规则比其他规则更有效。实际上,大多数 MCMC 都是螺母(不掉头采样器),在需要时(主要是当参数离散时)加入一些 Gibbs。

吉布斯

假设我们要求 x 和 y 两个参数的后验分布,我们可以不受限制地从一个点跳到另一个点,也可以把每次跳跃分解成一个水平运动+一个垂直运动。这就是吉布斯的工作。我们举起双手说:我们不知道如何为前者制定规则,但我们可以为后者创造规则。

来源

吉布斯要求有条件的结合。我们逐一检查所有参数。顺序无所谓— 直观上(但不是真的),横+竖=竖+横。我们通过分析求解后验概率对每个参数进行采样,保持所有其他参数不变。

举个简单的例子,假设我们想估计正态分布的均值μ和精度λ = 1/σ。我们放置先验μN(0,1)和λγ(1,1)。那么条件后验概率是

我们希望在这两种条件后验抽样之间进行交替。下面的 R 代码展示了吉布斯采样在这个模型中是如何工作的:

library(ggplot2)num_sample <- 5000    # number of samples for Gibbs
burn_in <- 1000       # first n samples we discard
prior_mean <- 0       # the prior on mu
prior_precision <- 1  # the prior on mu
prior_shape <- 1      # alpha in prior for precision
prior_rate <- 1       # beta in prior for precision
num_obs <- 30         # size of our data
true_mean <- 3        
true_precision <- 0.25set.seed(9)
X <- rnorm(num_obs, true_mean, 1/sqrt(true_precision))
mu <- rep(NA, num_sample)
lambda <- rep(NA, num_sample)#initialize some values
mu[1] <- 0 
lambda[1] <- 1for(i in 2:num_sample){
  if(i %% 2){
    mu[i] <- rnorm(
      1, 
      mean = (prior_precision * prior_mean + lambda[i-1] * sum(X)) / 
        (prior_precision + num_obs * lambda[i-1]),
      sd = sqrt(1 / (prior_precision + num_obs * lambda[i-1]))
    )
    lambda[i] <- lambda[i-1]
  } else{
    mu[i] <- mu[i-1]
    lambda[i] <- rgamma(
      1,
      shape = prior_shape + num_obs / 2,
      rate = prior_rate + sum((X - mu[i])^2) / 2
    )
  }
}posterior <- data.frame(mu, lambda)[(burn_in+1):num_sample,]ggplot(posterior) +
  geom_point(aes(x = mu, y = lambda)) +
  geom_path(aes(x = mu, y = lambda), alpha = 0.3) +
  ggtitle('Gibbs sampling') +
  xlab(expression(mu)) +
  ylab(expression(lambda))ggplot(posterior) +
  geom_histogram(
    aes(x = mu, y = stat(count) / sum(count)),
    alpha = 0.5) +
  geom_vline(
    aes(xintercept = quantile(posterior$mu, 0.025)), 
    color = 'red') +
  geom_vline(
    aes(xintercept = quantile(posterior$mu, 0.975)), 
    color = 'red') +
  ylab('Relative frequency') +
  xlab(expression(mu)) +
  ggtitle(bquote('95% credible interval of ' ~ mu))ggplot(posterior) +
  geom_histogram(
    aes(x = lambda, y = stat(count) / sum(count)), 
    alpha = 0.5) +
  geom_vline(
    aes(xintercept = quantile(posterior$lambda, 0.025)), 
    color = 'red') +
  geom_vline(
    aes(xintercept = quantile(posterior$lambda, 0.975)), 
    color = 'red') +
  ylab('Relative frequency') +
  xlab(expression(lambda)) +
  ggtitle(bquote('95% credible interval of ' ~ lambda))

请注意老化设置。MCMC 有希望收敛到目标分布,但可能需要一段时间。根据经验,我们丢弃前 1000 个,因为这个链可能还没有到达目的地。

尝试更改这些值,以直观地了解后验行为。如果我们追踪运动的路径,我们会看到水平-垂直模式:

我们可以使用边际分布计算可信区间:

当你的模型是有条件共轭的时候,Gibbs 会比其他方法更好。例如,尝试在 LDA 上运行 NUTS 不起作用,因为对于离散的潜在变量没有梯度。然而,为 LDA 运行 Gibbs 采样器(相对而言)更快更容易。

大都市

Metropolis 算法着眼于贝叶斯定理,提出“我们能让分母互相抵消吗?”算法:

  1. 从某个随机的初始点θ开始。
  2. 从某分布 p(θ|θ)画出一个建议值θ
  3. 如果 p(X|θ)p(θ) > p(X|θ)p(θ),接受建议值。否则,以概率[p(X|θ)p(θ)] / [p(X|θ)p(θ)]接受建议值。
  4. 如果被接受,移动到新的地点。否则,原地不动。不管怎样,记录你的位置。
  5. 重复(2)、(3)和(4),重复设定的迭代次数。

看接受概率:

记住 p(X)是一个未知常数。因为我们的目标是在与后验密度成比例的点上花费时间,所以我们可以不计算 p(X)就这样做。

满足遍历性和细节平衡的最简单方法是从 N(θ,s)中采样θ*。对称连续分布就可以了。

Metropolis-Hastings (MH)将该算法推广到非对称建议分布,同时保持详细的平衡。仔细观察 MH 的验收规则,并将其与详细平衡的含义进行比较。

下面是一些 R 代码,看看 Metropolis 算法是如何工作的,在θ上使用 N(0,1)先验,并且已知 X ~ N(θ,1):

library(ggplot2)num_iter <- 2000
s <- c(0.1, 1, 10)set.seed(1)
x <- rnorm(10, 10, 1)
thetas <- list()for(i in 1:length(s)){
  theta <- rep(NA, num_iter)
  current_theta <- rnorm(1, 0, 10)
  for(j in 1:num_iter){
    proposed_theta <- rnorm(1, current_theta, s[i])
    accept_prob <- exp(
      dnorm(proposed_theta, 0, 1, log = TRUE) +
        sum(dnorm(x, proposed_theta, 1, log = TRUE)) -
        dnorm(current_theta, 0, 1, log = TRUE) -
        sum(dnorm(x, current_theta, 1, log = TRUE))
    )
    if(runif(1) < accept_prob){
      current_theta <- proposed_theta
      theta[j] <- proposed_theta
    } else {
      theta[j] <- current_theta
    }
  }
  thetas[[i]] <- cbind(1:num_iter, theta, rep(s[i], num_iter))
}thetas <- data.frame(do.call('rbind', thetas))
colnames(thetas) <- c('iter', 'theta', 's')
thetas$s <- factor(thetas$s)ggplot(thetas) +
  geom_line(aes(x = iter, y = theta)) +
  facet_grid(s~.)ggplot(thetas[thetas$iter > 1000,]) +
  geom_line(aes(x = iter, y = theta)) +
  facet_grid(s~.)

Metropolis 算法的一个问题是,它对我们选择的建议分布很敏感。使用不同的标准差会产生不同的结果:

正如你所看到的,链需要一些时间来达到它的目标分布。解析地说,我们知道后验概率应该是 N(0.92,0.09)。为了看得更清楚,我们应该丢弃老化期间的样本,比如前 1000 个样本:

如果我们使 s 非常小,比如说 0.01,那么即使在 1000 次迭代之后,该链也不会达到目标分布。另一方面,拥有一个大的 s 会导致非常参差不齐的转换,因为我们会拒绝大多数提议。最好的 s 介于 0.1 和 1 之间。我们需要通过反复试验来找到它,这可能会很麻烦。虽然我们不会使用 Metropolis,但获得 MCMC 对设置如何敏感的直觉很重要。

哈密尔顿/坚果

我在这里说的任何东西都比不上 McElreath 的精彩文章,所以我建议阅读动画和细节。基本思想是哈密顿蒙特卡罗(HMC)是一种物理模拟。你有一个球在某个地形上滚动,这个地形是负对数后验概率,被某个未知常数上移。对于二维正态分布,想象一下把它翻过来,你就得到一个碗。你用一个随机的动量向一个随机的方向轻弹这个球,过了一段时间后停下来,记录下它最后停在哪里。当总能量(势能+动能)与初始能量相差太大时,您拒绝该样本,表明您的模拟失败。斯坦称这些为“发散过渡”。

MH 在极高的维度上失败了,因为最终你会得到接近 0%的接受率。人类的直觉在高维空间会崩溃。我们的三维大脑可能会将高维多元正态分布想象成一个实心球,但由于测量的的集中度,它实际上是一个非常薄的球壳。如果我们把这个投影到 2D,它看起来会像一个甜甜圈,而不是一个圆。HMC 在甜甜圈上表现出色的事实意义深远。

大的步长导致不好的近似([源](http://Physics simulations have to approximate trajectories by discretizing the steps. If you check every 10 "seconds", then your simulated trajectory might differ too much from the actual trajectory. If you check every 0.00001 "seconds", then your simulation will take a long time to compute even a single trajectory even though it will be much more accurate. One major downside of HMC is the need to tune the settings of the simulation.))

物理模拟必须通过离散化步骤来近似轨迹。如果你每 10 秒检查一次,那么你的模拟轨迹可能与实际轨迹相差太多。如果你每 0.00001 秒检查一次,那么你的模拟将花费很长时间来计算一个单独的轨迹,即使它会更精确。你需要调整模拟设置,以获得良好的 HMC 结果。

螺母在预热阶段(而不是预烧阶段)自动为您调整设置通过防止 U 形转弯为您提供更好的样本。如果你没有查看上面链接的篇,建议现在就看。在这个时代,几乎没有理由用 MH 或 HMC 代替坚果。

也就是说,NUTS 仍然会遇到一些问题。

首先,它可能会卡在多模态后部的单一模式附近(再次参考文章)。您可以通过诊断来检测此问题(运行多个链!)然后要求 NUTS 获取更多的样本以更充分地探查后部。

第二,NUTS 每走一步都需要评估地形的坡度。计算梯度的成本非常高,我们必须使用整个数据集,所以它是不可伸缩的。

尼尔的漏斗(来源)

第三,它不能探索类似尼尔漏斗的东西。这是分层模型的一个特别退化的例子。您可以阅读 Stan 文档中的示例。本质上,y 是对数标度参数,用于模拟组间方差,而 x 是组均值参数。NUTS 学习单一步长,但这种地形需要不同的步长,这取决于球在漏斗上的位置。在宽部分中起作用的步长在窄部分中将不起作用,而在窄部分中起作用的步长将太慢地探索宽部分。

如果您看到太多的发散过渡,并且它们都发生在同一个区域,您就会发现这个问题。建模者需要重新参数化模型,以便 NUTS 可以发挥其魔力,可能通过找到(相对)不相关的参数化或重新调整数据以使参数在相同的范围内。对于固定效应模型,这是通过对预测矩阵进行 QR 分解来实现的。

题外话:重新参数化通常是加速计算的好主意。这样想:如果我们提供一个漂亮的碗状表面,球可以滚得到处都是。探索一根稻草更加困难。在没有发散转换的情况下,来自两种方法的样本应该是正确的,但是 QR 分解的运行时间可以快很多。

诊断学

R 帽子

R hat 看起来可疑地像方差分析中的 F 统计量,所以这是我给出的直觉。如果所有的链都是相同的,那么“F 统计”应该是 1。

然而,反过来就不成立。Rhat 有可能是 1,然而链并不收敛于任何东西。我们仍然需要检查其他诊断,但至少如果 Rhat > 1.00,那么我们很快就会知道有问题。(好笑的是老一点的教材说> 1.1,后来改成了> 1.01,现在又往> 1.005 移动。让我们坚持 1.00 美元。)

n_eff

样本容量的有效数量定义为:

其中,ρ_t 是滞后 t 时的自相关,实际上,我们会在自相关变为 0 时截断求和。

由于马尔可夫特性,MCMC 不绘制独立样本——至少你的样本依赖于前一个样本。历史上,人们通过减少样本来回避这个问题,例如只保留十分之一的样本。现在我们更清楚了;我们应该保留所有的样本,并将 n_eff 用于类似 CLT 的目的。

这是一个有用的诊断,因为如果你的 n_eff 比你的样本总数(减去老化/预热)低得多,那么一定是出了严重的问题(或者你需要抽取更多的样本)。

我在教科书中最喜欢的一段话来自 McElreath 的《统计学再思考 2:

当人们开始使用 Stan 或其他一些哈密尔顿采样器时,他们经常发现他们以前适合 Metropolis 的模型——黑斯廷斯和吉布斯采样器——不再有效。链条很慢。有很多警告。…这些问题可能一直存在,甚至在其他工具中也是如此。但由于吉布斯不使用梯度,它没有注意到一些问题,汉密尔顿引擎会。一种文化已经在应用统计学中发展了,只是在很长一段时间内——几百万次迭代中——运行坏链,然后积极地变薄、祈祷和发布。这必须停止。[示例[修订]—500 万个样本,neff 为 66!]

他公开羞辱了一家报纸;那份报纸应该受到应有的羞辱。野蛮人。

这一点可以成为使用 NUTS 作为默认设置的有力论据。我怀疑 Gibbs 可以提取合理的样本,但会卡在某个局部空间中,所以诊断是正确的,但 NUTS 会尝试探索其他地方并发出警告。

有时候 n_eff 会比你的样本数高。那没有理由惊慌。

ELPD

将预期对数逐点预测密度(ELPD)视为贝叶斯情况下对数似然的推广。贝叶斯模型输出概率分布,而 RMSE /交叉熵等指标评估点预测的性能。ELPD 评估整个预测分布。

还有其他类似的指标,但是 ELPD 是您所需要的。AIC 和 BIC 评估点预测。WAIC 有很好的渐近性质,但对于较小的样本有不稳定的行为。他们的相似之处在于解释。ELPD 本身是没有意义的,但是它可以用来比较不同的模型,就像你使用 AIC 一样。

因为我们关心模型的泛化能力,所以我们希望从交叉验证中获得 ELPD。否则,我们会对模型性能过于乐观——在训练集上评估模型将产生乐观的低误差估计。

与机器学习中的传统智慧相反,对于贝叶斯模型,留一交叉验证(LOOCV)在计算上比 k-fold 交叉验证更有效。K-fold 要求我们对模型进行 k 次改装,但改装模型是最昂贵的部分。我们可以在已经从后验得到的样本上使用重要性抽样来近似 LOOCV,所以我们不需要重新调整模型。

如今,人们使用帕累托平滑重要性抽样( PSIS-LOOCV )。这些首字母缩略词越来越长。除了提高 ELPD 估计的稳定性,PSIS-LOOCV 还提供了一个额外的诊断:k。该算法采用 20%的最高重要性权重,并拟合一个广义帕累托分布。当 k >为 0.5 时,GPD 具有无限的方差,并表明 ELPD 的估计可能不可信,尽管从经验测试来看,直到 k >为 0.7 时,近似值还没有那么糟糕。当 k 很大时,它可能表示影响很大的观察结果扰乱了模型。

排名图

追踪图的表亲。虽然迹线图对检测退化情况很有用,但很难解释。等级图更容易检查。使用之前的 Metropolis 代码,创建 s = 0.2 的四个链:

library(data.table)
sampled_thetas <- data.table(thetas[iter > 1000])
sampled_thetas[,rank := frank(theta)]ggplot(sampled_thetas) +
  geom_histogram(aes(x = rank)) +
  facet_grid(.~s)

ggplot(thetas[(iter > 1000) & (iter < 1100)]) +
  geom_step(aes(x = iter, y = rank, color = s))

这两个图应该显示一些均匀的混合。否则,一定是出了问题。

对于 MCMC,理解算法是关键。对于 VI,我认为理解目标函数比算法更重要。

变分推理(VI)采用了不同于 MCMC 的方法,但在大多数应用中仍然使用蒙特卡罗。我们提出一个更简单易处理的分布族来逼近后验概率,而不是从后验概率中取样。然后这个问题被框定为一个优化问题。因此,VI 可以扩展到大数据,而 NUTS 不可能处理大数据。

虽然存在几个目标函数(主要替代函数是 Renyi 散度,但最常用的是 Kullback-Leibler 散度 (KL 散度),定义为:

确切的后验概率通常表示为 p,而我们的变分近似表示为 q。理解 KL 散度的性质对于使用 VI 至关重要,我们将从两个方面开始:

第一,是不对称。KL(p||q)要求我们取期望 w.r.t. p,而 KL(q||p)要求我们取期望 w.r.t. q。因此,它不是一个距离度量。

二是非负。从表达式来看不是很明显,可以参考这里的证明。

KL(p||q)被称为前向 KL,它很难处理,因为我们需要对 p 积分(如果我们知道 p,为什么我们还要这样做?).相反,VI 寻求最小化 KL(q||p),即反向 KL。例如,我们可能希望用正态分布来近似高度复杂的后验概率;我们寻求使反向 KL 最小的变分参数μ和σ。用更精确的符号表示,假设ν是变分参数,我们希望找到使以下参数最小化的ν:

但是我们在分母中仍然有那个讨厌的未知后验,所以我们不能直接和 KL 一起工作。就像 Metropolis 一样,我们应用了一个技巧,这样我们就不必计算 p(X):

回想一下,p(X)是一个常数,所以我们可以把它从期望值中去掉。重新排列给了我们证据下限(ELBO),VI 的目标函数:

因为 KL 是非负的,ELBO 的最大可能值是 log(p(X)),即对数证据。因此,为什么它被称为 ELBO:日志证据必须至少与 ELBO 一样高。然而,它可以是一个非常宽松的界限,差距将因假设和模型而异。不要用 ELBO 来比较假设。相反,使用拟合的后验概率计算贝叶斯因子。

ELBO 有两个重要特性:

首先,ELBO 是熵减去交叉熵。很有意思。想一想吧。熵希望 q 尽可能分散,而交叉熵希望 q 收敛到 p 模式上的点质量。这与先验和最大似然估计有类似的加权平均感觉,这是贝叶斯统计的主题。

第二,ELBO 鼓励 q 有太低的方差。在 p 密度高的地方,相对于 p 密度低的区域中的 x 过冲,x 过冲导致的%误差较小。为了解决这个问题,我们采用 w.r.t. q 的期望值,因此在 p 的低密度区域放置较小的质量将会降低这个误差的权重。

VI 对多模态后验概率和高度相关后验概率有困难。

作为一个例子,让我们在多模式后试验 NUTS 和 ADVI。它通常出现在混合模型中,但我们将使用最简单的例子:

标准文件:

data {
  int<lower=0> N;
  real x[N];
}
parameters {
  real mu;
}
model {
  mu ~ normal(0, 1);
  for (n in 1:N)
    x[n] ~ normal(fabs(mu), 1);
}

r 代码:

library(rstan)set.seed(555)
x <- rnorm(100, 2, 1)
data <- list(x = x, N = length(x))
model <- stan_model(file = 'bimodal_example.stan')mcmc <- sampling(
  model, 
  data, 
  iter = 2000, 
  warmup = 1000, 
  chains = 4, 
  seed = 1)advi <- vb(
  model,
  data,
  output_samples = 4000,
  seed = 3
)mcmc_samples <- sapply(
  mcmc@sim$samples, 
  function(x) x[['mu']][1001:2000]
)
advi_samples <- advi@sim$samples[[1]][['mu']]hist(mcmc_samples, breaks = 100, xlim = c(-3, 3))
hist(advi_samples, breaks = 30, xlim = c(-3, 3))

NUTS 报告的 Rhat 为 1.53,让我们知道这个模型是错误指定的。ADVI 收敛没有任何警告!因为拟合的变分分布在图的右边部分几乎没有质量,所以它未能覆盖的部分在 ELBO 中几乎没有重量。因此,它报告的方差比它应该报告的要低得多,使我们对错误的结论过于自信。

接下来,让我们比较 NUTS 与 ADVI 在高度相关后验概率方面的差异。

标准代码:

data {
  int<lower=0> N;
  real y[N];
  real x1[N];
  real x2[N];
}
parameters {
  real beta0;
  real beta1;
  real beta2;
  real<lower=0> sigmasq;
}
transformed parameters {
  real<lower=0> sigma;
  sigma = sqrt(sigmasq);
}
model {
  beta0 ~ normal(0, 1);
  beta1 ~ normal(0, 1);
  beta2 ~ normal(0, 1);
  sigmasq ~ inv_gamma(1, 1);
  for (n in 1:N)
    y[n] ~ normal(beta0 + beta1 * x1[n] + beta2 * x2[n], sigma);
}

r 代码:

library(rstan)set.seed(555)
x1 <- runif(100, 0, 2)
x2 <- x1 + rnorm(100, 0, 1)
y <- mapply(
  function(x1, x2) rnorm(1, x1 + 2 * x2, 1),
  x1,
  x2
)
data <- list(y = y, x1 = x1, x2 = x2, N = length(y))
model <- stan_model(file = 'correlated_example.stan')mcmc <- sampling(
  model, 
  data, 
  iter = 2000, 
  warmup = 1000, 
  chains = 4, 
  seed = 1)advi <- vb(
  model,
  data,
  output_samples = 4000,
  seed = 3
)nuts_beta1 <- sapply(
  mcmc@sim$samples, 
  function(x) x[['beta1']][1001:2000]
)
nuts_beta2 <- sapply(
  mcmc@sim$samples, 
  function(x) x[['beta2']][1001:2000]
)
advi_beta1 <- advi@sim$samples[[1]][['beta1']]
advi_beta2 <- advi@sim$samples[[1]][['beta2']]plot(nuts_beta1, nuts_beta2)
plot(advi_beta1, advi_beta2)

NUTS 设法很好地获得了相关性,但是 VI 认为参数是不相关的!怎么回事?(平心而论,Stan 警告你近似不好。)

默认情况下,VI 通过平均场假设加速计算,即局部参数彼此不相关。这使得观测值可以有条件地交换,并加速梯度计算。然而,正如这个例子所展示的,结果可能是非常错误的!

根据经验法则:

  1. 如果您的数据大小合理,使用 MCMC,因为它更有可能收敛到准确的后验概率。
  2. 如果你的数据对于 MCMC 来说太大,先试试均值场 VI。
  3. 如果平均场 VI 失败,尝试满秩 VI,它允许参数之间的相关性,但使计算慢得多。

坐标上升 VI

CAVI 是你的香草梯度上升。有人计算分析更新,我们迭代,直到 ELBO 收敛。这仅对于条件共轭模型是可能的。如果不可能为你的模型设置一个吉布斯采样器,那么 CAVI 也是不可能的。

像潜在狄利克雷分配这样的简单模型仍然需要大量的数学知识。(我说简单是因为这个模型可以用五行来描述,它是有条件共轭的,并且可以计算梯度。)即使有了分析更新,CAVI 的收敛速度可能会非常慢,但如果一个模型适合 CAVI,那么我们就可以使用 SVI。

随机 VI

如果 CAVI 是梯度上升,那么 SVI 是随机梯度上升。只要我们满足罗宾斯-门罗条件,那么 SVI 就一定会收敛(尽管这可能需要很多很多次迭代)。步长应该下降得足够慢,以便我们完全探索参数空间,但也应该下降得足够快,以便收敛到一个点。Spark 中的 LDA 实现默认使用 SVI。

最初,我认为 SVI 的表现会比 CAVI 差,但令人惊讶的是事实恰恰相反。这篇论文显示,使用 SVI 学习参数要快得多。之前的一个个人项目证实了这一点。对所有文档进行单次 CAVI 迭代产生的结果比只对 10%的文档进行 SVI 迭代产生的结果更差。

如果您可以计算 SVI 的自然梯度,那么它应该是拟合模型的最佳算法。主要的挑战是:你必须手工计算它们。当计算自然梯度太困难甚至不可能时,使用 VI 的下两种风格。他们称之为“黑盒变分推断”,用蒙特卡罗方法近似梯度。Pyro 中的 svi 函数是 BBVI。

分数梯度 VI

纸这里。附录中的推导。我们想通过近似 ELBO 的梯度来进行 SGD。直觉:

  • ELBO 是积分,梯度是极限。支配收敛定理的条件成立,所以我们可以交换∇和积分的顺序。
  • 将乘积法则应用于被积函数。
  • 常数的梯度为 0。
  • 得分函数的期望值为 0。

把这些按顺序应用给我们

我们可以通过从当前 q 中取样并评估被积函数中的每一项来对这一期望进行蒙特卡罗近似。

实际上,分数梯度的方差太高,使其不实用。需要额外的专业知识来控制偏差。否则,BBVI 将不会在任何合理的时间内收敛,因为我们踏遍了所有的地方。

重新参数化梯度 VI

纸这里。这是在大多数概率编程包中默认实现的 VI 版本。我建议阅读原文,因为它写得非常清楚。

基本思想是我们知道如何在多元正态分布上做 VI,那么为什么不把所有的 VI 问题转化成我们已经知道如何解决的问题呢?我们模型中的所有参数都是经过变换的 MVN。我们可以对这些转换函数应用链式法则(重新参数化),并使用自动微分来计算梯度。

实际上,后验分布对重新参数化很敏感。还不清楚什么函数能产生最好的近似值。同样,VI 的良好运行需要专业知识。自动寻找最佳重新参数化的算法是我最想做的事情,我会留意的。

诊断学

ELBO 跟踪图

来源

就像 SGD 算法一样,我们可以检查目标函数是否已经收敛。在现实中,很难知道什么时候停止。一旦逃离局部最优,ELBO 可以跳转,但我们无法判断它是否停留在局部最优。虽然轨迹图很好,但真正的诊断是…

重要性抽样

这是 Stan 在 ADVI 收敛到不适合时用来警告用户的诊断。假设我们想计算 E[θ] w.r.t .的后验概率,但是我们不能这样做,因为我们不知道后验概率。一个巧妙的技巧是

因此,即使我们不能从 p 中取样,我们也可以通过从一个方便的 q 中取样来进行蒙特卡罗近似。我们通过取这个加权平均值来近似期望

其中 w_i 是重要性权重,定义如下

就像 Metropolis 算法一样,我们永远不需要计算 p(X ),因为它在取加权平均值时会抵消掉(见模式?).幸运的是,我们已经有了一个方便的 q 样本:我们拟合的变分分布。众所周知,如果 p 和 q 没有太多重叠,则重要性权重可以具有无限方差。

斯坦将广义帕累托分布拟合到 20%的最高重要性权重。如果 k >为 0.5,GPD 具有无限的方差,尽管实际上,根据经验,在 k >为 0.7 之前,拟合相对较好。当 k > 0.7 时 Stan 警告用户。这应该是您评估 VI 适合性的主要诊断。

最后

希望本文为使用和诊断贝叶斯推理算法提供了很好的信息。一如既往,如果你看到任何错误或有任何建议,请让我知道,以便我可以修改文章。

贝叶斯推理——直觉和例子

原文:https://towardsdatascience.com/bayesian-inference-intuition-and-example-148fd8fb95d6?source=collection_archive---------0-----------------------

使用 Python 代码

为什么有人要发明贝叶斯推理?

一句话:随着我们收集更多的数据,更新概率

贝叶斯推理的核心是将两个不同的分布(似然和先验)组合成一个“更聪明”的分布(后验)。在经典的最大似然估计(MLE)没有考虑先验的意义上,后验是“更聪明”。一旦我们计算出后验概率,我们就用它来寻找“最佳”参数,而“最佳”就是在给定数据的情况下,最大化后验概率****。这个过程叫做最大后验概率(MAP) 。MAP 中使用的优化和典型机器学习中使用的优化是一样的,比如梯度下降或者牛顿法等。

当我研究著名的贝叶斯法则时,通过分析理解这个等式是相当容易的。但是你如何用数据实现它呢?

统计世界中最著名的方程式之一

具体来说,我们会有大量的数据点 X,我们如何将概率 wrt X** 乘以**概率 wrt θ?****

显然,贝叶斯推理的艺术在于你如何实现它。

示例:

每天大约有 2000 名读者访问我的中型博客。有人看完文章鼓掌有人不鼓掌。我想预测一下,当我将来写一篇新的博文时,会有百分之多少的人参与进来并鼓掌

这类问题适用面广。尝试将这一点应用到你自己的建模工作中——广告的点击率、在你的网站上实际购买的客户的转化率、同意与你约会的人的百分比、患乳腺癌的女性的生存机会等。

生成数据:

让我们生成数据 X 。现实生活中,你对 X 没有任何控制这是你要观察的。

import numpy as np
np.set_printoptions(threshold=100)# Generating 2,000 readers' reponse. 
# Assuming the claps follow a Bernoulli process - a sequence of binary (success/failure) random variables.
# 1 means clap. 0 means no clap.**# We pick the success rate of 30%.**
**clap_prob = 0.3**# IID (independent and identically distributed) assumption
**clap_data = np.random.binomial(n=1, p=clap_prob, size=2000)**

拍手数据是二进制的。1 表示拍手,0 表示没有拍手。

数据 X 看起来像:

In [1]: clap_data
Out[1]: array([0, 0, 0, ..., 0, 1, 0])In [2]: len(clap_data)
Out[2]: 2000

贝叶斯推理有三个步骤。

第一步。【先验】选择一个 PDF 来建模你的参数 θ ,又名先验分布 P(θ) 。这是你在** 看到数据 X 之前关于参数 的最佳猜测。**

第二步。【可能性】为 P(X|θ) 选择一个 PDF** 。基本上你是在给定参数 θ 的情况下模拟数据 X 的样子。**

第三步。【后验】计算后验**分布 P(θ|X) 取 P(θ|X)最高的 θ。**

后验成为新的先验。获得更多数据后,重复第 3 步。

第一步。先验 P(θ)

第一步是选择 PDF** 对参数 θ 建模。**

参数θ代表什么?

鼓掌声👏概率。

那么,我们应该用什么样的概率分布来建模一个概率呢?****

要表示一个概率,需要满足几个条件。首先,域的范围应该是从 0 到 1。第二,应该是连续分布。

那么我能想到的有两个众所周知的概率分布:

贝塔和狄利克雷。

狄利克雷用于多变量,贝塔用于单变量。我们只有一件事可以预测,那就是一个概率,所以我们用贝塔分布。

(一个有趣的旁注:很容易在(0,1)上创建任意分布。取任何一个在 0 到 1 之间不爆炸的函数,保持正的。然后,简单的从 0 到 1 积分,用那个结果除函数。)

要使用 Beta 分布,我们需要确定两个参数 α & β 。你可以把 α 想成有多少人鼓掌(成功数)β想成有多少人不鼓掌(失败数)。这些参数——αα&β的大小——将决定分布的形状。

假设您有昨天的数据,并观察到 2000 名访客中有 400 人鼓掌。

根据 beta 分布你会怎么写呢?

import scipy.stats as stats
import matplotlib.pyplot as plt**a = 400
b = 2000 - a**# domain θ
theta_range = np.linspace(0, 1, 1000)# prior distribution P(θ)
prior = **stats.beta.pdf(x = theta_range, a=a, b=b)**

让我们画出所有 θ 值的先验分布。

# Plotting the prior distribution
plt.rcParams['figure.figsize'] = [20, 7]
fig, ax = plt.subplots()
**plt.plot(theta_range, prior,** linewidth=3, color='palegreen')# Add a title
plt.title('[Prior] PDF of "Probability of Claps"', fontsize=20)# Add X and y Label
plt.xlabel('θ', fontsize=16)
plt.ylabel('Density', fontsize=16)# Add a grid
plt.grid(alpha=.4, linestyle='--')# Show the plot
plt.show()

不熟悉 Y 轴上的术语“密度”?→ 阅读“PDF 不是概率”

正如预期的那样,它的峰值达到了 20% (400 次鼓掌/ 2000 个读者)。两千个数据点似乎产生了一个强有力的先验。如果我们使用更少的数据点,比如说 100 个阅读器,曲线将会不那么尖锐。用α= 20&β= 80 试试。

对于那些想知道概率密度怎么会大于 1 的人。👉概率密度不是概率。

第二步。可能性 P(X|θ)

****选择一个概率模型为 P(X|θ) ,给定特定参数 θ 看到数据的概率 X 。可能性也称为抽样分布。对我来说,“抽样分布”这个术语比“可能性”更直观。

要选择使用哪种概率分布来模拟抽样分布,我们首先需要问:

我们的数据 X 是什么样子的?

X 是二进制数组[0,1,0,1,...,0,0,0,1]

我们还有访客总数(n)** 和我们想要**鼓掌的概率(p)。****

好的,n&p……他们对你尖叫什么?****

n&p的二项分布。

**# The sampling dist P(X|θ) with a prior θlikelihood = **stats.binom.pmf(k = np.sum(clap_data), n = len(clap_data), p = a/(a+b))****

我们之前的假设 θ 可能性大吗?

**In [63]: likelihoodOut[63]: 4.902953768848812e-30**

没有。

我们来看一下 P(X|θ) 对于所有可能的 θ 的曲线图。

**# Likelihood P(X|θ) **for all θ's**
likelihood = stats.binom.pmf(k = np.sum(clap_data), n = len(clap_data), **p = theta_range**)# Create the plot
fig, ax = plt.subplots()
**plt.plot(theta_range, likelihood,** linewidth=3, color='yellowgreen')# Add a title
plt.title('[Likelihood] Probability of Claps' , fontsize=20)# Add X and y Label
plt.xlabel(’θ’, fontsize=16)
plt.ylabel(’Probability’, fontsize=16)# Add a grid
plt.grid(alpha=.4, linestyle='--')# Show the plot
plt.show()**

给定数据的可能性 P(X |θ)

第三步。后。P(θ|X)

最后,让我们来回答我们在开始时提出的问题:

具体来说,我们会有大量的数据点 X,我们如何将概率 wrt X 乘以概率 wrt θ?

即使有数千个数据点,我们也可以通过将数据插入您选择的模型(在本例中,二项式分布)中,将它们转换为单个标量——可能性 P(X|θ)。)

然后,我们对一个具体的 θ 计算P(θ)&P(X |θ),并将它们相乘。如果你对每一个可能的 θ 都这样做,你可以在不同的 θ中挑选最高的 P(θ) * P(X|θ)

你最初对参数的猜测是 P(θ)。现在你正在将简单的 P(θ)升级为更具信息性的东西——P(θ| X)——随着更多数据的可用。**
P(θ|X) 仍然是 θ 的概率,就像 P(θ) 是一样。不过, P(θ|X)P(θ) 更聪明的版本。**

代码胜过千言万语:

# (cont.)theta_range_e = theta_range + 0.001 prior = **stats.beta.cdf(x = theta_range_e, a=a, b=b) - stats.beta.cdf(x = theta_range, a=a, b=b)** # prior = stats.beta.pdf(x = theta_range, a=a, b=b)likelihood = **stats.binom.pmf(k = np.sum(clap_data), n = len(clap_data), p = theta_range)** posterior = **likelihood * prior** # element-wise multiplication
normalized_posterior = posterior / np.sum(posterior)
In [74]: np.argmax(prior)
Out[74]: 199In [75]: np.argmax(likelihood)
Out[75]: 306In [76]: np.argmax(posterior)
Out[76]: 253
# Plotting all three together
fig, axes = plt.subplots(3, 1, sharex=True, figsize=(20,7))
plt.xlabel('θ', fontsize=24)**axes[0].plot(theta_range, prior,** label="**Prior**", linewidth=3, color='palegreen')
axes[0].set_title("Prior", fontsize=16)**axes[1].plot(theta_range, likelihood**, label="**Likelihood**", linewidth=3, color='yellowgreen')
axes[1].set_title("Sampling (Likelihood)", fontsize=16)**axes[2].plot(theta_range, posterior,** label='**Posterior**', linewidth=3, color='olivedrab')
axes[2].set_title("Posterior", fontsize=16)
plt.show()

当你看后验图(第三张)时,注意这是可能性向先验转移的地方。** 先前的鼓掌概率为 20%。数据的鼓掌概率被给定为 30%。现在,后验概率的峰值在 0.25%左右。**

此外,请注意,在先验/可能性中,钟形曲线的宽度在后验中缩小了。因为我们通过采样整合了更多的信息,所以可能的参数范围现在变窄了。

你收集的数据越多,后验概率图看起来就越像概率图,越不像先验概率图。换句话说,当你得到更多的数据时,原来的先验分布就不那么重要了。

最后,我们选择θ,其给出通过数值优化计算的最高后验,例如梯度下降或牛顿法。这整个迭代过程被称为最大后验估计(MAP)** 。**

脚注:我们通过减去两个stats.beta.**cdf**而不是使用stats.beta.**pdf**来计算先验,因为可能性stats.binom.**pmf** 是一个概率,而stats.beta.**pdf**返回一个密度。即使我们用密度来计算后验概率,也不会改变优化结果。然而,如果你想要单位匹配,将密度转换成概率是必要的。(还不清楚?阅读“PDF 不是概率,而 PMF 是概率”。)

需要注意一些事情:

  1. MAP 不仅可以通过数值优化来计算,还可以通过(仅适用于某些分布)、修改的期望最大化算法或蒙特卡罗方法来计算。****
  2. 使用封闭形式计算后验概率非常方便,因为你不必进行昂贵的计算。(看贝叶斯公式分母中每一个可能的 θ 的积分。非常贵。)
    在我们上面的例子中,贝塔分布是二项似然的共轭先验。这意味着,在建模阶段,我们已经知道后验也将是贝塔分布。那么在进行更多的实验后,我们只需将成功和失败的次数分别加到现有的参数 αβ 上,就可以计算出后验。
    我们什么时候可以将这种轻松的封闭形式用于后部?
    当你的先验有一个封闭形式(当然)并且是一个共轭先验——当先验乘以似然性再除以归一化常数,仍然是同一个分布。
  3. 归一化(对分母中每个可能的 θ 的积分)对于寻找最大后验概率是否必要

没有。不用归一化还是能找到最大值。但是,如果您想比较不同模型的后验概率,或者计算点估计,您需要将其归一化。

4.MAP 估计可以被看作是通过先验引入更多信息的正则化 ML。

5.你熟悉最大似然估计(MLE),但不太熟悉最大后验概率(MAP)吗?
MLE 只是具有统一先验的映射的一个特例

6.我写了先验是你最好的猜测关于参数 看到数据之前,*然而在实际操作中,一旦我们计算了后验,后验就变成了新的先验,直到新的一批数据进来。这样,我们可以迭代地更新我们的先验和后验。马尔可夫链蒙特卡罗抽样方法就是基于这种思想。*****

模拟 NBA 选秀顺序的贝叶斯推理

原文:https://towardsdatascience.com/bayesian-inference-of-mock-nba-draft-order-f4fa4a26be17?source=collection_archive---------52-----------------------

如何使用优步概率编程库 Pyro 对 NBA 选秀顺序进行建模

我们许多密切关注 NBA 选秀的人都渴望知道选秀的准确顺序,例如每个球员将被带到哪里(“哪里”在这里有双重含义,球队和选秀位置)。为此,我们通常会从十几份甚至更多的“重要”模拟草稿中吸取信息。分析师和媒体试图以不同的方式将这些信息整合成我喜欢称之为“元模拟”的东西。一般来说,这只涉及非常简单的操作,如平均排名或查看最小和最大吃水位置。Chris Feller 前几天分享了一个非常酷的生存分析方法。我还没有深入研究它,但是和我在这里做的事情相比会很有趣。

我想做的是为模拟草稿创建一个生成元模型,这与使用生存分析略有不同,但可以产生类似的见解,我将在后面展示。理论上,这使得人们能够从等级排序中推断出一些“价值”的度量(我没有发现模拟选秀给玩家分配数字评级),然后从后验分布中生成随机模拟选秀顺序。换句话说,就像 Nate Silver 运行模拟来预测谁将赢得选举一样,我们可以为模拟草案创建一个模拟,并在其中做各种各样的事情。让我告诉你怎么做!

我们首先需要的是对等级数据有意义的概率分布。向 Plackett-Luce 分布问好。基本思想是,如果你有一些集合 S 的项目,每个项目都有一些“价值” w_i 你可以在一些向量中的这些项目的任意排列的排名上生成一个概率分布。我不会向您展示这些方程(参见参考资料),但我可以向您展示一个非常简单的模拟来快速理解这个想法。首先我们需要导入一些包并定义 PL 发行版,我发现有人已经在 github 这里上实现了。这里的工作都是使用优步开源的 Pyro 概率编程语言完成的,它是基于脸书的 PyTorch 深度学习库构建的。

**import** **random**

**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**

**import** **torch**
**from** **pyro.infer.autoguide** **import** AutoDiagonalNormal 
**from** **pyro.infer** **import** SVI, Trace_ELBO, Predictive
**from** **pyro.distributions.distribution** **import** Distribution
**from** **torch.distributions** **import** constraints
**from** **pyro.distributions.torch_distribution** **import** TorchDistributionMixin, TorchDistribution
**import** **pyro.distributions** **as** **dist**
**import** **pyro**
**import** **seaborn** **as** **sns***# some utilities defined in https://github.com/agadetsky/pytorch-pl-variance-reduction/blob/master/utils.py*

**def** logcumsumexp(x, dim):
    *# slow implementation, but ok for now*
    **if** (dim != -1) **or** (dim != x.ndimension() - 1):
        x = x.transpose(dim, -1)

    out = []
    **for** i **in** range(1, x.size(-1) + 1):
        out.append(torch.logsumexp(x[..., :i], dim=-1, keepdim=**True**))
    out = torch.cat(out, dim=-1)

    **if** (dim != -1) **or** (dim != x.ndimension() - 1):
        out = out.transpose(-1, dim)
    **return** out

**def** reverse_logcumsumexp(x, dim):
    **return** torch.flip(logcumsumexp(torch.flip(x, dims=(dim, )), dim), dims=(dim, ))

**def** smart_perm(x, permutation):
    **assert** x.size() == permutation.size()
    **if** x.ndimension() == 1:
        ret = x[permutation]
    **elif** x.ndimension() == 2:
        d1, d2 = x.size()
        ret = x[
            torch.arange(d1).unsqueeze(1).repeat((1, d2)).flatten(),
            permutation.flatten()
        ].view(d1, d2)
    **elif** x.ndimension() == 3:
        d1, d2, d3 = x.size()
        ret = x[
            torch.arange(d1).unsqueeze(1).repeat((1, d2 * d3)).flatten(),
            torch.arange(d2).unsqueeze(1).repeat((1, d3)).flatten().unsqueeze(0).repeat((1, d1)).flatten(),
            permutation.flatten()
        ].view(d1, d2, d3)
    **else**:
        **ValueError**("Only 3 dimensions maximum")
    **return** ret**class** **PlackettLuce**(Distribution):
    *"""*
 *Plackett-Luce distribution*
 *"""*
    arg_constraints = {"logits": constraints.real}

    **def** __init__(self, logits):
        *# last dimension is for scores of plackett luce*
        super(PlackettLuce, self).__init__()
        self.logits = logits
        self.size = self.logits.size()

    **def** sample(self, sample_shape=torch.Size()):
        *# sample permutations using Gumbel-max trick to avoid cycles*
        **with** torch.no_grad():
            logits = self.logits.unsqueeze(0).expand(sample_shape, *self.size)
            u = torch.distributions.utils.clamp_probs(torch.rand_like(logits))
            z = self.logits - torch.log(-torch.log(u))
            samples = torch.sort(z, descending=**True**, dim=-1)[1]
        **return** samples

    **def** log_prob(self, samples):
        *# samples shape is: num_samples x self.size*
        *# samples is permutations not permutation matrices*
        **if** samples.ndimension() == self.logits.ndimension():  *# then we already expanded logits*
            logits = smart_perm(self.logits, samples)
        **elif** samples.ndimension() > self.logits.ndimension():  *# then we need to expand it here*
            logits = self.logits.unsqueeze(0).expand(*samples.size())
            logits = smart_perm(logits, samples)
        **else**:
            **raise** **ValueError**("Something wrong with dimensions")
        logp = (logits - reverse_logcumsumexp(logits, dim=-1)).sum(-1)
        **return** logp

好,让我们做一个小模拟。很简单。想象一下,我们有 5 名赛车手。我们将使用指数分布生成一些“价值”向量。我们看到,到目前为止,驾驶员 3 的评分最高,驾驶员 0 的评分最低。给定这些参数,然后我们使用 PL 分布生成“种族”的随机样本。我们这样做 10 次。

n_drivers = 5
torch.manual_seed(39)
theta = dist.Exponential(0.1).sample((n_drivers,))
ranks = list(zip(range(n_drivers),theta.numpy()))
[print(f'driver **{**i**}**: **{**j**:**0.3**}**') **for** i, j **in** sorted(ranks,key=**lambda** x: -x[1])]
pl = PlackettLuce(theta)
data = pl.sample(10)
print(data.numpy())# output
driver 3: 31.7
driver 4: 23.0
driver 2: 2.02
driver 1: 1.02
driver 0: 0.294
[[3 4 1 2 0]
 [3 4 1 2 0]
 [3 4 2 0 1]
 [3 4 2 1 0]
 [3 4 2 1 0]
 [3 4 1 0 2]
 [3 4 2 1 0]
 [3 4 1 2 0]
 [3 4 2 1 0]
 [3 4 0 2 1]]

你可以看到,在我们所有的 10 场模拟比赛中,3 号和 4 号车手分别获得了 1 号和 2 号。

现在,让我们做同样的模拟,但增加指数率参数,使驱动器更“均匀”。

n_drivers = 5
torch.manual_seed(39)
theta = dist.Exponential(1.0).sample((n_drivers,))
ranks = list(zip(range(n_drivers),theta.numpy()))
[print(f'driver **{**i**}**: **{**j**:**0.3**}**') **for** i, j **in** sorted(ranks,key=**lambda** x: -x[1])]
pl = PlackettLuce(theta)
data = pl.sample(10)
print(data.numpy())#output
driver 3: 3.17
driver 4: 2.3
driver 2: 0.202
driver 1: 0.102
driver 0: 0.0294
[[1 4 3 2 0]
 [3 1 4 2 0]
 [3 4 2 0 1]
 [4 3 2 0 1]
 [4 3 2 1 0]
 [3 4 0 1 2]
 [3 4 2 0 1]
 [3 4 1 2 0]
 [3 4 2 0 1]
 [4 0 3 2 1]]

你可以看到现在车手 4 赢得了一些比赛,甚至车手 1 也站在了领奖台上。太棒了。希望这开始对你有意义。我们基本上准备好了。我们只需要读入一些数据,创建模型,做一些推断。我们开始吧!

我从 17 个公开的模拟草稿中收集了数据。然而,并非所有的草案都模拟了两轮投票。这是可以的,因为即使在一个回合中仍然有有用的信息。我将很快解释我是如何处理这个问题的,但是让我们先看看数据。

df = pd.read_csv('data/mock-drafts.csv')
df.head()

作者图片

cols = df.columns[1:]
players_set = set()
**for** col **in** cols:
    **for** player **in** df[col].values:
        players_set.add(player)
players = {player:idx **for** idx,player **in** enumerate(players_set) **if** type(player) **is** str}
player_lut = {idx:player **for** player,idx **in** players.items() **if** type(player) **is** str}
print(player_lut)# output
{1: 'Kira Lewis', 2: 'Udoka Azubuike', 3: 'Tyrell Terry', 4: 'Saben Lee', 5: 'Aleksej Pokusevski', 6: 'Cassius Winston', 7: 'Austin Wiley', 8: 'Devon Dotson', 9: 'Naji Marshall', 10: 'Nick Richards', 11: 'Yam Madar', 12: 'Zeke Nnaji', 13: 'Kaleb Wesson', 14: 'Mason Jones', 15: 'Patrick Williams', 16: 'James Wiseman', 17: 'Tyrese Haliburton', 18: 'Theo Maledon', 19: 'LaMelo Ball', 20: 'Tyrique Jones', 21: 'Ty-Shon Alexander', 22: 'Vernon Carey', 23: 'Reggie Perry', 24: 'Xavier Tillman', 25: 'Filip Petrusev', 26: 'Leandro Bolmaro', 27: 'Josh Green', 28: 'Abdoulaye Ndoye', 29: 'Killian Hayes', 30: 'Tyler Bey', 31: 'Isaiah Stewart', 32: 'Lamine Diane', 33: 'Desmond Bane', 34: 'Lamar Stevens', 35: 'Aaron Nesmith', 36: 'Tyrese Maxey', 37: 'Anthony Edwards', 38: 'Yoeli Childs', 39: 'Omer Yurtseven', 40: 'Borisa Simanic', 41: 'Justinian Jessup', 42: 'Malachi Flynn', 43: 'Jahmius Ramsey', 44: 'Obi Toppin', 45: 'Markus Howard', 46: 'Tre Jones', 47: 'Robert Woodard', 48: 'Nate Hinton', 49: 'Isaac Okoro', 50: 'Cole Anthony', 51: 'Jaden McDaniels', 52: 'Jordan Nwora', 53: 'Deni Avdija', 54: 'Jalen Harris', 55: 'Rokas Jokubaitis', 56: 'Paul Reed', 57: 'Jay Scrubb', 58: 'Ashton Hagans', 59: 'Jalen Smith', 60: 'Kristian Doolittle', 61: 'Henri Drell', 62: 'CJ Elleby', 63: 'Isaiah Joe', 64: 'Paul Eboua', 65: 'Killian Tillie', 66: 'Kenyon Martin', 67: 'RJ Hampton', 68: 'Immanuel Quickley', 69: 'Sam Merrill', 70: 'Onyeka Okongwu', 71: 'Grant Riller', 72: 'Payton Pritchard', 73: 'Skylar Mays', 74: 'Karim Mane', 75: 'Giorgos Kalaitzakis', 76: 'Mamadi Diakite', 77: 'Nico Mannion', 78: 'Saddiq Bey', 79: 'Marko Simonovic', 80: 'Paul Ebouta', 81: 'Precious Achiuwa', 82: 'Cassius Stanley', 83: 'Daniel Oturu', 84: 'Elijah Hughes', 85: 'Josh Hall', 86: 'Devin Vassell'}

正如你所看到的,在这些模拟选秀中共有 86 名选手。现在我们将把模拟放入 Pyro 可以理解的数据格式中,一个包含 17 行的 Torch 张量。每一排将有所有 86 名球员在一些排列。现在我可以解释我是如何填充每个模拟的,这样无论一个模拟有 30 个还是 60 个玩家,每个都将被填充以包含所有的 86 个玩家。我假设一些非常简单的事情:如果一个模拟没有一个玩家,那么每个其他玩家可以被随机洗牌以填充整个模拟到位置 86。这是我能做的最简单的方法。更高级的方法是从这样的随机化开始,然后用基于模型推断评级的随机顺序来细化“反事实”填充。人们可以像这样不断迭代,直到达到某种平衡(基本上直到不再有改进)。

**import** **random**
n_players = len(player_lut)
list_data = []
**for** col **in** cols:
    mock = df[col]
    ranks = []
    players_cp = players.copy()
    **for** i **in** range(1,n_players+1):
        **try**:
            player = mock[i-1]
            players_cp.pop(player)
            ranks.append(players[player])
        **except** **KeyError**: 
            random_player = random.choice(list(players_cp.keys()))
            **if** players_cp.pop(random_player):
                ranks.append(players[random_player])
    list_data.append(ranks)
data = torch.tensor(list_data)-1
print(data)# output
tensor([[18, 15, 36,  ..., 44, 73,  6],
        [36, 52, 15,  ...,  8, 53, 78],
        [18, 16, 36,  ..., 75, 61, 63],
        ...,
        [18, 15, 36,  ..., 31,  3,  6],
        [36, 18, 69,  ..., 72, 51, 63],
        [36, 15, 18,  ..., 37, 44, 19]])

让我们看看其中的一行:

[player_lut[i+1] **for** i **in** data.numpy()[0]][0:10]# output
['LaMelo Ball',
 'James Wiseman',
 'Anthony Edwards',
 'Deni Avdija',
 'Obi Toppin',
 'Tyrese Haliburton',
 'Isaac Okoro',
 'Devin Vassell',
 'Onyeka Okongwu',
 'Killian Hayes']

好了,现在是激动人心的部分。让我们定义模型:

n_players = 86

**def** model(data):
    sigma = pyro.sample("sigma", dist.Uniform(0,1))
    theta = pyro.sample("theta", dist.Cauchy(torch.zeros(n_players,),sigma*torch.ones(n_players,)))
    **with** pyro.plate("data", data.shape[-2]):
        pyro.sample("obs", PlackettLuce(theta), obs=data)

真的就是这样。我使用柯西分布,因为如果你考虑 NBA 人才的分布,它似乎是“厚尾”的。换句话说,我们希望我们的模型能够处理有“超级明星”或一致同意的最佳人选的情况。如果我们让我们的分布过于平坦,这将更像一场赛马,任何一匹马都有机会第一个到达终点(或多或少)。现在我们进行推理步骤,根据 Pyro 的说法建立一个向导和优化器来进行随机变分推理(在未来,我计划研究更精确的 MCMC 采样方法,但是现在应该可以了)。

guide = AutoDiagonalNormal(model)
adam = pyro.optim.Adam({"lr": 0.03})
svi = SVI(model, guide, adam, loss=Trace_ELBO())
pyro.clear_param_store()
**for** j **in** range(5000):
    *# calculate the loss and take a gradient step*
    loss = svi.step(data)
    **if** j % 100 == 0:
        print("[iteration **%04d**] loss: **%.4f**" % (j + 1, loss / data.shape[-2]))

这是我们元模拟的结果!

1\. Anthony Edwards (12.2)
2\. LaMelo Ball (12.0)
3\. Deni Avdija (10.3)
4\. James Wiseman (10.3)
5\. Obi Toppin (9.9)
6\. Onyeka Okongwu (8.0)
7\. Killian Hayes (7.9)
8\. Tyrese Haliburton (7.6)
9\. Isaac Okoro (7.6)
10\. Devin Vassell (6.7)
11\. Patrick Williams (6.0)
12\. Aaron Nesmith (5.2)
13\. Saddiq Bey (4.7)
14\. Kira Lewis (4.6)
15\. Precious Achiuwa (4.5)
16\. RJ Hampton (4.1)
17\. Jalen Smith (4.0)
18\. Cole Anthony (3.9)
19\. Tyrese Maxey (3.7)
20\. Josh Green (3.0)
21\. Aleksej Pokusevski (2.6)
22\. Leandro Bolmaro (2.4)
23\. Isaiah Stewart (2.3)
24\. Jaden McDaniels (2.2)
25\. Theo Maledon (2.0)
26\. Jahmius Ramsey (1.7)
27\. Tyrell Terry (1.6)
28\. Desmond Bane (1.3)
29\. Nico Mannion (1.2)
30\. Zeke Nnaji (1.1)
31\. Malachi Flynn (1.0)
32\. Tre Jones (0.9)
33\. Devon Dotson (0.8)
34\. Paul Reed (0.5)
35\. Vernon Carey (0.5)
36\. Isaiah Joe (0.5)
37\. Elijah Hughes (0.5)
38\. Cassius Stanley (0.5)
39\. Daniel Oturu (0.4)
40\. Killian Tillie (0.4)
41\. Cassius Winston (0.4)
42\. Grant Riller (0.3)
43\. Udoka Azubuike (0.3)
44\. Tyler Bey (0.3)
45\. Reggie Perry (0.2)
46\. Xavier Tillman (0.2)
47\. Payton Pritchard (0.1)
48\. Jay Scrubb (0.1)
49\. Abdoulaye Ndoye (0.1)
50\. Immanuel Quickley (-0.0)
51\. Ty-Shon Alexander (-0.0)
52\. Ashton Hagans (-0.0)
53\. Jordan Nwora (-0.1)
54\. Robert Woodard (-0.1)
55\. Nick Richards (-0.1)
56\. Yam Madar (-0.1)
57\. Skylar Mays (-0.2)
58\. Nate Hinton (-0.2)
59\. Paul Ebouta (-0.2)
60\. Filip Petrusev (-0.3)
61\. Justinian Jessup (-0.3)
62\. Lamar Stevens (-0.3)
63\. Marko Simonovic (-0.3)
64\. Sam Merrill (-0.3)
65\. Josh Hall (-0.4)
66\. Karim Mane (-0.4)
67\. Kaleb Wesson (-0.4)
68\. Kristian Doolittle (-0.5)
69\. Tyrique Jones (-0.5)
70\. Borisa Simanic (-0.5)
71\. Markus Howard (-0.5)
72\. Kenyon Martin (-0.5)
73\. CJ Elleby (-0.6)
74\. Rokas Jokubaitis (-0.6)
75\. Lamine Diane (-0.6)
76\. Yoeli Childs (-0.6)
77\. Jalen Harris (-0.6)
78\. Mason Jones (-0.7)
79\. Paul Eboua (-0.7)
80\. Saben Lee (-0.7)
81\. Mamadi Diakite (-0.7)
82\. Omer Yurtseven (-0.8)
83\. Henri Drell (-0.8)
84\. Austin Wiley (-0.8)
85\. Naji Marshall (-0.8)
86\. Giorgos Kalaitzakis (-0.9)

好吧,还不错,但这还不是最酷的部分。最酷的部分是现在我们有了每个玩家的概率分布,所以我们可以去模拟成千上万的模拟选秀。我们开始吧!基本上,我们只是对后验分布进行采样(来自 Pyro guide 函数),并生成一个样本模拟汇票订单。然后我们做那 10,000(!)次,并将它们全部放入熊猫数据框中。

rank_hist = []
**for** m **in** range(10_000):
    theta = guide.forward()['theta']
    pl = PlackettLuce(theta)
    sample = pl.sample(1).numpy()[0]
    **for** i, j **in** enumerate(sample.squeeze()):
        **if** i<=59:
            rank_hist.append((i+1,player_lut[j+1]))
        **else**:
            rank_hist.append((61,player_lut[j+1]))
rank_df = pd.DataFrame.from_records(rank_hist,columns=['rank','player'])

所以现在我们有了每个球员的模拟选秀位置的分布(直方图)。例如,让我们看看安东尼·爱德华兹是在哪里被预言的:

sns.set_style("ticks", {"xtick.minor.size": 1, "ytick.major.size": 8})
players = ['Anthony Edwards']
sns.displot(data=rank_df[rank_df.player.isin(players)],x='rank',kind='hist',hue='player')

作者图片

理解这种分布的一个更简单的方法是看累积概率。还记得我说过这个模型可以以类似生存分析的方式使用吗?这就是我所说的:

sns.set_style("ticks", {"xtick.minor.size": 1, "ytick.major.size": 8})
players = ['Anthony Edwards']
sns.displot(data=rank_df[rank_df.player.isin(players)],x='rank',kind='ecdf',hue='player')

作者图片

从这里我们看到爱德华兹有大约 45%的机会被选为第一名,大约 80%的机会进入前两名,以此类推。相当整洁!现在让我们来看看一个预测范围更广的人,Saddiq Bey:

sns.set_style("ticks", {"xtick.minor.size": 1, "ytick.major.size": 8})
players = ['Saddiq Bey']
sns.displot(data=rank_df[rank_df.player.isin(players)],x='rank',kind='ecdf',hue='player')

作者图片

哦,那不是很酷吗?确实范围很广。让我们来看看一个更加边缘的球员,尼克·理查兹:

sns.set_style("ticks", {"xtick.minor.size": 1, "ytick.major.size": 8})
players = ['Nick Richards']
sns.displot(data=rank_df[rank_df.player.isin(players)],x='rank',kind='ecdf',hue='player')

作者图片

好的,所以我应该解释一下,在模拟中,如果一个球员没有被选进前 60,我就把他放在 61,这样他基本上就是一个未被选中的自由球员(UDFA)。这些图有点乱,但在我完成之前,这里有一个图表中有前 10 名的人。

sns.set_style("ticks", {"xtick.minor.size": 1, "ytick.major.size": 8})
players = ['Anthony Edwards', 'LaMelo Ball', 'Deni Avdija', 'James Wiseman', 'Obi Toppin', 'Onyeka Okongwu',
          'Killian Hayes', 'Tyrese Haliburton', 'Isaac Okoro', 'Devin Vassell']
sns.displot(data=rank_df[rank_df.player.isin(players)],x='rank',kind='ecdf',hue='player')

作者图片

嗯,我现在就知道这么多了。随着选秀临近(11 月 18 日),请(通过我的推特)关注更多与此相关的事情。如果你有任何建议(或修正)让我知道!以下是该项目的 github repo 的链接:

预测分析:Python 中的贝叶斯线性回归

原文:https://towardsdatascience.com/bayesian-linear-regression-project-in-python-forecast-water-consumption-under-the-impact-of-cea62c2693e4?source=collection_archive---------18-----------------------

Alex Samuels 在 Unsplash 上的照片

数据科学项目的贝叶斯线性回归基础概述

在这篇文章中,我想更多地关注贝叶斯线性回归理论,并用 Python 实现一个数据科学项目的建模。整个项目是关于预测未来三十年气候变化影响下的城市用水量。完整版本的代码可以在 GitHub 的 Jupyter 笔记本上找到,我鼓励你去看看。此外,研究结果发表在可持续发展的城市和社会上。

为什么是贝叶斯统计?

统计学有两个主要分支,描述统计推断统计。描述性统计提供数据的简明摘要,而推断性统计发现模式并对数据做出推断。但是为什么我要谈论这两个术语呢?😀嗯,在推断统计学中有两个对我们很重要的一般“哲学”;频率主义贝叶斯主义

频率统计和贝叶斯统计通过两种不同的方法来划分统计世界,以定义概率。在频率统计中,概率与重复事件的频率有关,而在贝叶斯统计中,概率与我们自身的确定性和不确定性有关。因此,结果是,频率主义者认为模型是固定的,数据围绕它们变化,但贝叶斯主义者谈论观察到的数据是固定的,模型可以围绕它们变化。

所以这个问题的答案是“为什么是贝叶斯统计?”是,有了贝叶斯统计,我们可以用概率来表示任何事件或假设中的不确定性。

贝叶斯定理

贝叶斯定理是贝叶斯统计中的关键规则[1]。如果 H 是假设,D 是观测数据,贝叶斯定理如下

贝叶斯定理

其中 P(H|D) 表示假设 D 发生的条件下,假设的后验概率P(H) 是假设的先验概率P(D) 是观测数据的边际(总)概率,实际上是一个归一化常数, P(D|H) 是给定假设的数据的概率(可能性)。

资料组

加拿大魁北克省的 Brossard 市被选为研究地点。我获得了 2011 年 1 月至 2015 年 10 月期间的日城市用水量q 的时间序列。对于同一时间段,我还得到了气候变量的时间序列:日最低气温 θ日最高气温 t总降水量 p 。这些气候变量的测量是在皮埃尔·艾略特·特鲁多国际机场(YUL)的加拿大环境站进行的。

贝叶斯线性回归

贝叶斯统计是一种强大的概率建模技术,已被广泛用于统计建模,包括线性回归模型,以预测系统[2,3,4,5]。线性回归模型表示为

线性回归模型

其中 q 为因变量(目标变量) β_0 为截距; β_1β_2β_3 为权重(称为模型参数); θtp 称为预测变量;并且 ε 是表示随机噪声或模型方程中不包括的变量的影响的误差项。该等式可以改写为

其中β=(β_ 0β_1β_2β_ 3);以及X=(1,qQp)【2,6】。线性回归是使用概率分布而不是点估计来预测 q 的。因此, q 不是作为单个值来估计的,而是假设从概率分布中提取的。响应从正态(高斯)分布 N 中取样的贝叶斯线性回归模型为

输出 q 由以平均值和方差为特征的正态分布产生。正态分布的平均值是回归系数矩阵()乘以预测值矩阵( X )。方差是标准差的平方, σ

贝叶斯线性回归模型提供了预测变量中不确定性的表示,并确定了模型参数的后验分布。不仅响应是由概率分布生成的,而且模型参数也被假定来自分布。模型参数的后验概率来自贝叶斯定理:

模型参数的后验概率

其中P(β| q, X )是给定预测值和自变量的模型参数的后验概率分布; P(q| β,X ) 是数据的可能性;P(β|X)是参数的先验概率,方程的分母是根据全概率定律可以找到的边际概率。

马尔可夫链蒙特卡罗

在实践中,很难计算连续值的边际可能性;计算精确的后验分布是困难的。作为一种解决方案,一种采样方法马尔可夫链蒙特卡罗被用于近似后验概率,而无需计算边际似然[3,5,7]。蒙特卡洛是一种抽取随机样本的通用技术,马尔可夫链意味着抽取的下一个样本仅基于上一个样本值。通过引入更多样本,后验概率的近似值将最终收敛于 β_1β_2β_3 的实际后验概率分布。

作为应用马尔可夫链蒙特卡罗的起点,定义覆盖 β_1β_2β_3 所有可能值的参数空间。然后,将每个参数的先验概率定义为正态分布。接下来,计算每个可能参数的可能性。最后,计算参数空间中任何给定点的先验×似然。

使用不掉头算法【8】实现马尔可夫链蒙特卡罗。当所涉及的变量是连续的并且不需要设置步数时,这种算法是有效的。这是优于哈密尔顿蒙特卡罗的优点,哈密尔顿蒙特卡罗采用由一阶梯度信息通知的一系列步骤,并且对步骤的数量敏感。

生成用于被接受的移动的一组参数值(如果建议的移动未被接受,则重复先前的值),并且在多次重复之后,找到分布的经验近似。最终,执行贝叶斯线性回归的结果是基于数据和先验的可能模型参数的概率密度函数。

模型性能测量

整个数据集被分成训练集和测试集。训练集包含 75%的数据,用于构建模型;而测试集包含 25%,用于验证预测的准确性。此外,两个拟合优度指标用于评估本研究中开发的模型的性能。这些度量是平均绝对误差和均方根误差。平均绝对误差是预测值和实际值之差的绝对值的平均值,均方根误差是预测值和实际值之差的平均值的平方根。

均方根误差

绝对平均误差

Python 代码

正如我之前提到的,我在这篇文章中的重点是贝叶斯线性回归模型。因此,我跳过数据预处理这一步。贝叶斯线性回归模型的输入数据集如下

输入数据集

  • UWC:城市用水量
  • Max_T:最高温度
  • 最低温度
  • 总降水量

⚠️在创建模型之前,请确保您已经处理了缺失值,因为贝叶斯线性回归模型不接受带有缺失点的数据。

在 PyMC3 中创建贝叶斯线性回归模型

首先,我使用 sklearn 库将预处理数据集(df)拆分为 75%训练和 25%测试。

注: X_train 和 X_test 包含目标变量 UWC。

*from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(df, df['UWC'],
test_size = 0.25,random_state = 42)*

在这个项目中,我在 PyMC3 中创建了贝叶斯线性回归模型。让马尔可夫链蒙特卡罗算法从后验概率中抽取样本来近似每个模型参数的后验概率。

为了创建模型,我将线性回归公式、参数的先验族和数据传递给 GLM 。为了执行马尔可夫链蒙特卡罗抽样,我指定样本数为 2000,链数为 2,调优步数为 500。

*import pymc3 as pm
from pymc3 import traceplot**# Formula for Bayesian Linear Regression** 
formula = ‘UWC ~ ‘ + ‘ + ‘.join([‘%s’ % variable for variable in X_train.columns[1:]])
print(formula)**# Context for the model**
with pm.Model() as normal_model:

    **# The prior for the model parameters will be a normal distribution**
    family = pm.glm.families.Normal()**# Creating the model requires a formula and data (and optionally a family)**
    pm.GLM.from_formula(formula, data = X_train, family = family)**# Perform Markov Chain Monte Carlo sampling**
    normal_trace = pm.sample(draws=2000, chains = 2, tune = 500)*

所以,UWC 是最高温度、最低温度和总降水量的函数。

将后验分布绘制成直方图

*pm.plot_posterior(normal_trace)*

(a)截距β_0 的后验直方图;(b)对于 θ 的回归系数β_ 1;(c)回归系数 β_2t;(d)对于 p 的回归系数β_ 3;标准偏差 σ

结果显示为 β_0β_1β_2β_3、σ 的后验直方图。直方图显示 95%的最高后验密度(HPD),这是参数的可信区间。贝叶斯统计中的可信区间相当于置信区间。比如 0.034<σ0.037 的概率是 95%。

计算梅和 RMSE

为了计算 MAE 和 RMSE,我取 UWC 概率分布的中值,并将其作为对 evaluate_prediction 函数的预测。

***# Define a function to calculate MAE and RMSE**
def evaluate_prediction(prediction, true):
    mae = np.mean(abs(predictions - true))
    rmse = np.sqrt(np.mean((predictions - true) ** 2))

    return mae, rmsemedian_pred = X_train['UWC'].median()
median_preds = [median_pred for _ in range(len(X_test))]
true = X_test['UWC']**# Display mae and rmse**
mae, rmse = evaluate_prediction(median_preds, true)
print('Mean Absolute Error: {:.4f}'.format(mae))
print('Root Mean Square Error: {:.4f}'.format(rmse))*

对模型性能的评估表明,预测模型具有良好的精度。

结论

这篇文章是一个数据科学项目的贝叶斯线性回归的简要概述。我希望它能帮助你更好地理解贝叶斯线性回归的基本原理。😊

非常感谢您的反馈。你可以在 LinkedIn 上找到我。

参考

[1]赫克曼博士、盖格博士和奇克林博士(1995 年)。学习贝叶斯网络:知识和统计数据的结合。机器学习*, 20 (3),197–243。【https://doi.org/10.1023/A:1022623210503 *

[2]韩,贾伟和裴,简和坎伯,M. (2011)。数据挖掘:概念和技术。检索自http://myweb . saban ciuniv . edu/rdehkharghani/files/2016/02/The-mor gan-Kaufmann-Series-in-Data-Management-Systems-Jia Wei-Han-Micheline-Kamber-Jian-Pei-Data-Mining。-概念和技术-第三版-摩根-考夫曼-2011.pdf

[3] Mudgal,a .,Hallmark,s .,Carriquiry,a .,和 Gkritza,K. (2014 年)。环形交叉路口的驾驶行为:分层贝叶斯回归分析。交通研究 D 部分:交通与环境26 ,20–26。https://doi.org/10.1016/j.trd.2013.10.003

[4]a . e .拉夫特里、d .马迪根和 J. A .赫廷(1997 年)。线性回归模型的贝叶斯模型平均。美国统计协会杂志92 (437),179–191。检索自https://www . tandfonline . com/doi/ABS/10.1080/01621459 . 1997 . 10473615

[5]袁晓春,孙晓霞,赵,魏,米,张,王,魏延明(2017)。2030 年中国区域能源需求预测:贝叶斯方法。资源、保护和回收127(5 月),85–95。https://doi.org/10.1016/j.resconrec.2017.08.016

[6]t .塔勒布和 m .卡杜尔(2017 年)。无线传感器网络中提高能量效率的分层凝聚分簇方案。交通与电信18 (2),128–138。https://doi.org/10.1515/ttj-2017-0012

[7] Godsill,S. J. (2001 年)。模型不确定性的马尔可夫链蒙特卡罗方法之间的关系。计算与图形统计杂志10 (2),230–248。https://doi.org/10.1198/10618600152627924

[8]医学博士霍夫曼和盖尔曼(2011 年)。不掉头采样器:在哈密顿蒙特卡罗中自适应地设置路径长度。(2008), 1–30.从 http://arxiv.org/abs/1111.4246取回

使用 PyMC3 的贝叶斯逻辑回归

原文:https://towardsdatascience.com/bayesian-logistic-regression-with-pymc3-8e17c576f31a?source=collection_archive---------11-----------------------

这是一系列文章中的另一篇(参见此处和此处的其他相关文章),一般来说是关于概率编程的,特别是关于 PyMC3 的。在我们之前的文章中,我们解释了 PyMC3 如何帮助统计推断。在本文中,我们将使用 PyMC3 解决一个端到端的分类问题。更准确地说,我们将使用 PyMC3 通过以下公共数据集进行贝叶斯逻辑回归:

https://archive . ics . UCI . edu/ml/datasets/Occupancy+Detection+

该数据集包含几个变量,如光线、温度、湿度和二氧化碳水平。目标是从这些变量中检测房间的占用情况。

首先,我们需要加载几个相关的包。

**import** **arviz** **as** **az**
**import** **matplotlib.pyplot** **as** **plt**
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **pymc3** **as** **pm**
**import** **seaborn**
**import** **theano.tensor** **as** **tt**
**import** **warnings**
**from** **IPython.core.pylabtools** **import** figsize
**import** **seaborn** **as** **sns**
**from** **sklearn.metrics** **import** (roc_curve, roc_auc_score, confusion_matrix, accuracy_score, f1_score, 
                             precision_recall_curve) 
**from** **sklearn.metrics** **import** confusion_matrix

接下来,我们加载数据集。

df=pd.read_csv('datatest.txt')
df.sample(5)

为了方便起见,我们将日期变量转换为日期时间对象。

df['date']=pd.to_datetime(df['date'])

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

首先,让我们看一下数据集的概况。

df.describe()

数据集概述

我们看到这个数据集中有 2655 个样本。此外,没有丢失值。让我们也看看这个数据集的时间框架。

df['date'].describe()count                    2665
unique                   2665
top       2015-02-03 07:25:59
freq                        1
first     2015-02-02 14:19:00
last      2015-02-04 10:43:00
Name: date, dtype: object

所以我们的数据只在三天内就收集好了。接下来,我们将探讨我们的变量及其关系。首先,让我们画出温度变量。

figsize(12.5, 4)
plt.hist(df['Temperature'], bins=40, density=**True**, label='Temperature')
plt.xlabel('Temperature')
plt.title('Distribution of temperature')
plt.show()

该图显示温度具有重尾分布。湿度变量呢?

figsize(12.5, 4)
plt.hist(df['Humidity'], bins=50, density=**True**, label='Humidity')
plt.xlabel('Humidity')
plt.title('Distribution of Humidity')
plt.show()

有趣的是,在 22.5 和 25 附近有两个峰值。我们还对不同日子里的光照变化感兴趣。

figsize(12.5, 4)
sns.boxplot(x=df['date'].dt.day,y=df['Light'], orient='v')
plt.xlabel('Day')
plt.title('Boxplot for Light during different days')
plt.show()

我们看到光的分布在这三天中几乎是相同的。接下来,让我们看看二氧化碳水平。

figsize(12.5, 4)
sns.boxplot(x=df['date'].dt.day,y=df['CO2'], orient='v')
plt.xlabel('Day')
plt.title('Boxplot for CO2 level during different days')
plt.show()

这些分布明显不同。2015 年 2 月 4 日有很多异常值。最后,我们将深入研究湿度比变量。

figsize(12.5, 4)
sns.boxplot(x=df['date'].dt.day,y=df['HumidityRatio'], orient='v')
plt.xlabel('Day')
plt.title('Boxplot for Humidity Ratio level during different days')
plt.show()

这看起来非常类似于二氧化碳水平的箱线图。也许,二氧化碳水平和湿度之间有很强的相关性。我们可以用这两个变量的散点图来验证。

ax=sns.scatterplot(df['CO2'], df['HumidityRatio'], style=df['date'].dt.day)

二氧化碳水平和湿度比的散点图

事实上,二氧化碳水平和湿度比之间有很强的线性关系。让我们看一下变量之间的关系。这可以通过 seaborn 的 pair plot 函数来完成。

ax=seaborn.pairplot(df)

数据集中所有要素的配对图

这直观地显示了在以下对之间存在强线性关系:CO2 和温度、CO2 和湿度、湿度和湿度比、湿度比和 CO2。我们甚至可以通过绘制热图来量化这些关系。

corr=df.iloc[:, 1:-1].corr()
*# Generate a mask for the upper triangle*
mask = np.triu(np.ones_like(corr, dtype=np.bool))
*# Set up the matplotlib figure*
f, ax = plt.subplots(figsize=(11, 9))*# Draw the heatmap with the mask and correct aspect ratio*
ax=sns.heatmap(corr, mask=mask,
            square=**True**, linewidths=.5, cbar_kws={"shrink": .5})

清楚地表明,两对湿度-湿度比和湿度比-CO2 表现出最强的线性关系。

基于 PyMC3 的贝叶斯逻辑模型

我们将建立几个机器学习模型,根据其他变量对入住情况进行分类。

回想一下,我们有一个二元决策问题。换句话说,我们的目标变量假设遵循伯努利随机变量,p 由下式给出:

其中,var 是我们在模型中使用的所有变量的集合,logit 是逻辑函数。

为了建立贝叶斯逻辑回归模型,我们首先要对每个参数进行先验分布。这些先验的选择将影响结果(尽管有更多的数据,它们可能会“收敛”到相同的分布。)

一旦我们的先验被指定,PyMC3 将使用马尔可夫链蒙特卡罗模拟及其推广在数值上近似后验分布。然后,我们可以使用这些后验样本进行推断。

先验分布均匀的第一个模型

由于我们没有关于这些参数的先验知识,我们可以假设它们可以是任何东西。换句话说,我们假设所有的β_var 服从一个上下界都很大的均匀分布。为了捕捉一张大网,我们对均匀分布使用大的上下界。

 lower=-10**6
higher=10**6
**with** pm.Model() **as** first_model:
    *#priors on parameters*
    beta_0=pm.Uniform('beta_0', lower=lower, upper= higher)
    beta_temp=pm.Uniform('beta_temp', lower, higher)
    beta_humid=pm.Uniform('beta_humid', lower, higher)
    beta_light=pm.Uniform('beta_light', lower, higher)
    beta_co2=pm.Uniform('beta_co2', lower, higher)
    beta_humid_ratio=pm.Uniform('beta_humid_ration', lower, higher)

    *#the probability of belonging to class 1*
    p = pm.Deterministic('p', pm.math.sigmoid(beta_0+beta_temp*df['Temperature']+
                               beta_humid*df['Humidity']+
                               beta_light*df['Light']+
                               beta_co2*df['CO2']+
                               beta_humid_ratio*df['HumidityRatio']))
**with** first_model:
    *#fit the data* 
    observed=pm.Bernoulli("occupancy", p, observed=df['Occupancy'])
    start=pm.find_MAP()
    step=pm.Metropolis()

    *#samples from posterior distribution* 
    trace=pm.sample(25000, step=step, start=start)
    burned_trace=trace[15000:]

这可能需要一段时间来运行。一旦完成,我们就可以绘制样本。

pm.traceplot(burned_trace)
plt.show()

我们得出结论,我们的算法确实收敛。我们可以计算这些后验分布的平均值。

coeffs=['beta_0', 'beta_temp', 'beta_humid', 'beta_light', 'beta_co2', 'beta_humid_ration']
d=dict()
**for** item **in** coeffs:
    d[item]=[burned_trace[item].mean()]

result_coeffs=pd.DataFrame.from_dict(d)    
result_coeffs
*#coeff_result=pd.DataFrame(d)* 
*#coeff_result*

与频率统计相比,贝叶斯统计的一个优势是我们拥有的不仅仅是平均值。特别是,我们可以计算这些参数的 95% 高密度区间%2C%202015-,4.3.,highest%20density%20interval%2C%20abbreviated%20HDI.&text=Moreover%2C%20the%20probability%20density%20of,any%20x%20outside%20those%20limits.)。

pm.stats.hpd(burned_trace['beta_0'])
coeffs=['beta_0', 'beta_temp', 'beta_humid', 'beta_light', 'beta_co2', 'beta_humid_ration']
interval=dict()**for** item **in** coeffs:
    interval[item]=pm.stats.hpd(burned_trace[item]) *#compute 95% high density interval*

result_coeffs=pd.DataFrame.from_dict(interval).rename(index={0: 'lower', 1: 'upper'})
result_coeffs

注意,湿度比的系数明显大于其他系数。这并不一定意味着这个变量更重要。如果我们仔细观察数据,我们会发现这个变量取的值非常小。

此外,我们可以探索不同参数之间的关系。例如,让我们来看看β_ CO2 和β_ wet _ ratio 系数。

figsize(12.5, 12.5)
seaborn.jointplot(burned_trace['beta_co2'], burned_trace['beta_humid_ration'], kind="hex") *#color="#4CB391")*
plt.xlabel("beta_co2")
plt.ylabel("beta_humid_ratio");

CO2 和湿度比系数的散点图

曲线图显示这两个系数负相关。注意,CO2 水平和湿度比是正相关的。

回想一下,在经典的逻辑回归中,我们通过最大后验估计 (MAP 解)来寻找最佳参数。换句话说,最佳拟合参数由下式给出

其中,𝑝(𝜃|𝐷)p(θ|D 是给定数据时θ的后验分布,p(D|θ)是似然函数,p(θ)是θ的先验分布。

请注意,由于我们在第一个模型中使用均匀分布,我们可以预期我们的 MAP 解决方案应该与 MLE 解决方案(最大似然估计)一致,后者对应于 frequentist logistic 回归。我们可以使用 Scikit-Learn 库来测试这个语句。首先,我们使用 MAP 计算系数。

coeffs=['beta_0', 'beta_temp', 'beta_humid', 'beta_light', 'beta_co2', 'beta_humid_ration']
d=dict()
**for** item **in** coeffs:
    d[item]=[float(start[item])]

map_coeffs=pd.DataFrame.from_dict(d)    
map_coeffs

接下来,我们使用经典的逻辑回归计算β系数。

**from** **sklearn.linear_model** **import** LogisticRegressionX=df.iloc[:, 1: -1]
y=df['Occupancy']
logit=LogisticRegression()
logit_model=logit.fit(X,y)
pd.DataFrame(logit_model.coef_, columns=X.columns)

是啊!两种方法的系数几乎相同。

接下来,我们讨论了我们的模型的预测能力,并与经典的逻辑回归进行了比较。我们用经典方法记录预测。

logit_prediction=logit_model.predict(X)

为了使用贝叶斯逻辑模型进行预测,我们通过对样本值进行平均来计算𝑦_score。

*#compute the average probability of predicting 1\.* 
y_score = np.mean(burned_trace['p'], axis=0)*#histogram of the distribution*
figsize(12.5,4)
plt.hist(y_score, bins=40, density=**True**)
plt.xlabel('Probability')
plt.ylabel('Frequency')
plt.title('Distribution of $y_score$')
plt.show()

y 分数的分布

有趣的是,p 的大部分集中在 0 和 1 附近。我们也可以使用 y_score 进行预测。

first_model_prediction=[1 **if** x >0.5 **else** 0 **for** x **in** y_score]

让我们通过计算混淆矩阵来评估我们的模型的性能。

first_model_confussion_matrix =confusion_matrix(df['Occupancy'], first_model_prediction)
first_model_confussion_matrixarray([[1639,   54],
       [   3,  969]])

这很好。我们甚至还可以通过其他指标来量化性能。

**import** **sklearn**
**from** **sklearn.metrics** **import** classification_reportprint(sklearn.metrics.classification_report(y, first_model_prediction))precision    recall  f1-score   support 0       1.00      0.97      0.98      1693
           1       0.95      1.00      0.97       972 accuracy                           0.98      2665
   macro avg       0.97      0.98      0.98      2665
weighted avg       0.98      0.98      0.98      2665

我们也可以计算曲线下的面积。

pred_scores = dict(y_true=df['Occupancy'],y_score=y_score)
roc_auc_score(**pred_scores)0.99358530283253

所以,我们的模型表现得相当好。我们来和经典的 logistic 回归比较一下。

print(sklearn.metrics.classification_report(y, logit_prediction))precision    recall  f1-score   support 0       1.00      0.97      0.98      1693
           1       0.95      1.00      0.97       972 accuracy                           0.98      2665
   macro avg       0.97      0.98      0.98      2665
weighted avg       0.98      0.98      0.98      2665

他们是一样的!然而,使用贝叶斯模型,我们获得了更多的信息,因此我们对自己的估计更有信心。

先验分布为正态分布的不同模型。

现在,让我们使用一组不同的先验知识来训练我们的模型。例如,我们可以假设系数遵循正态分布。

**with** pm.Model() **as** second_model: 
    #priors with normal distribution beta_0=pm.Normal('beta_0', mu=0, sd=10**4)
    beta_temp=pm.Normal('beta_temp', mu=0, sd=10**4)
    beta_humid=pm.Normal('beta_humid', mu=0, sd=10**4)
    beta_light=pm.Normal('beta_light', mu=0, sd=10**4)
    beta_co2=pm.Normal('beta_co2', mu=0, sd=10**4)
    beta_humid_ratio=pm.Normal('beta_humid_ration', mu=0, sd=10**4) #probability of belonging to class 1 p = pm.Deterministic('p', pm.math.sigmoid(beta_0+beta_temp*df['Temperature']+
                               beta_humid*df['Humidity']+
                               beta_light*df['Light']+
                               beta_co2*df['CO2']+
                               beta_humid_ratio*df['HumidityRatio']))#fit observed data into the model**with** second_model:
    observed=pm.Bernoulli("occupancy", p, observed=df['Occupancy'])
    start=pm.find_MAP()
    step=pm.Metropolis()
    second_trace=pm.sample(25000, step=step, start=start)
    second_burned_trace=second_trace[15000:]
pm.traceplot(second_burned_trace)
plt.show()

我们再次看到算法确实收敛了。让我们计算 MAP 解的β系数。

coeffs=['beta_0', 'beta_temp', 'beta_humid', 'beta_light', 'beta_co2', 'beta_humid_ration']
d=dict()
**for** item **in** coeffs:
    d[item]=[float(start[item])]

second_map_coeffs=pd.DataFrame.from_dict(d)    
second_map_coeffs

它们与我们在第一个模型中得到的非常接近。更进一步,因为我们在贝叶斯框架中,我们甚至可以比较两个模型的后验分布。例如,让我们看看截距变量。

figsize(12.5,4)
plt.hist(burned_trace['beta_0']-second_burned_trace['beta_0'], bins=40, density=**True**)
plt.title('Distribution of the difference between beta_0')
plt.legend()
plt.show()

虽然 MAP 解对β_0 给出了相同的估计,但我们看到两个后验概率相当不同。让我们也比较一下这两个模型之间β_temp 的后验分布。

figsize(12.5,4)
plt.hist(burned_trace['beta_temp'], label='First model', bins=40, density=**True**)
plt.hist(second_burned_trace['beta_temp'], bins=40, label='Second model', density=**True**)
plt.title('Distribution of of beta_temp')
plt.legend()
plt.show()

实际上差别很小。接下来,让我们计算第二个模型的预测能力。

second_y_score = np.mean(second_burned_trace['p'], axis=0)
second_model_prediction=[1 **if** x >0.5 **else** 0 **for** x **in** second_y_score]
second_model_confussion_matrix =confusion_matrix(df['Occupancy'], second_model_prediction)
second_model_confussion_matrixarray([[1639,   54],
       [   3,  969]])

这与我们从第一个模型中得到的结果相同。我们可以检查一下 y_score 和 second_y_score 几乎是一样的。

figsize(12.5,4)
plt.hist(y_score-second_y_score, bins=40)
plt.title('Distribution of the difference between y_score and second_y_score')
plt.ylabel('Frequency')
plt.show()

内置广义线性模型(GLM)的模型。

在前面的章节中,我们使用实际操作的方法来构建我们的模型。这很容易,因为我们只有几个变量。当变量数量很大的时候,就不会很实用了。幸运的是,PyMC3 有一个内置的广义线性模型,在这个模型中,一切都将自动化。让我们使用这个内置模型来拟合我们的数据。

**with** pm.Model() **as** third_model:
    pm.glm.GLM.from_formula('Occupancy ~ Temperature + Humidity + Light + CO2 + HumidityRatio',
                            df,
                            family=pm.glm.families.Binomial())
    third_trace = pm.sample(25000, tune=10000, init='adapt_diag')pm.traceplot(third_trace)
plt.show()

与以前的模型不同,在这种情况下,我们的参数的后验分布是单峰的。

让我们总结一下这些后验分布。

pm.summary(third_trace)

除了查看汇总的统计数据,我们还可以查看地图解决方案。

**with** third_model:
    map_solution=pm.find_MAP()
d=dict()
**for** item **in** map_solution.keys():
    d[item]=[float(map_solution[item])]

third_map_coeffs=pd.DataFrame.from_dict(d)    
third_map_coeffs

我们看到,第二种和第三种模型的地图解决方案之间存在显著差异。预测呢?

**with** third_model:
    ppc = pm.sample_posterior_predictive(third_trace, samples=15000)*#compute y_score* 
**with** third_model:
    third_y_score = np.mean(ppc['y'], axis=0)
*#convert y_score into binary decisions* 
third_model_prediction=[1 **if** x >0.5 **else** 0 **for** x **in** third_y_score]*#compute confussion matrix* 
third_model_confussion_matrix =confusion_matrix(df['Occupancy'], third_model_prediction)
third_model_confussion_matrixarray([[1639,   54],
       [   3,  969]])

这个混淆矩阵与前两个模型中的相同。第二个和第三个模型的 y 分数分布如何?

figsize(12.5,4)
plt.hist(third_y_score-second_y_score, bins=40)
plt.title('Distribution of the difference between y_score and second_y_score')
plt.ylabel('Frequency')
plt.show(

这种分布集中在 0 左右。换句话说,y_scores 在不同模型间的分布几乎相同。系数呢,比如温度系数?

figsize(12.5,4)
plt.hist(third_trace['Temperature'][-40000:]-second_burned_trace['beta_temp'], bins=40, density=**True**)
plt.title('Difference between the temperature coefficients for the second and the third model')
plt.show()

差值近似遵循具有小平均值的正态分布。

让我们也检查一下湿度系数之间的差异。

figsize(12.5,4)
plt.boxplot(third_trace['Humidity'][-40000:]-second_burned_trace['beta_humid'])
plt.title('Difference between the humidity coefficients for the second and the third model')
plt.show()

同样,这种差异很小。

3.结论

我们看到,即使我们的模型使用不同的先验,预测性能是相似的。这证实了我们的信念,随着我们的数据集变大,它们应该收敛到同一个解决方案。

我们希望我们的项目将帮助 PyMC3 的初学者学习它的语法。我们发现 PyMC3 的代码相当直观,我们希望我们的代码清楚地证明了这一点。

4.参考文献。

[1]https://docs.pymc.io/notebooks/GLM-logistic.html官方 PyMC3 文档

[2]https://Goldin locks . github . io/Bayesian-logistic-regression-with-pymc 3/

PyTorch 上的贝叶斯 LSTM—使用 BLiTZ,PyTorch 贝叶斯深度学习库

原文:https://towardsdatascience.com/bayesian-lstm-on-pytorch-with-blitz-a-pytorch-bayesian-deep-learning-library-5e1fec432ad3?source=collection_archive---------22-----------------------

是时候给你的时间序列预测画一个置信区间了——现在这很简单。

LSTM 细胞插图。来源访问于 2020 年 4 月 14 日

这是一篇关于如何使用 BLiTZ 的帖子,BLiTZ 是一个 PyTorch 贝叶斯深度学习库,使用其贝叶斯 LSTMs 的实现来创建、训练和执行序列数据上的变分推理。

你可以查看这篇文章的示例部分的笔记本这里和 PyTorch 上 BLiTZ Bayesian 深度学习的知识库这里。

为了做到这一点,我们将解释贝叶斯长短期记忆是如何工作的,然后使用 Kaggle 的数据集通过一个股票置信区间预测的例子。

如果你是贝叶斯深度学习主题的新手,你可能想在 Medium 上寻找关于它的许多帖子中的一个,或者只是我们 lib repo 中关于贝叶斯 DL 的文档部分。你可能也想看看这篇关于 BLiTZ 用法教程的文章。

贝叶斯 LSTM 层

正如我们所知,LSTM 架构旨在解决当标准递归神经网络用于处理长序列数据时出现的信息消失问题。

在数学上,我们将 LSTM 架构翻译为:

LSTM 方程。来源:https://en.wikipedia.org/wiki/Long_short-term_memory由我用乳胶改写。访问时间为 2020 年 4 月 14 日。

我们还知道,贝叶斯神经网络的核心思想是,我们可以对它们进行采样以获得概率分布,然后优化这些分布参数,而不是具有确定性的权重。

利用这一点,有可能衡量预测的可信度和不确定性,这与预测本身一样,都是非常有用的洞察数据。

从数学上来说,我们只需要在上面的方程中增加一些额外的步骤。它们是权重和偏差采样,发生在前馈操作之前。

代表在层/模型的位置 N 上在第 I 时间采样的权重的方程。

代表在层/模型的位置 N 上第 I 次采样的偏差的方程。

当然,我们的可训练参数是参数化每个权重分布的ρ和μ。BLiTZ 有一个内置的 BayesianLSTM 层,可以为您完成所有这些艰苦的工作,因此您只需担心您的网络架构和培训/测试循环。

让我们来看看我们的例子。

首先,我们的进口

除了我们常见的进口产品,我们还将从blitz.modules引进BayesianLSTM,从blitz.utils引进variational_estimator一名室内装潢师,对他们进行不同的培训和复杂的成本收集。

我们还引入了collections.deque用于时间序列数据的预处理。

数据预处理

我们现在将创建并预处理数据集,以将其提供给网络。我们将从从 Kaggle 获得的数据集导入亚马逊股票定价,获得它的“收盘价”列,并将其规范化。

我们的数据集将由标准化股票价格的时间戳组成,并将具有形状(batch_size、sequence_length、observation_length)。

让我们导入并预处理数据:

我们还必须创建一个函数来转换时间戳中的股票价格历史。为此,我们将使用一个最大长度等于我们正在使用的时间戳大小的 deque。我们将每个数据点添加到 deque 中,然后将其副本附加到主时间戳列表中:

创建我们的网络类

我们的网络类接收到了variational_estimator装饰器,它简化了对贝叶斯神经网络损失的采样。它将有一个贝叶斯 LSTM 图层,其中 in_features=1,out_features=10,后跟一个 nn。Linear(10,1),输出股票的标准化价格。

正如你所看到的,这个网络是一个非常正常的网络,这里唯一不常见的是BayesianLSTM层实例和variational_estimator装饰,但是它的行为是一个正常的火炬。

完成后,我们可以创建我们的神经网络对象,分割数据集,并继续进行训练循环:

创建对象

我们现在可以创建我们的损失对象,神经网络,优化器和数据加载器。请注意,我们没有随机分割数据集,因为我们将使用最后一批时间戳来评估模型。因为我们的数据集就大小而言非常小,所以我们不会为训练集创建数据加载器。

我们将使用正态均方误差损失和学习率=0.001 的 Adam 优化器

火车环线

对于我们的训练循环,我们将使用variational_estimator添加到我们的神经网络的sample_elbo方法。它对 X 个样本的损失进行平均,帮助我们轻松地进行蒙特卡罗估计。

为使该方法有效,网络的forward方法的输出必须与将被输入损失对象/标准的标签具有相同的形状。

评估模型并收集置信区间

我们将首先用要绘制的真实数据创建一个数据框架:

为了预测置信区间,我们必须创建一个函数来预测相同数据的 X 次,然后收集其平均值和标准差。同时,在参考真实数据之前,我们必须设置我们将尝试预测的窗口大小。

让我们看看预测函数的代码:

和置信区间的收集。请注意,我们可以决定距离均值有多少标准差来设置我们的置信区间:

由于我们使用的样本数量非常少,因此我们用高标准偏差对其进行了补偿。我们的网络将尝试预测 7 天,然后查询数据:

这里我们可以通过查看真实值是低于上界还是高于下界来检查置信区间。设置好参数后,您应该有一个 95%左右的置信区间,如我们所知:

查看预测图表

我们现在只是绘制预测图,直观地看看我们的训练是否顺利。我们将绘制真实数据和测试预测及其置信区间:

基于置信区间的股票价格预测。

为了结束我们的评估,我们将放大预测区域:

带有置信区间的测试数据的网络预测图。

结论

我们看到 BLiTZ 贝叶斯 LSTM 实现使得利用贝叶斯深度学习的所有能力在时间序列上实现和迭代变得非常容易。我们还看到贝叶斯 LSTM 很好地集成到 Torch 中,并且易于在任何工作或研究中使用和介绍。

我们还可以非常准确地预测 IBM 股票价格的置信区间,这可能是一个比点估计有用得多的洞察力。

参考

[## piEsposito/blitz-贝叶斯深度学习

BLiTZ 是一个简单且可扩展的库,用于创建贝叶斯神经网络层(基于 Weight…

github.com](https://github.com/piEsposito/blitz-bayesian-deep-learning) [## 了解 LSTM 网络

2015 年 8 月 27 日发布人类不是每秒钟都从零开始思考。当你读这篇文章时,你…

colah.github.io](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) [## BLiTZ——py torch 的贝叶斯神经网络库

火炬动物园中的贝叶斯层是一个简单且可扩展的库,用于在…

towardsdatascience.com](/blitz-a-bayesian-neural-network-library-for-pytorch-82f9998916c7) [## 神经网络中的权重不确定性

我们介绍了一个新的,有效的,原则性和反向传播兼容的算法学习概率…

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

贝叶斯元学习

原文:https://towardsdatascience.com/bayesian-meta-learning-fa4eedcb89fc?source=collection_archive---------23-----------------------

这个故事介绍了贝叶斯元学习方法,其中包括贝叶斯黑盒元学习,基于贝叶斯优化的元学习,MAMLs 集成和概率 MAML。这是课程的简短总结‘斯坦福 CS330:多任务和元学习,2019 |第 5 讲——贝叶斯元学习’。

via 艺术字

这个故事涵盖了我们为什么需要贝叶斯方法的原因,以及如何实现和评估这些方法。它是课程‘斯坦福 CS330:多任务和元学习,2019 |第五讲——贝叶斯元学习’的总结。

对于元学习算法,3 个算法特性是重要的:表达能力、一致性和不确定性意识。 表现力是 f 代表一系列学习过程的能力,它衡量可扩展性和对一系列领域的适用性。一致性意味着学习的学习过程将解决具有足够数据的任务,这一特性减少了对元训练任务的依赖,从而导致良好的分布外性能。不确定性意识是在学习过程中对模糊性进行推理的能力。它让我们思考如何在强化学习的环境中探索新的环境,以减少我们的不确定性。它还考虑了如果我们处于安全关键环境中,我们想要校准不确定性估计。它也允许我们从元学习的贝叶斯观点来思考,什么样的原则方法可以从那些图形模型中导出?

这个故事涵盖了 1。为什么是贝叶斯?2.贝叶斯元学习方法 3。如何评价巴伊亚人

为什么是贝叶斯?

多任务原则和元学习原则是训练和测试必须匹配,任务必须共享“结构”。“结构”是什么意思?这意味着对共享潜在信息θ的统计依赖性。

来源:课程幻灯片

图形模型,其中θ是所有任务共享的肉参数。φI 是每个任务 I 的特定于任务的参数。特别是,这个图形模型显示了对θ的一些依赖性。基本上,每个参数ϕi 都有一个从θ开始的箭头。如果你的条件以θ为信息,任务参数(ϕs)就变得独立,也就是ϕi 独立于另一个以θ为条件的ϕi。如果你把θ作为潜在信息的条件,那么它们就不是独立的。这些性质表明给定θ的ϕ上的分布比ϕ.的边缘分布具有更低的熵本质上,θ告诉你关于特定任务参数ϕ.的信息

如果您可以识别θ(例如,通过元学习),在哪些情况下,学习ϕ不会比从头开始学习更快?如果ϕs 在知道以θ为条件之前是独立的,这意味着它们的熵将是相同的,那么从零开始学习将与从共享信息θ中学习一样快。如果单个点承载了θ的所有信息,那么共享的信息基本上不会告诉你那么多,因为信息也存在于单个数据点中。以θ为条件的熵会相当高,边际熵也会相当高。如果给定θ的ϕ熵为零会怎样?这意味着在ϕ中没有任何附加信息不被θ捕获,那么θ可以解决所有的任务,你不需要做任何事情来学习θ。

【theta 可能包含什么信息?如果任务族对应于具有不同振幅和不同相位的正弦曲线,那么θ将对应于正弦函数族。在机器翻译的例子中,θ对应于所有语言对的家族,而ϕ中没有出现在θ中的信息将对应于特定语言的特定事物。注意,在这两个例子中,θ比所有可能函数的空间都要窄(这就是为什么原则上我们可以从使用元学习中获益)

如果你有无限多的任务,你应该可以精确地恢复θ,或者基本上高精度地恢复那一族。如果你在没有大量任务的情况下进行元学习会怎样?如果你有一个任务空间,它不一定会覆盖任务的真实分布,但可能会对任务空间进行元过拟合,这样实际上不会恢复对应于所有语言对的θ,但它会找到对应于一组语言对的θ,这些语言对看起来像你的训练数据中的东西,而不是捕捉完整分布的东西。因此,除非测试数据非常接近训练样本,否则你不会有效地适应来自该分布的新事物

少数几个学习问题可能是模糊的。有“+”和“-”两类。对于“+”类,图片的特征可能是“微笑”、“戴帽子”和“年轻”。但是最右边的测试图像包含一些特征,但不是全部,所以很难区分这些测试图像属于哪一类。来源:课程幻灯片

参数方法使用这种分布的确定性估计,而贝叶斯元学习方法试图从这种分布中采样。来源:课程幻灯片

对于参数方法,在给定数据集和元参数θ的情况下,我们恢复的是任务特定参数ϕ的确定性估计。所以你会得到这个分布的点估计。这在哪里/为什么会成为问题?在某些情况下,我们需要的不仅仅是点估计。例如,一些少量的学习问题可能并不完全由他们的数据决定,也许在你有先验信息的证据下,基础函数是不明确的。在本例中,模糊性是因为数据集很小。为了解决这个问题,如果我们可以生成关于底层函数的假设,会怎么样?如果我们可以从这个分布中取样,我们就可以对我们的不确定性进行推理,这对于安全关键的少量拍摄学习非常重要。它允许我们在元学习中主动学习和探索。这就是贝叶斯元学习方法的用武之地。

贝叶斯元学习方法

从计算图的角度来看。来源:课程幻灯片

如果我们关心在我们的预测上生成分布, 一种方法是让函数 f 输出在标签上分布的参数 。例如,如果你的标签 y 是离散的,你让 f 输出对应于离散分类分布概率的东西;您还可以输出高斯分布的均值和方差来表示标签上的高斯分布;或者,如果你有一个更多模态的分布,你可以试着表示高斯混合的均值、方差和混合权重;或者,如果您有一个多维输出标签 y,那么您可以输出一系列条件分布的参数,以允许您表示这些变量的联合分布,这是一个自回归模型。一旦你输出了分布的参数,你就可以用 最大似然估计优化 来训练这些方法,优化分布的均值和方差,或者基本上优化该分布的所有全概率值。

这种方法的好处是它们简单并且可以与多种方法结合。缺点是这种方法不能推理底层函数的不确定性,以确定数据点之间的不确定性如何相关。它还倾向于产生校准不良的不确定性估计。例如,你不能把模型不确定性和标签噪声分开。它也被限制在 y 上的一类特殊分布。

我们能为ϕ做同样的最大似然训练吗?我们不能以完全相同的方式来做,因为我们没有对应于ϕ的标签,除非我们生成标签。

贝叶斯元学习方法

贝叶斯深度学习工具箱

一种可变自动编码器。来源:课程幻灯片

贝叶斯深度学习旨在用神经网络来表示分布。有许多方法可以用神经网络来表示分布。 一种流行的方法 就是使用潜变量模型,然后用变分推理对其进行优化。 具体来说,我们有一个图形模型,其中有潜在变量 Z 和观察变量 x。例如,左边的图形模型是一个可变自动编码器。你可以制定一个似然目标的下限,并使用它来优化 X 上的分布,其中 X 上的分布可能是非高斯的,因为它有这个潜在变量。

另一种方法在某些方面非常流行,也非常简单,那就是 使用基于粒子的分布图 。特别是,您可以在不同的数据引导上训练不同的模型。这些模型中的每一个都对应于你的一个特定的分布,然后你把这些粒子组合起来,代表那个分布的样本。

另一种方法 是表示神经网络参数的权重的显式分布。 然后练习这些分布趋向于带有对角协方差矩阵的高斯分布,这样你基本上就有了每个神经网络参数的独立方差。这使您可以表示函数的分布,但需要注意的是,这种两个参数独立的独立假设在实践中总是被违反。

规格化流程 通过将一些潜在分布转化为你的数据分布,或者从潜在空间转化为你的数据空间,再转化回你的潜在空间,尝试表示数据分布上的函数

在 e 基于能量的模型和 GAN 、 中,估算非标准化密度的方法是对数据使用低能量,对其他所有数据使用较高能量,而其他所有数据都由 GAN 中的生成器近似。

埃尔博。来源:课程幻灯片

这个图形模型包含了观察变量 x,和潜在变量 z .T3【证据下界】或者 ELBO 希望能够估计出一个关于数据的似然性的下界 T5【以便优化数据的似然性。ELBO 可以由关于 q(z|x)的期望加上在 q(z|x)上正则化或操作的熵项来表示。q 是表示 x 和 z 的概率的变分分布,这个可以改写为两项互相加, 第一项对应的是解码器的重构损失,基本上是从推理网络 q 采样后根据解码器的数据的似然性,第二项对应的是推理网络和先验之间的 KL 散度。 P 对应于模型,q 对应于为了逼近似然目标 而引入的变分分布。对于如何表示 p,有几种设计选择:p(z)和 p(x|z)。 P (x|z)可以表示为一个神经网络, 例如,在变分自动编码器的情况下,它表示一个神经网络,该网络接收潜在变量并输出图像或您正在建模的任何数据类型。P(z)通常被表示为具有单位方差的对角高斯。** 它也可以由神经网络来表示,或者表示为学习的平均值和学习的方差。实际上,变分自动编码器通常不学习它,因为之后的层可以将它转换成学习的均值和方差。 q(z|x)也是用神经网络来表示的,推断为推理网络或者你的变分分布。 在深度学习的上下文中使用变分推理时,θ表示模型参数,ϕ表示推理网络的参数。**

重新参数化的把戏。来源:课程幻灯片

但是优化 ELBO 有个问题。ELBO 包含关于 q 的期望,这意味着我们需要能够反向传播到 q 分布中,但是采样是不可微分的 e。我们可以使用 重新参数化技巧对于高斯 q(z|x ),它可以用一种可微分的方式来表示,用从单位高斯采样的噪声来重新参数化。特别是,如果我们将潜在变量的分布表示为与输出均值和方差的神经网络 q 的输出相对应的高斯分布,那么您可以将 q 的输出(高斯分布)表示为由噪声重新参数化,而不是从均值加上方差乘以噪声的特定分布中采样。幸运的是,这个方程是可微的。如果你的推理网络足够有表现力,它应该能够将你的数据分布转换成潜在变量的高斯分布。

这通常被称为 摊销变分推断 ,我们有一个推断网络,它预测变分分布,基本上摊销了估计该分布的过程。元学习可以用摊销变分推理吗?

贝叶斯元学习方法

贝叶斯黑盒元学习

黑盒元学习方法。来源:课程幻灯片

首先,为了简单起见,让我们考虑一下黑盒元学习方法。特别是,我们希望有一个神经网络,它将训练数据集作为输入,并在我们的参数φ上产生分布。然后应用ϕ对神经网络进行参数化,该神经网络将 x 作为输入,将 y 作为输出。目标是在根据我们的训练数据集对特定任务参数进行采样时,能够最大化给定特定任务参数的测试数据点的可能性。

摊提变分推理成元学习。来源: 课程幻灯片

在标准 VAE 中,观察变量是 x,潜在变量是 z。而在元学习中,观察变量是数据集,潜在变量是ϕ.ELBO 开始学习数学。它在特定任务参数ϕ上有一个变化的分布,在这里我们将从给定的ϕ.中取样并估计数据的可能性 KL 项表明 phi 上的变分分布和先验应该是相似的。

来源:课程幻灯片

对于 q 条件有两种设计选择。如果您希望能够将参数作为我们数据集的函数进行采样,那么我们应该对我们的训练数据进行条件 q(这显示在第一个等式中)。这个训练数据和测试数据点的概率有什么不同? 因此,当根据我们的训练数据集 对我们的任务特定参数进行采样时,您希望能够最大化给定我们的任务特定参数的测试数据点的可能性(如第二个等式所示)。

元参数θ。来源:课程幻灯片

元参数θ呢?我们将有一个以θ为条件的特定任务参数ϕ的先验。测试数据点的分布仅是φ的函数。我们也可以θ为条件。

最终目标(为了完整性)。来源:课程幻灯片

最终目标是使所有任务的元参数和期望值最大化。特定于任务的参数从神经网络 q 中采样,然后应用它们来最大化 p 的可能性。右边的一项鼓励 q 接近某个先验分布。

贝叶斯黑盒元学习概述。来源:课程幻灯片

为了总结贝叶斯黑盒元学习,列出了一些好处和缺点。一个好处是它可以表示 y 上的非高斯分布,并且它还生成任务特定参数ϕ上的分布,而不仅仅是生成标签上的分布(y^{ts}).这使得它能够表示基础函数的不确定性,而不仅仅是基础数据点的不确定性。缺点是在给定θ的情况下,它只能表示ϕp 的高斯分布。这有两个原因。一个是重参数化技巧,它适用于高斯。第二件事是,在目标中出现的 KL 项,对于高斯型目标是可以以封闭形式评估的,但是对于其他非高斯型目标是不能以封闭形式评估的。

贝叶斯元学习方法

基于贝叶斯优化的元学习

将基于梯度的元学习重铸为分层贝叶斯。来源:课程幻灯片

我们可以将基于梯度的元学习重铸为分层贝叶斯。这很好,因为它将 MAML 的贝叶斯解释作为一种学习元参数,这样在测试时,您可以在元参数所代表的高斯先验下进行地图推断。它使用特定于任务的参数ϕ的地图估计作为θ的函数,这意味着它表示该分布的点估计,并且它只给出该分布的一组参数,例如,您无法从该分布中进行采样或更容易地表示任务参数的完整分布。

贝叶斯元学习方法

摊销贝叶斯元学习

Q 是任意函数 ,它可以包含一个梯度算子。这是,所以你可以有一个推理网络,基本上是在你的推理网络内执行梯度下降。因为 q 不必是神经网络,它可以是输出ϕ.分布的任何东西 (摊销贝叶斯元学习) 在文中,我们将运行梯度下降 w.r.t .一组参数的均值和该组参数的方差 w.r.t .一些训练数据,然后其他一切都是一样的。 与 MAML 相比,这不仅仅是对参数进行梯度下降,这是对参数的均值和方差进行梯度下降,在这个过程的最后,你会得到参数的均值和方差,而不仅仅是均值。好处是你在测试时运行梯度下降,所以我们得到一个基于优化的元学习方法,基本上是把梯度下降填充到参考网络中。缺点是 p(ϕi|θ)被建模为高斯。

我们可以建立非高斯后验模型吗?

贝叶斯元学习方法

合奏

我们可以通过维护单独的模型实例来模拟非高斯后验。有几篇关于组装哺乳动物的论文。

MAMLs(aka EMAML)的集成训练 M 个独立的 MAML 模型,如果集成成员太相似,就不能很好地工作。我们可以将这种想法应用到集成黑盒和非参数方法中。

来源:课程幻灯片

BMAML 是一个更加多样化的哺乳动物群体,基本上,它将不同的群体成员相互推开,鼓励他们代表不同的模型。 实现这一点的方法是,当你运行梯度下降时,你有典型的似然项,但你也有一个鼓励不同系综成员彼此不同的项。你可以用不同的核函数来表示模型之间的相似性。

BMAML 优化。来源:课程幻灯片

他们不仅仅是将粒子相互推开,还进行了优化,使集合给你一个产生高可能性的粒子分布。因此,他们没有完全分别训练这些不同的模型,而是把它们组合在一起,优化了一个术语,共同优化了它们。所以你在优化这 M 个粒子的平均可能性。

这些集成模型的好处是它们简单,往往工作良好,并且它们可以模拟非高斯后验。缺点是您需要维护 M 个模型实例,或者只在最后一层进行基于梯度的推理。我们可以在所有参数上模拟非高斯后验模型而不必维护单独的模型实例吗?

贝叶斯元学习方法

概率 MAML

我们可以用像哈密尔顿蒙特卡罗这样的程序对参数向量进行采样吗?具体来说,哈密顿蒙特卡罗所做的是添加噪声,然后重复运行梯度下降,以便能够从一些分布中采样。直觉是学习一个先验,一个随意的踢腿可以让我们进入不同的模式。

损失景观。来源:课程幻灯片

在这种损失格局中,有不同的解决模式。一个对应于分类“微笑”和“戴帽子”的分类器,一个对应于分类“微笑”和“年轻”的分类器。我们希望参数向量在中间,这样如果我们给参数向量添加一些噪声,然后运行梯度下降,我们得到这个解的两种不同模式。我们得到不同的函数,代表正确答案的不同模式。

概率 MAML 中测试时的推断。来源:课程幻灯片

在这种情况下,θ将是一个分布,而不是一个单一的参数向量。我们的目标是在测试时给定所有观察到的变量,即x trainy trainx test,对不同的特定于任务的参数进行采样。我们可以跨越x test,因为y test没有给定,其他的保持条件独立,所以你可以从ϕ给定的函数x trainy train中采样。这种分布的精确解是完全难以处理的,因为它需要积分。如果我们知道如何在给定θx trainy train的情况下对 phi 进行采样,那么采样就会变得容易得多。通过地图推断,我们可以用ϕ点估计来粗略地近似这个分布。实际上,我们仍然可以从ϕ采样,首先从θ采样,然后我们运行几个梯度下降步骤。这是在测试时我们想做推理时发生的。训练可以用摊余变分推理来完成,详情可以查阅论文。

概率 MAML 中的祖先抽样。来源:课程幻灯片

祖先取样是什么样子的?有 2 个步骤: 首先我们从θ的 P 中采样,这个 P 有均值和方差;然后我们运行梯度下降,从样本θ开始,运行梯度下降到θ。它允许我们表现这些类型的多模态分布。

这种方法的好处它具有非高斯后验,在测试时简单,并且只有一个模型实例(与 MAML 的系综相反)。缺点是它有更复杂的训练程序。

贝叶斯元学习方法

方法概述

涵盖了三种方法。第一个是训练函数 f 来输出在y test上的分布。好处是它很简单,可以结合多种方法。但是它不能推理基础函数上的不确定性,并且也可以表达y test上的有限类分布。第二种方法是黑盒方法,其中使用潜在变量模型和摊销变分推断。好处是它可以代表y test上的非高斯分布,但它只能代表高斯分布 p(ϕi |θ),当ϕi 是一个潜在向量时是可以的。对于基于优化的方法,我们提到了 3 种类型:摊提推理;集成和混合推理。摊销推断很简单,但它将 p(ϕi |θ)建模为高斯分布。集成方法简单,往往工作良好,具有非高斯分布,但它包含 M 个模型实例。混合推理具有非高斯后验,测试时简单,只有一个模型实例,但训练过程比较复杂。

如何评价巴伊亚人

如何评价一个贝叶斯元学习者?

使用标准基准怎么样,比如 Minilmagenet 精度?好处是它是标准化的,所以我们可以更容易地比较论文。Minilmagene 也有实像。但是像准确性这样的度量标准不能评估不确定性。任务可能不会表现出模糊性,并且不确定性在该数据集上可能没有用。什么是更好的问题和度量?这取决于你关心的问题。

检查这些算法性能的一种方法是看不同的玩具例子。例如,设想您从中取样的基础函数。

来源:课程幻灯片

这个例子对应于基本的元学习函数是正弦函数和线性函数,其中标签中有噪声,使得任务不明确。它所推理的函数类型,在某些情况下,是模糊的,即使它是正弦函数或者线性函数。你可以从抽样分布中看到这种多模态输出。这表明函数实际上可以表示多模态的东西。

来源:课程幻灯片

第二个例子是一个分类的例子,你只给了一个数据点,所有的任务都对应于循环决策边界。你试图区分积极点和消极点。D train仅包含一个正数据点,而D test 包含正负数据点。因此,基本上你可以看到虚线所示的决策边界的可视化,其中神经网络代表这些不同的决策边界,这些边界代表了它接受训练的函数类的结构。

我们也可以使用可能性或准确性的组合以及分布的覆盖范围来衡量性能。或者我们可以绘制预测器的置信度与预测器的精确度的关系图。还有主动学习评价。

参考

  1. 斯坦福 CS330:多任务和元学习,2019 |第 5 讲——贝叶斯元学习
  2. 课程幻灯片
  3. 具有潜在嵌入优化的元学习
  4. 元数据集:用于从少量示例中学习的数据集的数据集
  5. 主动一次性学习—斯坦福计算机科学
  6. 主动学习的学习算法
  7. 自动编码变分贝叶斯
  8. 使用深度集成进行简单和可扩展的预测不确定性估计
  9. 概率模型不可知元学习
  10. 概率模型不可知元学习——NIPS 会议录

英国停车搜索的贝叶斯模型

原文:https://towardsdatascience.com/bayesian-modelling-of-uk-stop-and-search-3f9947272fce?source=collection_archive---------28-----------------------

用贝叶斯推理拟合泊松广义线性混合模型研究停止和搜索的过度使用

国际国王教会在 Unsplash 上拍摄的照片

在英国和国际上,关于过度使用拦截和搜查的讨论越来越多。看看英格兰和威尔士警察部队拦截和搜查次数与逮捕次数的比例,我们可以调查不同种族群体之间是否存在差异。具体来说,泊松广义线性混合模型被实施以允许种族群体固定效应和警察力量随机效应。该模型符合使用 Gibbs 抽样的贝叶斯推断,并且我们发现在样本中对于我们的种族群体效应的实质性差异。这证明了警察部队在地理层面过度使用拦截和搜查。这个项目的 bug 模型的实现可以在 GitHub 上找到。

背景

现有文献旨在调查过度使用拦截和搜查。Bowling 和 Phillips (2007 年)提供了关于英国文献的广泛总结和讨论,认为统计数据显示对黑人个人使用拦截和搜查权力是不成比例的。这里要看的一个常见统计数据是按种族划分的每个居民的停留和搜索次数。这可以从折线图中看出,例如,在 2019 年,每 1000 名黑人居民中黑人个体被拦下和搜查的次数比每 1000 名白人居民中白人个体被拦下和搜查的次数多 9 倍以上。

Bowling 和 Phillips (2007)强调,按常住人口标准化的统计数据经常受到批评,因为没有考虑潜在的不同犯罪参与和“可用性”。在这里,Miller (2000)将“可用”定义为描述一个人在停车和搜查发生的时间和地点使用公共场所。此外,Miller (2000)确实发现了常住人口和可居住人口的差异,与常住人口相比,来自黑人、亚洲人和少数民族背景的个人在可居住人口中的比例过高。因此,在这个项目中,拦截和搜查是按逮捕比例进行调查的。但是,应该注意的是,如果在拦截和搜查过程中存在偏见,在逮捕过程中也可能存在偏见,因为这两个过程通常都需要“合理的理由”。似乎可以合理地假设,如果存在的话,这些偏见将具有相同的方向,因此,按照逮捕的比例来看待拦截和搜查可以作为不相称的最低门槛。

数据

拦截和搜查个人层面的数据是公开的,由英国警方提供。对于这个项目,我们已经采取了 2015 年 1 月至 2020 年 2 月(含)英格兰和威尔士警方报告的所有拦截和搜查(约 190 万次)。探索这些数据很有趣,例如,最常见的搜索对象是毒品(56%),而攻击性武器仅占所有搜索对象的 10%。此外,大约 70%的拦截和搜查导致没有采取进一步行动,只有大约 15%导致逮捕。如上面的堆积条形图所示,除了逮捕之外,还可以采取范围广泛的进一步行动。

每份拦截和搜查报告都包括警察力量和自我定义的种族。因此,拦截和搜查次数是按种族和警察队伍汇总的。由 Office⁴.内政部提供的按族裔群体分列的被捕人数也是公开的这些是在 2015 年 3 月至 2019 年 3 月期间收集的。该地图显示了“拦截搜查差距”,即黑人被拦截和搜查的次数与黑人被逮捕的次数的比例白人被拦截和搜查的次数与白人被逮捕的次数的比例。停止逮捕差距大于 1 反映了黑人相对于白人更频繁地被停止和搜查,与逮捕成比例。警察力量似乎有很大差异,支持在我们的泊松广义线性混合模型中使用随机警察力量效应。

泊松广义线性混合模型

泊松广义线性混合模型的实施考虑到了种族群体的固定效应和警察力量的随机效应,可以被看作是盖尔曼和 al.(2007)⁵.的扩展作者用种族群体固定效应和警察辖区随机效应研究了纽约的拦截和搜查。因此,该项目的实施着眼于更大范围的警察部队与辖区的区域单位以及英格兰和威尔士与纽约的地理区域。我们的最终模型如下所示。

该模型采用马尔可夫链蒙特卡罗方法进行贝叶斯推理拟合。具体来说,选择 Gibbs 抽样是因为模型的层次结构,并且使用了 BUGS 软件。假设所有未知参数都有非信息先验。运行三个平行链,并结合轨迹图使用 Gelman-Rubin 统计来评估收敛性。通过 2,000,000 次迭代和 1,000,000 次老化,达到了令人满意的收敛证据。10 的细化用于适应 bug 内存限制。

结果

结果表显示了通过取样本平均值估计的后验平均值。此外,可信区间代表 95%的高后验密度区间。任何种族群体截距的可信区间都不会跨越零,因此给定种族群体效应的值大于零的概率为 95%。由于对数关联函数,必须采用后验均值的指数来量化族裔群体对警察部队拦截和搜查次数的影响,以及与逮捕的比例。因此,通过取后验平均值的指数,我们可以看到,亚裔、黑人和混血儿被拦截和搜查的次数分别是白人的 1.52 倍、1.30 倍和 1.20 倍,与被逮捕的人数成比例。最后,下面的轨迹图显示在左侧,支持收敛的证据。此外,在右侧,种族群体效应的密度图看起来平滑且呈单峰。此外,零度以下的密度非常低。

结论

由于难以控制潜在变化的犯罪参与和可利用性,衡量过度使用拦截和搜查存在很大困难。该项目通过观察拦截和搜查与逮捕的比例来解释这些情况,作为不相称的最低门槛。将警察部队一级的拦截搜查和逮捕汇总,发现不同族裔群体的拦截搜查率与逮捕率之间存在差异。据估计,亚洲人、黑人和混血儿被拦截和搜查的频率分别是白人的 1.52 倍、1.30 倍和 1.20 倍,与被捕人数成比例。这与 Gelman 等人(2007)在纽约警区的发现一致。有缺陷的 Gibbs 抽样被证明是模拟后验分布的一种灵活有效的方法。此外,随机效应的方差参数的可信区间不跨越零,支持混合效应模型的实现。最后,如果在较低的地理水平上可以获得逮捕数据,那么用较小的区域单位重复这种分析,以调查是否有证据表明警察部队内部的随机效应,将是有用的。

参考

[1]鲍林,b .和 c .菲利普斯(2007)。不相称和歧视:审查警察拦截和搜查的证据。现代法律评论。

[2]米勒,J. (2000 年)。可用于停靠和搜索的人口分析。内政部警察研究系列。

[3]英国警方(2020 年)。停下来搜索数据。【https://data.police.uk/data/】T4。

[4]家庭办公室(2019)。警察权力和程序英格兰和威尔士统计。https://www . gov . uk/government/collections/police-powers-and-procedures-England-and-Wales。

[5]赫尔曼、法甘和基斯(2007 年)。在种族偏见的背景下对纽约市警察局拦截搜身警察的分析。美国统计协会杂志。

贝叶斯网络和合成节点

原文:https://towardsdatascience.com/bayesian-networks-and-synthetic-nodes-721de16c47e2?source=collection_archive---------37-----------------------

之前,我已经直观地介绍了什么是 bn以及如何构建它们。在这篇文章中,我给出了一个更正式的观点,并讨论了建模的一个重要元素:合成节点。

虽然神经网络基于可用数据给出答案,但贝叶斯网络(BNs)包括与我们的研究相关的非样本或先验人类专业知识。通常,采访专家询问几个参数的影响是收集所有信息的最佳方式,这使得贝叶斯网络比其他技术更丰富。将这种专业知识与样本数据相结合使这种技术变得强大。此外,他们提出了模型的图形表示结构,在这种情况下,这比神经网络等黑盒模型更好。更容易解释获得的结果并与专家交流:当与不是建模技术专家而是商业领域(即医疗保健或风险管理)专家的人一起工作时,这提供了优势。BNs 的另一个优势是它们能够通过专家知识和原始数据来构建,即使先前的知识是不完整的。可以从专家的知识开始,用数据提炼,然后用专家的知识进行反馈,等等。

贝叶斯网络综述

贝叶斯网络(BN)是概率模型的一部分,该概率模型通过图表示一组变量及其依赖关系,即一对 G = (V,e),其中 v 是不同节点的有限集合,E ⊆ V×V 是弧的集合。有序对( u,v ) ∈ E 表示从节点 u 到节点 v 的有向弧, u 被称为 v 的父节点, vu 的子节点(Pearl 1988)。

BN 通常是表示概率因果关系的有向无环图(DAG ),其中节点表示变量,弧线表示变量之间的依赖关系。更准确地说,节点是随机变量的状态,从父节点指向子节点的弧线是两个节点之间的因果条件依赖。假设父节点状态的概率不同,则因果关系由节点状态的概率表示。

BN 使用条件概率来描述事件。任何关于事件或假设的不确定性的信念都是暂时的。这被称为先验概率或“P(H)”。这个先验概率被新的经验“e”更新,提供了关于“H”的不确定性的修正信念。给定证据的新概率称为后验概率或“P(H|e)”。贝叶斯定理描述了后验概率和先验概率之间的关系“P(e|H)”是假设假设为真,证据为真的概率,而“P(e)”表示在所有可能的假设下,新证据为真的概率。

条件概率表(CPT)展示了节点之间的概率关系。下图在三个基本图表上显示了这种关系。在这个例子中,每个节点有两种状态:真(T)和假(F)。该图还显示了每个节点配置的不同 CPT。

三个基本的 BN 模型

对于 BN,条件概率分布可以表示为一组参数:

其中 i = 1,…, n 定义每个节点; k = 1,…,r i 定义每个 r i 变量值(节点的状态);并且 j= 1,…,qi 定义了父变量节点的 qi 变量配置的集合(例如上图中的每个图形配置)。因此,对于父节点的 q 个 i 个有效配置中的每一个,存在具有向量的多项式分布

例如,在上图的共同效果图中,黄色 P(Z=T | X=T,Y=F)中的参数表示假设 X 为真,Y 为假,Z 为真的条件概率。

BN 配置的参数化需要矢量的完全估计。随后,两种类型的分析是可能的:(1)反向推理,它允许给定的一个观察发现最可能的原因中的假设(诊断),和(2)自上而下的推理,它允许估计概率的一个观察给定的假设(预测)(Pearl 1988)。

使用合成节点

在 BN 中,对于由 pa (Xi)表示的节点 Xi 的一组父节点,节点值的联合概率分布可以写成每个节点及其父节点的局部概率分布的乘积:

计算目标节点的概率分布所需的变量的数量随着父节点的数量及其状态的数量而增加,这是耗时的。合成节点应该减少计算目标节点 CPT 所需的数据量。正如(康斯坦蒂努等人,2016)提到的,“合成节点是一个简单地由它的父节点的值使用一些专家驱动的组合规则定义的节点”。因此,合成节点对于减少因果复杂性和 CPT 中组合爆炸的有害影响是有用的。此外,这些节点改善了 BNs 的结构,即因果关系的可视化。通过使用合成节点,CPT 的大小和复杂性“大大降低,提高了模型的计算速度和准确性(Fenton 和 Neil 2013)。

例如,上图(a 部分和 b 部分)显示了从简单网络开始使用合成节点的方案。在这个例子中,网络有四个变量 a、b、c 和 d,每个变量有四个状态,计算 P(A|D,b,c)的 CPT 的概率值的数目是 4^4 = 256。相反,通过引入合成节点 s,该计算可以简化为两个表 P(A|B,s)和 P(S|C,d)。现在,该模型需要使用 4^3 + 4^3 = 64 值而不是 256 值来计算 s 和 a 的两个 CPT。

(Neil 等人,2000)中描述的合成节点的使用示例

“从从业者的角度来看,考虑到当前算法的准确性和速度,使用最新的软件工具编译和执行 BN 的过程相对来说没有痛苦。然而,为特定问题构建完整的 BN 的问题仍然存在,即 如何构建图结构以及如何为图 的每个节点定义节点概率表。”(尼尔、芬顿和尼尔森 2000)。

感谢阅读!!

如果你想理解贝叶斯网络的逻辑(一个更基本的信息),我推荐你这篇文章:

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

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

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

如果你想了解构建贝叶斯网络的参数(和超参数)是什么,我建议你这样做:

[## 贝叶斯网络中的超参数调整问题

在这段历史中,我们讨论了在基于贝叶斯理论建立模型时要考虑的结构标准

towardsdatascience.com](/the-hyperparameter-tuning-problem-in-bayesian-networks-1371590f470)

参考书目

康斯坦蒂努、安东尼·科斯塔、诺曼·芬顿、威廉·马什和卢卡斯·拉德林斯基。2016."从复杂的问卷调查和访谈数据到用于医疗决策支持的智能贝叶斯网络模型."医学中的人工智能 67:75–93。

芬顿、诺曼和马丁·尼尔。2013.用贝叶斯网络进行风险评估和决策分析。Crc 出版社编辑。

尼尔、马丁、诺曼·芬顿和拉斯·尼尔森。2000."建立大规模贝叶斯网络."知识工程评论 15(3):257–284。https://doi.org/10.1017/S0269888900003039.

**珠儿,朱迪亚。1988."智能系统中的概率推理."摩根考夫曼圣马特奥。https://doi.org/10.2307/2026705.

贝叶斯神经网络:1 为什么烦恼?

原文:https://towardsdatascience.com/bayesian-neural-networks-1-why-bother-b585375b38ec?source=collection_archive---------33-----------------------

贝叶斯神经网络

由法鲁尔·阿兹米在 Unsplash 上拍摄

这是贝叶斯深度学习系列的第一章。下一章可用 此处 而第三章则是 此处

我经常被要求解释我对贝叶斯神经网络的古怪兴趣。所以这是一系列关于他们的开始。因此,我可以有把握地说,这是一系列关于深度学习未来的开始——一个现在就可以实现的未来。在接下来的几周里,您将学习如何使用为贝叶斯型神经网络构建的一个新库。我将包含代码并讨论 TensorFlow-Probability 和 Pytorches Pyro 的工作,包括安装、训练和预测各种不同的网络架构。在本章中,我们将讨论以下目标:

了解为什么贝叶斯神经网络如此有用和令人兴奋
了解它们与普通神经网络的不同
理解您可以获得的不确定性度量是一个主要优势
安装一个库,开始处理所有随机的事情

今天,许多深度学习的开发者并不是从计算机科学或学术背景开始的。反复试验,对一本书和一些博客的耐心大有帮助。不出所料,贝叶斯深度学习不需要任何不同。

但是一些基础理论知识的优势比平时更大。令人放心的是,这可以压缩,表达和理解相当简单。首先,是不寻常的术语引起了混淆。因此,在开始之前,我们将用一些代码来讨论它们。

我们对随机变量感兴趣。这意味着大多数变量在需要的时候都会改变值。所以非正式的随机变量是不可靠的东西(更正式的说法是我们称之为‘随机变量’,但是谁会从正式中受益呢?).使用张量流概率(TFP)或 Pytorches Pyro,您可以调用:

rv_normal = dist.Normal(loc=0., scale=3.)
rv_normal.sample([1])

这将返回一个值,每次我们运行第二行时,这个值都是不同的。即使我们不重新运行第一行也是如此,因为 rv_normal 是由正态(高斯)分布定义的随机变量。

因此,您可以将这些随机变量插入到神经网络中,并使用它们来代替我们通常用于权重的点值。你为什么要这么麻烦?因为在网络被训练之后,我们所做的每一个预测都将具有不同的随机可变权重。所以,整个模式会不一样。然而——在我放开你之前,我们用随机变量构建的神经网络的重要性在于,这些变量就像被拴在狗链上一样,只能返回特定范围内的值。这是因为我们的神经网络训练已经训练了我们的正态分布,使其钟形峰值位于最佳值附近。

从所有这些中可以得出三点:
分布拥有随机变量,每次我们做预测时,这些随机变量都会返回我们的随机权重值。
我们的神经网络训练移动整个分布,而不仅仅是一个点权重值。
这类似于在传统神经网络中使用分布初始化权重的过程(用于权重的初始值)。除了我们在整个训练和预测中继续使用分布,而不仅仅是初始化。

训练分布更正式地称为调节分布(类似于巴甫洛夫调节他的狗。(我似乎既不能逃避形式,也不能逃避狗)。所以所有这些复杂的随机变量和分布加起来就是一件事..,不同的预测。但是,如果我们已经很好地训练了贝叶斯神经网络,我们的预测将非常相似(对于连续、浮点、回归输出)和相同(对于分类输出)。).如果我们训练我们的神经网络不好,我们每次都会得到非常不同的结果。如果贝叶斯网络可以说话,它会说它的预测相似或非常不同之间的差异是它的不确定性。将不确定性视为信心(只有贝叶斯神经网络不喜欢谈论他们的信心,所以称它为不同的东西)。如果我们建立了一个良好的网络架构,最重要的是如果我们提供了良好的数据,神经网络将给出自信的预测,如果我们做的一切都不好,我们将得到不自信的预测。在贝叶斯魔法术语中,当我们给出坏消息时,神经网络会更加不确定,而当我们给出好消息时,神经网络会更加不确定。术语上的神奇差异因为贝叶斯神经网络从来都不是确定的,它们只是不太确定。而我们传统的神经网络总是确定一切!当你第一次开始使用神经网络时,你可能已经看到了类似的东西。您完成了对第一个模型的训练,并且表现一般,然后您在不做任何更改的情况下训练了另一个模型,平均来说仍然表现一般,只是您得到了完全不同的结果。贝叶斯神经网络就像那样,只是不是依靠你的挫折来保持训练有微小差异的神经网络,而是通过贝叶斯方法,你训练一次,就内置了无限数量的模型。

太棒了。掌声。那又怎样?所以…我们可以改变这一切,通过观察结果的可变性来看我们的数据(主要)有多适合这项任务。但比贝叶斯模型好得多的是,我们通常能够用比神经网络常规所需数据更少的数据来训练模型。贝叶斯模型将很好地推广。它也较少受到每个训练类的数据量不平衡的困扰——这是表现不佳的一个被忽视的原因。

说够了,我的好人,告诉我们怎么做。对哦。

首先,您需要安装两个主要概率编程库中的一个,以遵循本系列。虽然您可以仅使用核心库来构建贝叶斯神经网络,但您需要手动实现训练代码,这不会在数学和隐藏错误方面感到害羞。所以我们要么用 Pyro(建立在 Pytorch 之上),要么用 TensorFlow-Probability(可能很明显建立在 TensorFlow 之上)。如果您有使用某个核心库的经验,最好继续使用它,并从您的熟悉中获益,而不是改变它。滚动到你喜欢的一个相关的库部分,或者如果你是一个受虐狂,继续执行它们,然后给我发电子邮件。

张量流概率

我们将使用 TensorFlow 2 作为基础库,它有一些类似于 PyTorch 的实现,尽管受益于我们将在后面章节中使用的许多特性。TensorFlow 通常也受益于语言和平台的可移植性。您可以从从 Java 到 C#的几乎任何语言中调用用 Python TensorFlow 编写的模型,并非常容易地将模型部署到移动设备上。

TensorFlow 和 TensorFlow-Probability 很容易安装。确保你已经安装了 Python(Python 3,如果你还没有这个或者任何 Python 发行版,我强烈推荐你从:www.anaconda.com下载 Anaconda 发行版,它包含了你在这里开始所需要的一切。)

安装张量流和张量流-概率:

如果要使用 Anaconda/Miniconda 安装 TensorFlow,请使用 conda 软件包管理器并键入:

conda install tensorflow

或者对于 GPU 支持:

conda install tensorflow-gpu

在撰写本文时,如果你想获得 GPU 支持,用 conda 而不是 pip 安装有一些好处。conda 版本自动安装数学库,显著提高 CPU 训练性能。使用 conda 安装 GPU(tensor flow-GPU)也更容易,因为默认情况下,它会安装 CUDA 和 cuDNN,而这两个软件需要使用 pip 进行独立安装。GPU versoins 要求机器上有 CUDA(即 NVIDIA) GPU。然而,conda 并不像 pip 那样包含那么多不同的库,当同时使用 pip 时很容易崩溃。

要使用 pip 安装计算(非 GPU)版本:

pip install — upgrade tensorflow==2.*

或者,如果您想使用带画中画的 GPU 版本:

pip install — upgrade tensorflow-gpu==2.*)

如果你不确定,选择第一个。2 号。*部分确保安装最新的 2 个版本。该系列大部分可以通过 TensorFlow 1.13 以上的版本完成,但需要在导入 tensor flow 后使用:tf.enable_eager_execution()激活急切执行(在 TF2 默认激活),此外还需要在该系列后面的章节中进行一些其他更改。

注意: 在安装 TensorFlow-Probability 之前必须安装核心 TensorFlow 库,意外的是 TensorFlow-Probability 安装不会为你安装核心库作为依赖。

通过 conda 安装 TFP,包括:

conda install -c conda-forge tensorflow-probability

对于 pip:

pip install — upgrade tensorflow-probability

然后检查一切是否正常,创建一个新的 Jupyter 笔记本,IPython 实例或 Python 脚本,并添加:

import tensorflow as tf
import tensorflow_probability as tfp
dist = tfp.distributionsrv_normal = dist.Normal(loc=0., scale=3.)
print(rv_normal.sample([1]))

你会认出这一章开头的最后两行。你在对一个随机变量进行采样,所以作为输出,你应该得到一个张量,它包含了每次执行最后一行时不同的随机值。

安装 Pytorch 和 Pyro:

对于 Pyro,你首先需要安装 PyTorch。通常,这可以通过 conda 以下列方式最容易地完成:

 conda install pytorch-cpu torchvision-cpu -c pytorch

或者如果有 NIVIDA GPU 可供您使用:

 conda install pytorch torchvision cudatoolkit=9.0 -c pytorch

Pip 安装也是可能的,但不幸的是平台的 CUDA 版本有很大不同,因此如果你只想使用 pip,建议你参考 pytorch.org 的安装指南。

Pyro 随后安装有:

conda install -c gwerbin pyro-ppl

或者

 pip install pyro-ppl 

注意:软件包‘Pyro’(没有-ppl)是完全不同的软件,与 Pytorch-Pyro 无关。

要开始使用 Pyro,创建一个 Jupyter 笔记本,Ipython 控制台或 python 脚本并键入:

import torch
import pyro
import pyro.distributions as dist
rv_normal = dist.Normal(loc=0., scale=3.)
print(rv_normal.sample([1]))

你会认出这一章开头的最后两行。你在对一个随机变量进行采样,所以作为输出,你应该得到一个张量,它包含了每次执行最后一行时不同的随机值。

摘要

你已经学习了随机变量和分布之间的关系,并看到了它的作用。您实现了一个位于 0、标度为 3 的正态分布。位置是分布平均值的另一个词,而标度是标准差的另一个词。然而,我们将坚持使用术语位置和比例,因为这些术语有助于我们在处理其他(非正态)分布时保持一致。

下周我们将学习如何实现贝叶斯神经网络,并进一步了解这些分布和随机变量的适用范围。我打赌你等不及了!订阅博客以获得关于下一版本的通知。

[1]:你可能也听说过 PyMC3,这是另一个很好的库,你可以用它来构建概率模型。然而,PyMC3 总体上特别倾向于统计建模,对使用神经网络的人不太友好(例如,自动签名和 GPU 支持更具挑战性)。

[2]:例如,TensorFlow 2 删除了设置图形所需的“会话”上下文,转而使用函数。

[3]:如果你不能选择使用哪个库,你会发现 TensorFlow-Probability 比 Pyro 更容易使用和理解。然而,这份关于 Pyro 的文档非常好,但是从神经网络的角度来解释 TFP 却很简单。

贝叶斯神经网络:TensorFlow 和 Pytorch 中的 2 个完全连接

原文:https://towardsdatascience.com/bayesian-neural-networks-2-fully-connected-in-tensorflow-and-pytorch-7bf65fb4697?source=collection_archive---------10-----------------------

贝叶斯神经网络

Photo by 青 晨 on Unsplash

本章继续贝叶斯深度学习系列。可用上一章 此处 和下一章 此处 本章我们将探索传统密集神经网络的替代解决方案。这些备选方案将调用神经网络中每个权重的概率分布,从而产生单个模型,该模型有效地包含基于相同数据训练的神经网络的无限集合。我们将用这些知识来解决我们这个时代的一个重要问题:煮一个鸡蛋需要多长时间。

章节目标:

  • 熟悉密集贝叶斯模型的变分推理
  • 了解如何将正常的全连接(密集)神经网络转换为贝叶斯神经网络
  • 了解当前实施的优点和缺点

这些数据来自煮鸡蛋的实验。煮鸡蛋的时间和鸡蛋的重量(以克为单位)以及切开鸡蛋后的发现一起提供。调查结果分为三类:欠熟、半熟和全熟。我们想从鸡蛋的重量和煮的时间得到鸡蛋的结果。这个问题非常简单,以至于数据几乎是线性可分的⁠.但也不尽然,因为没有提供鸡蛋的预煮寿命(冰箱温度或室温下的橱柜储存),你会看到这改变了烹饪时间。没有缺失的数据,我们无法确定打开鸡蛋时会发现什么。知道了我们有多确定我们可以影响这里的结果,就像我们可以影响大多数问题一样。在这种情况下,如果相对有把握鸡蛋没有煮熟,我们会在敲开之前多煮一会儿。

让我们先看看数据,看看我们在处理什么。如果你想亲自感受这种不同,你可以在github . com/doctor loop/Bayesian deep learning/blob/master/egg _ times . CSV获取数据。您将需要 Pandas 和 Matplotlib 来探索数据。(pip install —升级 pandas matplotlib)将数据集下载到您正在工作的目录中。如果不确定,可以从 Jupyter 笔记本的单元格中键入 pwd 来查找目录的位置。

https://gist . github . com/doctor loop/5a 8633691 f 912d 403 e 04 a 663 Fe 02 E6 aa

https://gist . github . com/doctor loop/21e 30 BD F16 D1 f 88830666793 f 0080 c 63

图 2.01 鸡蛋结果散点图

让我们看一下柱状图。

https://gist . github . com/doctor loop/2 a5e 95 a68a 29315 f 167 E0 e 875 E7 FAE 16

图 2.02 按结果划分的排卵次数直方图

我似乎不太擅长做我喜欢的半熟鸡蛋,所以我们看到了一个相当大的阶级不平衡,相对于半熟的可爱鸡蛋,半熟鸡蛋的数量是半熟鸡蛋的两倍,熟鸡蛋的数量是半熟鸡蛋的三倍。这种类别不平衡可能会给传统的神经网络带来麻烦,导致它们表现不佳,并且不平衡的类别大小是一个常见的发现。

注意,我们没有将 density 设置为 True (False 是默认值,因此不需要指定),因为我们对比较实际数字感兴趣。而如果我们要比较从三个随机变量中的一个中采样的概率,我们会希望设置 density=True,以将数据总和的直方图归一化为 1.0。

直方图对于数据的离散化可能很麻烦,因为我们需要显式指定(或使用算法为我们指定)收集值的箱数。箱的大小极大地影响了数据的显示方式。作为一种替代方法,我们可以选择使用核密度估计,但在比较组时通常会更好,因为我们在这里使用的是小提琴图。violin 图是一种混合图,带有显示平滑分布的箱形图,便于比较。在 python 中,用 seaborn 库来绘制 violin 图既容易又漂亮(pip install —升级 Seaborn)。但是为了保持一致,我将在 matplotlib 中显示它。

https://gist . github . com/doctor loop/C5 BAC 12d 7 b 7 EBD 7758 cc 83 f 0 Fe 931 fc 0

图 2.03 按结局划分的鸡蛋次数小提琴图。中间的条形表示平均值。

好极了。现在让我们强调一下我们实际上要学习的神经网络之间的架构差异。我们将首先实现一个经典的密集架构,然后将其转换成一个强大的 Bayesianesque 式的对等物。我们使用基本库(TensorFlow 或 Pytorch)实现密集模型,然后使用附加库(TensorFlow-Probability 或 Pyro)创建贝叶斯版本。不幸的是,TensorFlow 实现密集神经网络的代码与 Pytorch 的代码非常不同,所以请转到您想要使用的库部分。

张量流/张量流-概率

源代码可从以下网址获得

【github.com/DoctorLoop/BayesianDeepLearning/ 号

https://gist . github . com/doctor loop/3a 67 FD 1197 a 355 f 68 f 45076 be 0074844

我们使用 Keras 来实现,因为这是我们后面的 TFP 模型所需要的。我们通过调用编译后的模型开始训练,如下所示。

https://gist . github . com/doctor loop/f6c 74509046068 AE 7 AC 37 EFE 00d 08545

你会看到 TensorBoard 是用来记录我们的训练的——利用 TensorBoard 作为其强大的模型调试手段和 TensorFlow 的关键功能之一是很好的。如果我们想在训练期间在单元格下输出训练进度,我们可以使用 Keras 输出,将 model.fit 的 verbose 参数设置为 1。Keras 输出的问题是它会打印每个时期的损失。这里我们训练了 800 个纪元,所以我们会得到一个又长又乱的输出。因此,最好创建一个定制的日志记录器来控制打印损失的频率。自定义记录器的源代码非常简单,可以在 Github 的笔记本中找到。TensorBoard 回调(和任何自定义记录器)都被传递给 callbacks 参数,但如果您不想只记录笔记本中的每个纪元,可以忽略这一点。Keras 的伟大之处在于,它会为我们拆分数据进行验证,从而节省时间。这里 10%的数据用于验证。有些人使用 25%的数据进行验证,但由于数据是神经网络最重要的考虑因素,数据集往往相当大,因此 10%的数据很好,并使模型更有可能达到我们的训练目标。Github 笔记本还展示了如何使用类权重来解决我们之前讨论的类不平衡问题。最后,如果培训时间很重要,请确保验证不频繁,因为验证比培训本身慢得多(特别是使用自定义记录器时,大约慢 10 倍),从而使培训时间更长。

最终损耗在 0.15 左右,精度 0.85。如果你在 1200 个历元之后训练超过 800 个历元,你会发现验证的准确性在下降,尽管损失仍在下降。这是因为我们已经开始过度适应训练数据。当我们过度拟合时,我们使我们的模型依赖于特定的训练实例,这意味着它不能很好地概括我们看不见的验证数据或模型⁠.的预期真实世界应用过度拟合是传统神经网络的祸根,传统神经网络通常需要大型数据集和早期停止方法来缓解。

但我们是来学习解决方案而不是问题的!进入我们的贝叶斯神经网络阶段,它可以抵抗过度拟合,不会特别担心类别不平衡,最重要的是 在很少数据的情况下表现得非常好

让我们看一下模型的贝叶斯实现。

https://gist . github . com/doctor loop/f 00 c 18 f 591553685 e 06 a 79 fdb 4 b 68 e 0

它与我们的传统模型非常相似,只是我们使用了 TensorFlow-Probability 的 flipout 层。我们指定一个核散度函数,它是前面提到的 Kullback-Leibler 散度。大概就是这样。

Pytorch/Pyro

当比较传统的密集模型和贝叶斯等价模型时,Pyro 做的事情不同。对于 Pyro,我们总是先创建一个传统的模型,然后通过添加两个新的函数来进行转换。传统模型需要提供一种从权重分布中自动采样值的方法。采样值被插入到传统模型上的相应位置,以产生训练进度的估计。从上一章你会记得训练如何调节(训练)体重分布。在清晰的语言中,这意味着训练改变了正态分布,并改变了它们的比例来代表每个权重。然而,为了进行预测,我们仍然插入单一重量的固体值。虽然我们不能使用整个分布来进行预测,但是我们可以进行许多预测,每个预测使用不同的采样权重值来近似分布。这就是我们首先构建的密集模型非常适合的地方。

我们将从一个类开始来封装我们的密集模型。完整的源代码可以在 https://github.com/DoctorLoop/BayesianDeepLearning 的在线笔记本上找到。

https://gist . github . com/doctor loop/33b 192030388 c 46 d0a 2591459 b2f 6623

我们设置了三层,只有前两层使用激活功能。然后,我们指定了损失函数和优化器。请注意,对于这个模型,我们使用的是 torch.optim.Adam (Pytorch 优化器),而不是 Pyro 优化器。如果你试图在这里使用 Pyro,它会抛出错误,因为参数是不同的。如果你以前用过 Pytorch,我们的训练循环没有什么特别的。800 个纪元完全是多余的,但那又怎样。

https://gist . github . com/doctor loop/75854 f 26 bee 106 d9 b 596 B2 ee 0544 C5 D5

[Out]:
…
Test accuracy: 0.88
Final loss:0.173 at epoch: 799 and learning rate: 0.001

这里的表现非常好,速度也很快。如果你是 Pytorch 的新手,并且在其他地方有经验,你可能会对 softmax 的缺乏感到惊讶。在 Pytorch 中,需要注意的是 softmax 内置于 CrossEntropyLoss 中。

让我们继续升级它。这是我提到的两个新功能,模型和向导。

https://gist . github . com/doctor loop/a 4d cf 6 b 0 f 7 f1 ECE 43087534 ebdfcaa 08

我们将在本系列的另一篇文章中详细讨论这些函数的作用。简而言之,该模型明确声明了用于每个图层的分布,以替换点值。而指南声明了用于调节(训练)这些分布的变量。您会注意到这些函数看起来很相似,但仔细观察后,模型列出了权重和偏差的单独分布,然后指南列出了模型 中每个权重和偏差分布的平均值和标准差 的分布。这听起来有点玄乎——因为确实如此。把思考留到以后,现在就感受一下训练。

https://gist . github . com/doctor loop/5a 3837 c 384181 b 391 df 5927 BD D5 e 2 ab 5

训练这个美丽的怪物很快。我们得到的精度略高于密集模型 0.88–0.90,损失为 0.18。我在这里实现了一些额外的函数来使训练更容易(trainloader 和 predict 函数),并在 GitHub 笔记本中提供了完整的源代码。

贝叶斯深度学习的损失函数

我们不能通过随机变量反向传播(因为根据定义它们是随机的)。因此,我们欺骗和重新参数化这些分布,并让训练更新分布参数。随着这一根本性的变化,我们需要一种不同的方法来计算培训损失。

你可能已经知道传统模型中使用的负对数似然。它反映了模型生成数据的概率。现在不要担心这意味着什么。相反,我们通过取大量样本的平均值来估算这一损失。但是,随着我们的负对数可能性,我们结合了一个新的损失,利用计算中的分布。新的损失是 kull back-lei bler 散度(KL 散度),并提供了两个分布如何彼此不同的度量。我们会经常提到 KL 散度,并发现它在其他领域也很有用,包括 uncertainty⁴.指标负对数似然被加到 KL 散度上以得到 ELBO 损失(边际似然的预期下限,也称为变分自由能)。ELBO 损失允许我们在训练期间近似分布,并且在可训练性和训练时间方面受益巨大。

最后,作为总结,让我们来看看当我们做预测时会发生什么,毕竟这是我们在这里的目的。

https://gist . github . com/doctor loop/41 c 31 BF 30339 DC 1 B4 B4 c 7 e 69 a 001 b 9 BF

我们制作 5000 个样本(这可能需要几分钟,取决于您的计算机)。使用传统的神经网络,所有这些预测都将是完全相同的,因此这将是一个毫无意义的努力。但是我们不再使用传统的神经网络。

https://gist . github . com/doctor loop/1 ae0d 213d 3875 DD 569d 582 c 810769 fc 7

图 2.04:3 个测试输入的 5000 个样本的直方图

预测函数从我们用 TFP 或 Pyro 训练的主模型中采样多个不同的模型版本。我们输入的三个测试实例都产生了定义明确的峰值。第一个测试实例(红色直方图)的重量为 61.2 克,沸腾时间为 4.8 分钟。大多数时候,我们可以看到我们的模型预测它将是一个半熟的鸡蛋,但有 5%的时间它预测一个半熟的鸡蛋,有 2%的时间它认为它将是一个半熟的鸡蛋。该模型对此预测相当有信心,但不如第二个测试示例(绿色直方图)有信心,第二个测试示例几乎总是预测煮了 6 分钟的 53g 鸡蛋的煮熟结果。如果每次预测都不一样,我们如何从模型中获得一致性?我们只是取平均值。如果预测太易变,即每类中有三分之一,我们就不想做预测,除非我们可以根据信息采取行动,告诉用户模型对结果不确定(或者问问我们自己是否需要对模型/数据做更多的工作!)在这两种情况下,我们都获得了传统模型无法提供的非常有力的信息。因此,我们可以认为传统模型总是傲慢的,而我们的新模型是恰当的。很谨慎,但是自信正确的时候很自信。我们不需要成为计算机科学心理学家来欣赏更好的模型——人格。

总结

在这一章中,我们已经探索了基本贝叶斯模型的变化,并看到了伴随它的一些主要优势。我们已经在 TensorFlow-Probability 和 Pyro 中看到了如何做到这一点。虽然该模型功能齐全,但在现阶段它并不完美,也不是真正的贝叶斯模型。“更真实”的模型是否重要取决于你的环境。在随后的文章中,我们将讨论 softmax 的使用等缺陷,以及如何解决这些问题。在下一篇文章中,我们的主要关注点将是使用贝叶斯卷积深度学习进行图像预测。如果我的写作看起来更正式一点,我可能会更有信心在那里看到你!

1 因此,当更简单的模型可以做得很好的时候,用神经网络来解决问题有点滥用。

2 不确定这里的实际应用是什么,早餐咖啡馆?

3 如果你的想法是:哇,张量流概率代码看起来简单多了,因为它现在为你做了运算。也就是说,我们可以通过使用 Pyro autoguide 来简化 Pyro 代码。正如它所暗示的那样,这对你起着向导的作用。但我们在这里是为了学习贝叶斯深度学习的神奇之处,所以我们需要在某些时候曝光!

4 有趣的是,我们可以通过直接使用 KL 散度来制作具有合理性能的简单分类器,即,可以使用局部二进制模式算法和 KL 来构建图像模式分类器。在这种伙伴关系中,KL 比较输入图像和具有已知图案的图像之间的角和边缘的分布。

贝叶斯神经网络:3 贝叶斯 CNN

原文:https://towardsdatascience.com/bayesian-neural-networks-3-bayesian-cnn-6ecd842eeff3?source=collection_archive---------16-----------------------

贝叶斯神经网络

知道什么时候被骗的超级深度学习

图像由 DoctorLoop 提供

这是贝叶斯深度学习系列的第三章。上一篇可用 此处可用

我们已经知道神经网络是傲慢的。但是标准神经网络的另一个缺点是容易被欺骗。想象一下,一个 CNN 肩负着像人脸识别这样道德上有问题的任务。它从安全摄像头获取信息。但是,当安全摄像头发送一只狗、一个人体模型或一个儿童玩偶的照片时,会发生什么呢?CNN 仍然会输出被类似人脸的东西欺骗的分类。CNN 呼吁贝叶斯治疗,因为我们不希望我们的工作被愚蠢的错误所破坏,因为在错误分类的后果很严重的地方,我们想知道网络有多可靠。一个娃娃,或者任何一个真人,成为通缉犯的可能性有多大?我们需要知道。

章节目标

  • 了解如何实现贝叶斯卷积模型
  • 了解我们如何在从未见过的情况下识别坏的输入数据
  • 理解贝叶斯神经网络的参数问题如何影响训练

正如我们在以前的文章中发现的,贝叶斯分析处理的是分布而不是单个值。我们在正态分布中看到了这一点,在正态分布中,我们得到了一个连续的浮点值,并返回了最有可能的平均值。分类的分布变成了离散的(钢琴键而不是小提琴弦)。对于概率,我们将得到一个特定的结果,比如一个类、一个指数(或者一个音符,如果我们挤压音乐类比的话)。这种分布是由我们模型中的逻辑信息决定的。

能够用少得多的数据表现得很好,同时具有更好的概括能力,这使得贝叶斯神经网络更受欢迎。而且这还没有考虑其他优势。然而,贝叶斯实现的一个缺点在本章变得很重要。贝叶斯实现需要更多的参数。考虑到整个分布替换了每个权重值参数,令人惊讶的是只需要两倍的参数。很容易看出相当具体的“两倍”数字来自哪里,因为重量分布大多是正态分布,而这些正态分布各自有两个参数。

在《离经叛道庄园》中,作者自然地创造了一个奇怪的新数据集来突出这个问题。我们发现自己在帮助父母解决一个重要的问题。父母总是对测量他们孩子的身高感兴趣。嗯,他们再也不用担心整天带着尺子到处跑了。我们将创建一个从图片中估计高度的模型。一个由 836 个婴儿和初学走路的孩子的剪影以及他们的身高组成的数据集已经被创建。因此,我们解决的不是分类问题,而是回归问题。我们的目标是返回一个与照片中孩子的身高相对应的浮点值。这是一个比上一章的分类练习稍微难一点的问题,并且由于蜘蛛的偶尔出现而变得更加困难。虽然训练集只包括有效的人类轮廓,但训练后我们会加入蜘蛛只是为了好玩。这就是有趣的地方,因为我们想避免返回昆虫的身高测量值,但是我们不允许有任何训练中的昆虫的照片。

用于训练的儿童原始剪影示例(左右两幅图像),位于不可用于训练的多毛蜘蛛剪影的两侧。这些剪影都被随机缩放至原始尺寸的 1/2–2 倍。

当然,蜘蛛通常比孩子小。因此,为了防止简单的基于大小差异的歧视,蜘蛛被升级以占据与儿童相当的空间。此外,为了让这项任务变得相当困难,孩子们被随机地重新调整了比例,所以他们的轮廓在原来的 1/2 到 2 倍之间。当然,当我们对孩子的身高感兴趣时,重新调整没有多大意义!但是这个精心设计的愚蠢问题完美地展示了贝叶斯深度学习的力量。您将看到这些模型如何很好地概括真实世界的情况,只有很少的训练示例,并且没有任何他们可能收到的损坏数据的示例!

让我们陷入张量流概率的问题。完整的代码和数据可以在 Jupyter 笔记本上在线获得:https://github.com/DoctorLoop/BayesianDeepLearning。首先,我们将定义架构。

贝叶斯卷积架构(https://gist . github . com/doctor loop/293 AE 5c C3 BDA a2 CCC 333d 9 b 216 eacc 301)

在第一行中,我们清除任何可能已经在内存中的会话,清空任何参数存储和变量,这样就不会干扰新的运行。接下来,我们定义一个 lambda 函数,帮助我们通过上一章讨论的 Kullback-Leibler (KL)散度更新损失。然后,我们将这个λ传递给每个卷积层,以便可以参考近似分布和我们的先验分布之间的差异来更新损耗。严格来说,这并不是绝对必要的,因为该层的默认参数几乎相同。然而,不同之处在于,默认参数仅获得 KL 散度,我们更进一步,将其除以示例总数(836)。默认实现将 epoch 的总 KL 应用于每个示例。但是我们更喜欢的是将总的历元 KL 的一部分应用到每个例子中,而不是每次都应用总的 KL。虽然两者都将训练,我们看到通过缩放损失更好的结果。自己实验看看。

实际模型的定义与任何其他 keras 序列一样。当然,我们使用的是卷积 2DFlipout 层(我们将在后面讨论),而不是通常的 Conv2D。你可能会感到惊讶,我们只使用两个卷积层,而使用数百个卷积层已经足够了。我们使用两个只是因为结果令人印象深刻,对于这个问题,我们真的不需要更多。我们还在神经元层之间加入了两个最大池层,两者都有相当大的步幅/池大小。如果你有一个问题,需要特别敏感的像素完美的测量,你可能要尝试删除这些。当然,这样做的代价是硬件需求的增加,所以建议对两者进行比较。

最后一层是单个密集(贝叶斯)神经元,因为我们只对一个输出感兴趣。这个输出将是我们的测量。就这么简单。

最后用均方误差损失(MSE)编译模型。这是欺骗性的,因为虽然我们只指定了 MSE,但我们也在每一层上添加了 KL。然而,我们自己定义了吉隆坡,因为我们是独立的 Bayesianists 谁想要给 Keras 一个当之无愧的休息。当我们在培训期间打印损失时,我们将看到 KL 参与的证据。它明显不同于(大于)单独的 MSE。两者的区别就是我们的 KL。

培养

让我们开始训练,看看这次损失:

贝叶斯卷积模型的训练说明(https://gist . github . com/doctor loop/4b 10 c 410 a 709 e 0 DFD 71 ace 8 b 004255 BC

[Out]:
....
Epoch 250/250
151/151 [==============================] - 1s 4ms/step - loss: 12.5878 - mse: 5.1539 - val_loss: 16.3906 - val_mse: 8.9721

这里没有什么需要注意的。损耗比较高而批量比较低!

为了首先解决损失问题,我们会反复发现,与传统模型相比,贝叶斯模型的损失值是一个更差的模型性能指标。第一个原因是因为我们合并了至少两个损失。当然,我们感兴趣的是损失的变化,而不是明确的值,但即使这样,变化也不总是清晰的,因为我们经常在训练期间逐步改变两个损失的相对影响。我们将在后面的章节中讨论这些考虑因素。现在只需要记住,看到一个分类模型损失几千(!)同时拥有完善的验证指标。

虽然有些人可能会嘲笑我微不足道的批量,并认为资源是稀缺的——他们错得不能再错了。使用贝叶斯模型,批量大小对训练的影响比我们预期的要大得多。这是我们经常认为我们理解的神经网络理论的一些领域的一个例子,但这将要求我们重新审视我们的信念。我们通常认为批量大小对训练速度至关重要。一些人也欣赏更大批量带来的减少的差异。然而使用贝叶斯模型,批量大小直接影响培训绩效。通过重复运行批量为 5 和 50 的相同模型来观察一下。您会注意到,当批量大小为 50 时,epochs 当然会快得多,但我们从未获得像批量大小为 5 时那样好的损失或性能指标。这不是一个小差异,而是巨大的差异!这很重要,因为很快就会清楚,批量大小是贝叶斯深度学习成功的一个非常有影响力的超参数。

很快就会清楚,批量大小是贝叶斯深度学习成功的一个非常有影响力的超参数

虽然起初我们有另一个超参数要优化,这似乎令人沮丧,但我们会发现自己能够通过一个非常简单的架构变化来提升性能,这比我们过去依赖的架构更简单(在本文底部的附录中,我们将讨论像 Flipout 这样推动这些变化的层)。

推理

最后我们得出结论。我们对从贝叶斯主模型中做出多重预测感兴趣。每个输出都略有不同,因为每个预测都将由一个新的模型做出,该模型填充了从我们训练的贝叶斯主模型的权重分布中采样的权重。

两个列表理解,每个为两个不同的输入图像生成 1000 个预测。https://gist . github . com/doctor loop/09552736976 a7e 0 a 32 E3 f 27d 28 a4 ee1 c

在上面的代码中,我们使用列表理解方式进行循环预测。如果我们只提供一个输入数组(1000 x 126 x 126 x 1)并一次做出所有的预测,不是更快吗?事实上这会快得多。但与此同时,它会违背目的,因为它是一个单独的模型。predict 调用从我们的贝叶斯训练的分布中采样新的权重。因此,每个预测调用负责创建一个独特的新模型,该模型受我们在培训中创建的分布的约束。如果我们输入 1000 张图片,只进行一次预测调用,所有的预测都将是相同的,因为我们将使用单个权重样本,从而模拟一个标准模型。我们更感兴趣的是利用贝叶斯训练创建的无限模型包的能力。我们称之为模型集合,我们利用多个不同模型的集合来获得相同数据的许多不同观点。许多观点的一致是最重要的,它告诉我们输入数据的质量。

根据有效输入(baby_predictions)和无效输入(spider_predictions)绘制预测。https://gist . github . com/doctor loop/41 Abe 385934 fb0f 7728 ba 048564 e26d 4

针对单个有效输入(绿色)的 1000 个高度预测和单个无效输入(红色)的 1000 个高度预测的密度图。当模型被给予具有蜘蛛的无效输入时,预测的分布显示了预测之间的不一致,表明高度不确定性。对有效婴儿轮廓的测量预测的相似性显示了指示有把握的预测的预测一致性。

在上面的代码和图中,我们制作了一张婴儿图片(绿色)和一张蜘蛛图片(红色)的 1000 个高度预测的密度图。我们可以看到,对婴儿身高的预测非常紧密地聚集在 51 像素左右(其平均值和期望值)。而大约 30%的预测正好是这个测量值(恰好是真实值),并且几乎所有的预测都在事实的一个像素之内!另一方面,虽然对蜘蛛的预测也集中在一个值(90 像素)上,但只有不到 4%的预测是在期望值上,并且预测在从 51 像素一直到 134 像素的范围内分散得更广。显然蜘蛛上的预言彼此不一致。因此,我们可以凭直觉认为,我们的贝叶斯模型对于无效对象的预测是不确定的,而我们的贝叶斯模型对于来自训练的对象的相关预测是有信心的。这正是我们想要的。

在下一篇文章中,我们将探索如何使简单的贝叶斯模型比复杂的标准模型更好。我们还将了解如何利用其他类型的不确定性来指导培训,以及如何优化和比较模型以找到最佳方案。

附录:张量流-概率卷积层

如果你最近阅读了文档或任何论文,你可能已经找到了解决贝叶斯深度学习的不同方法。TensorFlow Probability 为卷积层实现了两种方法(更多方法可用于密集层)。第一个是重新参数化层:

TFP . layers . convolution 2d 重新参数化。重新参数化允许我们通过分布的最可能值来计算梯度。因此,我们操纵描述分布的参数,而不是神经网络中的权重值。处理分布参数意味着实际的分布可以被忽略,并被有效地抽象掉。描述分布的参数可以被认为是分布对象的替身,就像纸币代表黄金等实物资产一样。在这两种情况下,替身都是首选,因为这样更方便。在训练中,我们方便地避免了通过随机变量尝试反向传播的尴尬(尴尬是因为它不起作用)。

重新参数化速度很快,但遗憾的是,实际上需要将一批实例的所有权重设置为相同的值。如果重量被单独记录而不是共享,内存需求将会激增。共享权重是有效的,但是增加了方差,使得训练需要更多的历元。

flipout 层:TFP . layers . convolution 2d flipout 采用不同的方法。虽然类似,但它受益于一个特殊的损耗梯度估计器。这种 flipout 估计器在小批量中摇动权重,使它们更加相互独立。反过来,与重新参数化方法相比,抖动减少了方差,并且需要更少的训练时期。但是有一个问题。虽然 flipout 需要更少的历元,但它实际上需要两倍的计算!幸运的是,这些计算可以并行化,但我们仍然会发现一个模型每个时期需要 25–50%的时间(取决于硬件),即使训练总共需要更少的时期。

在没有重新参数化分布的情况下,我们打破了大样本给出更好估计的假设。虽然我们中的许多人并没有从这些方面考虑训练,但我们一直依赖于这个假设。因此,通过重新参数化,我们描述了最可能值的变化,而不是样本中最可能的变化,我们无法预测样本中最可能的变化,因为变量不是随机的,如果我们可以预测的话。

具有张量流概率的贝叶斯神经网络

原文:https://towardsdatascience.com/bayesian-neural-networks-with-tensorflow-probability-fbce27d6ef6?source=collection_archive---------2-----------------------

概率模型不确定性预测的逐步指南。

图片 via 维基百科。

介绍

机器学习 模型通常从数据开发为 确定性 机器,其使用通过 最大似然 方法计算的参数权重的点估计来映射输入到输出。然而,在后台有很多统计上的侥幸。例如,数据集本身是来自叠加了加性噪声的未知分布的任意大小的点的有限随机集合,并且对于这种特定的点集合,不同的模型(即不同的参数组合)可能是合理的。因此,对于正在进行的参数和预测,存在一些 不确定性贝叶斯统计 提供了一个框架来处理所谓的不确定性,随着 张量流概率概率建模 的发布,这已经变得容易多了,我将在这篇文章中演示。要知道不会提供任何理论背景;关于这个话题的理论,我真的可以推荐 Gelman 等人的书《贝叶斯数据分析》,这本书是免费的 PDF 文件。

**** [## “贝叶斯数据分析”这本书的主页

这是本书的 pdf 格式,可以下载用于非商业目的。

www.stat.columbia.edu](http://www.stat.columbia.edu/~gelman/book/)

贝叶斯神经网络

贝叶斯神经网络 的特征在于其在权重(参数)和/或输出上的分布。取决于是否考虑了听觉的、认知的或两者都考虑的不确定性,贝叶斯神经网络的代码看起来略有不同。为了演示工作原理,来自 De Vito 的空气质量数据集将作为一个例子。它包含来自不同污染物化学传感器的数据(如电压)以及作为一年时间序列的参考数据,这些数据是在一个汽车交通繁忙的意大利城市的主要街道上收集的,目标是构建从传感器响应到参考浓度的映射(图 1),即构建一个校准函数作为 回归 任务。

图 1: 参考和传感器数据。注意参考数据中的相关性。(图片由作者提供)

启动

如果您还没有安装 TensorFlow Probability,您可以使用 pip 来完成,但是在此之前创建一个虚拟环境可能是一个好主意。(由于命令在以后的版本中可能会改变,您可能希望安装我用过的那些。)

**# Install libraries.**pip install tensorflow==2.1.0
pip install tensorflow-probability==0.9.0

打开你最喜欢的编辑器或者 JupyterLab。导入所有必要的库。

**# Load libriaries and functions.**import pandas as pd
import numpy as np
import tensorflow as tf
tfk = tf.keras
tf.keras.backend.set_floatx("float64")
import tensorflow_probability as tfp
tfd = tfp.distributions
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import IsolationForest**# Define helper functions.**scaler = StandardScaler()
detector = IsolationForest(n_estimators=1000, behaviour="deprecated", contamination="auto", random_state=0)
neg_log_likelihood = lambda x, rv_x: -rv_x.log_prob(x)

接下来,获取数据集(链接可以在上面找到)并将其作为熊猫数据框架加载。由于传感器容易因老化而漂移,最好丢弃过去六个月的数据。

**# Load data and keep only first six months due to drift.**data = pd.read_excel("data.xlsx")
data = data[data["Date"] <= "2004-09-10"]

预处理

数据相当杂乱,必须先进行预处理。我们将关注大部分时间测量的输入和输出(一个传感器很早就死了)。删除缺少值的行后,对数据进行缩放。之后,使用 隔离林 检测并移除异常值。

**# Select columns and remove rows with missing values.**columns = ["PT08.S1(CO)", "PT08.S3(NOx)", "PT08.S4(NO2)", "PT08.S5(O3)", "T", "AH", "CO(GT)", "C6H6(GT)", "NOx(GT)", "NO2(GT)"]
data = data[columns].dropna(axis=0)**# Scale data to zero mean and unit variance.**X_t = scaler.fit_transform(data)**# Remove outliers.**is_inlier = detector.fit_predict(X_t)
X_t = X_t[(is_inlier > 0),:]**# Restore frame.**dataset = pd.DataFrame(X_t, columns=columns)**# Select labels for inputs and outputs.**inputs = ["PT08.S1(CO)", "PT08.S3(NOx)", "PT08.S4(NO2)", "PT08.S5(O3)", "T", "AH"]
outputs = ["CO(GT)", "C6H6(GT)", "NOx(GT)", "NO2(GT)"]

数据处理

TensorFlow 提供了一个 数据集类 来构造训练集和测试集。我们将使用 70%的数据作为训练集。集合被混洗并且重复的批次被构造。

**# Define some hyperparameters.**n_epochs = 50
n_samples = dataset.shape[0]
n_batches = 10
batch_size = np.floor(n_samples/n_batches)
buffer_size = n_samples**# Define training and test data sizes.**n_train = int(0.7*dataset.shape[0])**# Define dataset instance.**data = tf.data.Dataset.from_tensor_slices((dataset[inputs].values, dataset[outputs].values))
data = data.shuffle(n_samples, reshuffle_each_iteration=True)**# Define train and test data instances.**data_train = data.take(n_train).batch(batch_size).repeat(n_epochs)
data_test = data.skip(n_train).batch(1)

模型结构

听觉不确定性

为了解决由输出中的噪声引起的听觉不确定性,密集图层与概率图层相结合。更具体地,输出的均值和协方差矩阵被建模为输入和参数权重的函数。第一个隐藏层应包括 10 个节点,第二个隐藏层需要 4 个节点用于均值,加上 10 个节点用于最终层中的四维(有 4 个输出)多元高斯后验概率分布的方差和协方差。这是通过使用最后一层 ( MultivariateNormalTriL)的params_size 方法来实现的,这是 后验概率分布 结构的声明,在这种情况下是多元正态分布,其中仅估计了协方差矩阵的一半(由于对称性)。模型中的参数总数为 224 个——由 变分法 估算。这个神经网络的确定性版本由一个输入层、十个 潜变量 (隐藏节点)和一个输出层(114 个参数)组成,其中不包括参数权重的不确定性。

**# Define prior for regularization.**prior = tfd.Independent(tfd.Normal(loc=tf.zeros(len(outputs), dtype=tf.float64), scale=1.0), reinterpreted_batch_ndims=1)**# Define model instance.**model = tfk.Sequential([
tfk.layers.InputLayer(input_shape=(len(inputs),), name="input"),
tfk.layers.Dense(10, activation="relu", name="dense_1"),
tfk.layers.Dense(tfp.layers.MultivariateNormalTriL.params_size(
len(outputs)), activation=None, name="distribution_weights"),
tfp.layers.MultivariateNormalTriL(len(outputs), activity_regularizer=tfp.layers.KLDivergenceRegularizer(prior, weight=1/n_batches), name="output")
], name="model")**# Compile model.**model.compile(optimizer="adam", loss=neg_log_likelihood)**# Run training session.**model.fit(data_train, epochs=n_epochs, validation_data=data_test, verbose=False)**# Describe model.**model.summary()

activity_regularizer 参数作为输出层的先验(权重必须根据批次数进行调整)。根据您机器的规格,培训可能需要一段时间。该算法需要大约 50 个历元才能收敛(图 2)。

图 2: 有训练和验证损失的学习曲线。(图片由作者提供)

听觉和认知的不确定性

考虑到听觉和认知的不确定性(参数权重的不确定性),密集层必须与 翻转 层(DenseFlipout)或 变化 层(DenseVariational)交换。这种模型有更多的参数,因为每个权重都由具有非共享平均值和标准偏差的正态分布来参数化,因此参数权重的数量加倍。对于不同的预测,权重将被重新采样,在这种情况下,贝叶斯神经网络将表现得像一个 集合

tfp.layers.DenseFlipout(10, activation="relu", name="dense_1")

权重的默认先验分布是tfd.Normal(loc=0., scale=1.),可以使用kernel_prior_fn 参数进行调整。

预言;预测;预告

因为是概率模型,所以执行 蒙特卡罗实验 来提供预测。特别是,样本 x 的每一次预测都会产生不同的输出 y ,这就是为什么必须计算许多单独预测的期望值。此外,可以通过这种方式确定方差。

**# Predict.**samples = 500
iterations = 10
test_iterator = tf.compat.v1.data.make_one_shot_iterator(data_test)
X_true, Y_true, Y_pred = np.empty(shape=(samples, len(inputs))), np.empty(shape=(samples, len(outputs))), np.empty(shape=(samples, len(outputs), iterations))
for i in range(samples):
    features, labels = test_iterator.get_next()
    X_true[i,:] = features
    Y_true[i,:] = labels.numpy()
    for k in range(iterations):
        Y_pred[i,:,k] = model.predict(features)

**# Calculate mean and standard deviation.**Y_pred_m = np.mean(Y_pred, axis=-1)
Y_pred_s = np.std(Y_pred, axis=-1)

图 3 显示了所有输出的测量数据与预测值的对比。 决定系数 约为 0.86,斜率为 0.84——不算太差。

图 3: 测量值与预测值的一致性。(图片由作者提供)

预测的不确定性可以通过绘制误差线和期望值来可视化(图 4)。在这种情况下,误差棒是标准偏差的 1.96 倍,即占概率的 95%。

图 4: 数据与预测的比较。(图片由作者提供)

理论上,由于额外的不确定性信息,贝叶斯方法优于确定性方法,但由于其高计算成本,并不总是可行的。最近的研究围绕着开发新的方法来克服这些限制。

[## 用贝叶斯推理量化预测的不确定性

贝叶斯统计最重要的特征之一。

towardsdatascience.com](/uncertainty-quantification-of-predictions-with-bayesian-inference-6192e31a9fa9)****

贝叶斯优化——第一部分

原文:https://towardsdatascience.com/bayesian-optimization-an-intuitive-explanation-130e97fa4e18?source=collection_archive---------30-----------------------

一个直观的,没有数学的介绍

马里乌斯·马萨拉尔在 Unsplash 上的照片

优化是现代机器学习的核心。为什么?线性回归,最小化误差平方和。逻辑回归,最小化负面可能性。支持向量机,最小化两个支持向量之间的负距离。

让我们用更简单的术语来理解优化,而不是用数学定义和等式来解释。“今天是这个月的最后一天,你只剩下 30 美元了。你渴望吃一些美味的食物。你想在比萨(每块 5 美元)、汉堡(每块 3 美元)和可乐(每块 1 美元)中至少选择一种。你不能吃超过 4 个披萨,至少要两个汉堡”。这就对了。现实生活中的优化问题:在某些约束条件下最大化或最小化目标函数

上述问题是线性还是非线性优化?线性优化涉及仅由线性项(或一次项)组成的目标函数,如果它有任何二次项或非线性方程,则它是非线性优化。

在本文中,我们将只关注非线性优化范例——解决这些问题比解决线性问题要复杂得多..

我们来玩个游戏吧!有一个函数 f(x),我就不透露了。这个函数接受实数。任务是这样的:你必须在区间[-150,350]内逼近函数的最小(最低)值。我会告诉你你问的任意 x 值的函数值。但是这里有一个问题,你只有有限的请求,确切地说,只有 5 个。在-150 和 350 之间有无限个实数,所以要小心选择。

假设您的第一个问题是简单明了的 0。

任何理性的人都会选择一个正数和一个负数,所以让我代表你们来做。我将在 x = 150 和 x=-50 时分享 f(x)

那是一组有趣的点,不是吗?你和我想的一样吗?选择-50 附近的下一个点,检查我们的函数是否在那里有最小值?用最优化的术语来说就是叫做 剥削 。这就像,当你知道与其他值相比,某一点的函数值接近我们想要的值时,你会继续利用那个区域。我不想浪费我最后的两次机会。可能在 0 到 100 之间,我可能有我们想要的值,这个区域我们还没有探索过。在优化术语中,这被称为 探索 ,你已经知道你的函数对于几个值输出什么,所以我们将探索新的区域来找到我们想要的值,而不是利用已知的值。一个好的优化算法应该在探索和利用之间取得平衡

讨论完以上内容,让我们使用最后两种猜测:一种是利用,一种是探索。让我们把 x 作为-100 和 100。

开发得到了回报,我们现在在 x=-100 处有一个最小值(相对于我们所做的 5 次猜测),但是我们仍然不知道它是否是真正的最小值。

这种智能地选择迭代中的下一个点来寻找所需值的现象就是贝叶斯优化优雅地做的事情。

没有太多的数学知识,我将尝试使用图形来解释它如何评估。最后一次,我保证没有数学。

一个有效的优化算法如何计算函数在哪里有最小值?它必须遍历给定范围内的所有值,并评估每个值的函数值——就像网格搜索一样。这是非常繁琐和非常不准确的,尤其是如果它是一个多元函数或一个有许多局部最小值。

现在,我们将看到贝叶斯优化是如何处理人类的思维方式,但在统计意义上。

所以,当我给定第一个输入为 x=0 时,我们得到了对应的 f(x)值。贝叶斯优化使用高斯过程来模拟通过该点的不同函数。什么是高斯过程?这超出了本文的范围(可能是下一篇)。但是现在,想象你在空间中有一个点,我要求你画出通过这个点的各种线。

不同的人有不同的想象力

如果你仔细观察,会发现有一个浅蓝色的阴影,它非常亮,你可能看不到,但你仍然会想,为什么在我们知道的输出值下,它不存在?这是我对我画的图的信心,也就是说,我对实际函数的图看起来像这样没有信心,但是如果你看到在已知值处我没有任何方差,这是因为我知道 f(x)在该点的确切值。

现在,当我们得到新的值时,让我们运用我们的想象力和近似图。

当我们得到 f(x)在 x=-50,150 处的值时,就可以近似得到这个图

当我们得到 f(x)在 x=-100,100 处的值时,就可以近似得到这个图

早些时候我告诉你,我已经用我的想象力绘制了上面穿过我们猜测的点的怪异线条,对吗?“我在某种程度上使用高斯过程来模拟曲线。这样,贝叶斯优化在每个新值之后逼近函数图。基于以前的值选择下一个点的智能方法是通过所谓的获取函数,它在探索和利用之间取得了良好的平衡。这只是一个直观的介绍为什么你应该选择贝叶斯优化,我希望你对它的工作原理有所了解。为了深入理解它,我们需要数学,就像我将在后续文章中尝试涉及的许多数学一样。

最后,我给出了我们试图找出最小值的图表,

如需任何澄清/反馈,或者如果您想在数据科学项目上进行合作,请通过 LinkedIn 联系我

在深入贝叶斯之前,我建议你精通传统的优化方法,比如牛顿拉夫森,你可以在这里找到我的文章,牛顿拉夫森第一部分,第二部分,第三部分

参考资料:

https://arxiv.org/abs/1012.2599

用通俗的语言解释贝叶斯优化概念

原文:https://towardsdatascience.com/bayesian-optimization-concept-explained-in-layman-terms-1d2bcdeaf12f?source=collection_archive---------7-----------------------

由 kazuend 在 Unsplash 拍摄的照片

假人的贝叶斯优化

贝叶斯优化已经广泛用于机器学习领域的超参数调整。尽管涉及到许多术语和数学公式,但背后的概念却非常简单。这篇文章的目标是分享我所学到的贝叶斯优化与教科书术语的直白解释,并希望,它将帮助你在短时间内理解什么是贝叶斯优化。

超参数优化综述

为了文章的完整性,让我们从超参数优化方法的基本概述开始,一般有 4 种类型:

手动搜索、随机搜索、网格搜索和贝叶斯优化

贝叶斯优化不同于随机搜索和网格搜索,因为它使用过去的性能来提高搜索速度,而其他两种方法是统一的(或独立于)过去的评估。在这个意义上,贝叶斯优化就像手动搜索。假设您正在手动优化随机森林回归模型的超参数。首先,你将尝试一组参数,然后查看结果,改变其中一个参数,重新运行,并比较结果,这样你就知道你是否朝着正确的方向前进。贝叶斯优化做类似的事情——你过去的超参数的性能影响未来的决策。相比之下,在确定要评估的新超参数时,随机搜索和网格搜索不考虑过去的性能。因此,贝叶斯优化是一种更有效的方法。

贝叶斯优化的工作原理

让我们继续使用优化随机森林回归模型的超参数的例子。假设我们想找到一组使 RMSE 最小的超参数。这里,计算 RMSE 的函数被称为目标函数。如果我们知道我们的目标函数的概率分布,(简单地说,如果我们知道目标函数的形状),那么我们可以简单地计算梯度下降并找到全局最小值。然而,由于我们不知道 RMSE 分数的分布(这实际上是我们试图找出的),我们需要贝叶斯优化来帮助我们破译这个黑盒模型。

那么什么是贝叶斯优化呢?

贝叶斯优化建立目标函数的概率模型,并使用它来选择超参数以评估真实的目标函数。

这句话听起来可能很复杂,但实际上传达了一个简单的信息。让我们来分解一下:

“贝叶斯优化建立目标函数的概率模型”

真正的目标函数是固定的函数。假设它看起来像图 1,但正如我提到的,在超参数调谐的开始,我们不知道这一点。

图 1:真正的目标函数

如果有无限的资源,我们将计算目标函数的每一个点,以便我们知道它的实际形状(在我们的例子中,一直调用随机森林回归模型,直到我们得到所有可能的超参数组合的 RMSE 分数)。然而,那是不可能的。假设我们只有来自真实目标函数的 10 个样本,如图 2 中的黑色圆圈所示:

图 2:真实目标函数的 10 个样本

使用这 10 个样本,我们需要建立一个代理模型(也称为响应面模型)来逼近真正的目标函数。请看图 3。代理模型用蓝线表示。蓝色阴影代表偏差。

图 3:启动代理模型

根据定义,代理模型是“目标函数的概率表示”,本质上是在(超参数,真实目标函数得分)对上训练的模型。数学上是 p(目标函数得分|超参数)。有不同的方法来构造代理模型,但是我稍后将回到这一点。

"并使用它来选择超参数"

现在我们有目标函数的 10 个样本,我们应该如何决定将哪个参数作为第 11 个样本?我们需要构建一个采集函数(也称为选择函数)。下一个选择的超参数是采集函数最大化的地方。在图 4 中,绿色阴影是采集函数,红色直线是采集函数最大化的位置。因此,相应的超参数及其目标函数得分(用红圈表示)被用作更新替代模型的第 11 个样本。

图 4:最大化采集功能以选择下一个点

“在真实目标函数中进行评估”

如上所述,在使用获取函数来确定下一个超参数之后,获得这个新的超参数的真实目标函数分数。由于代理模型已经在(超参数,真实目标函数得分)对上训练,添加新的数据点更新代理模型。

…重复上述步骤,直到达到最大时间或最大迭代次数。然后嘣!您现在(希望)有了真实目标函数的精确近似值,并且可以很容易地从过去评估的样本中找到全局最小值。你的贝叶斯优化完成!

放在一起

总结一下,我们来看下面图 5 中的伪代码,它来自这篇论文:

图 5:基于通用顺序模型优化的伪代码

这里,SMBO 代表基于序列模型的优化,这是贝叶斯优化的另一个名字。它是“顺序的”,因为添加超参数是为了逐个更新代理模型;它是“基于模型”的,因为它用一个评估起来更便宜的替代模型来近似真实的目标函数。

伪代码中的其他表示:

H :(超参数,得分)对的观察历史
T:最大迭代次数
f:真实目标函数(在我们的例子中,RMSE 函数)
M:代理函数,每当添加新样本时更新
S:采集函数
x
:下一个选择的要评估的超参数*

让我们再来一遍这个循环。

  • 首先,启动一个代理模型和一个获取函数。
  • 第 3 行:然后对于每次迭代,找到采集函数最大化的超参数 x* 。获取函数是代理模型的一个函数,意思是使用代理模型而不是真正的目标函数构建的(继续读,你就知道是什么意思了)。注意,这里的伪代码显示 x* 是在采集函数最小化时获得的,而我一直说采集函数应该最大化。最大化或最小化都取决于如何定义采集函数。如果你使用的是最常见的获取函数——预期改善,那么你应该最大化它。
  • 第 4 行:获得 x* 的目标函数分数,看看这一点实际表现如何
  • 第 5 行:将(超参数 x,真实目标函数得分)*包含在其他样本的历史中
  • 第 6 行:使用样本的最新历史来训练代理模型

重复直到达到最大迭代次数。最终返回(超参数,真实目标函数得分)的历史。请注意,最后一项记录不一定是最好的成绩。您必须对分数进行排序,以找到最佳超参数。

不同类型的代理模型和获取函数

我将只给出常用类型的一般描述,而不是进入代理模型和获取函数的数学细节。如果你有兴趣更多地了解获取函数如何与不同的代理模型一起工作,请查看这篇研究论文。

最常见的获取函数:预期改善

让我们从解释什么是获取函数开始,这样我们就可以解释每种类型的代理模型是如何被优化的。

最常见的获取函数是预期改善。该公式如下所示:

p(y|x): 代理模特。y 是真实的目标函数分数,x 是超参数

y:目前观察到的最小真实目标函数分数*

y:新分数

预期的改进是建立在代理模型之上的,这意味着不同的代理模型将导致优化该获取函数的不同方式。我们将在下面的部分中讨论这一点。

最常见的代理模型:高斯过程模型

大多数研究论文使用高斯过程模型作为替代模型,因为它简单且易于优化。高斯过程直接建模 P(y|x)。它使用(超参数,真实目标函数得分)的历史作为(x,y) 来构造多元高斯分布。

为了最大化高斯过程模型的预期改进结果,新的分数应该小于当前的最小分数 (y < y)* ,以便 max(y — y,0)* 可以是一个大的正数。

让我们来看看图 6 中的一个具体例子(我借用了这篇文章):

图 6:分数与超参数的虚拟示例

假设在图 6 中最低分= 12,那么 y* = 12。预期改善函数将关注不确定性高且均值函数接近或低于 y*的区域。使用多元高斯分布产生最高预期改进的 n 个估计量将被用作真实目标函数的下一个输入。

替代代理模型:树 Parzen 估计量(TPE)

在一些 python 包(例如 hyperopt 库)中实现的另一个代理模型是 TPE。首先回忆一下下面显示的贝叶斯规则:

高斯过程直接建模 p(y|x) ,而 TPE 建模 p(x|y) ,这是给定目标函数得分的超参数的概率分布。

让我们继续以图 7 为例。TPE 算法不是选择 y* = 12 作为高斯过程,而是选择 y作为观察到的 y 值的某个分位数γ,使得 p(y < y) = γ. In other words, TPE chooses y* to be some number that’s a bit higher than the best-observed score so that it can separate the current observations into two clusters: better than y* and worse than y*. See Fig 7 as an illustration.

Fig 7: The black dash line is the selected y*

Given the separate scores, TPE then constructs separate distributions for the hyperparameters. Thus p(x|y) is written as:

where l(x) is the distribution of the hyperparameters when the score is lower than the threshold y* and g(x) is the distribution when the score is higher than y*.

The Expected Improvement formula for TPE is then changed to:

and after some math transformation, it becomes:

The end formula means that to yield a high Expected Improvement, points with high probability under l(x) and low probability under g(x), should be chosen as the next hyperparameter. This meets our intuition that the next hyperparameter should come from the area under the threshold rather than the area above the threshold. To learn more about the TPE surrogate model, refer to 本文或本文。

摘要、参考资料和进一步阅读

在本文中,我以一种简单明了的方式解释了贝叶斯优化的概念。对于那些想了解更多信息的人来说,以下是我认为有用的资源列表:

  • 对机器学习的贝叶斯超参数优化的概念性解释 :另一篇着重解释 TPE 方法的中型文章
  • 超参数优化算法 :一篇很棒的研究论文详细解释了期望改善优化在高斯过程和 TPE 中是如何工作的。
  • 机器学习的贝叶斯方法 :一段 10 分钟的 YouTube 短片,介绍了其他类型的采集函数
  • 扩展、应用和其他杂项的贝叶斯优化 :一个 1 小时 30 分钟的讲座记录,详细介绍贝叶斯优化的概念,包括不同类型的代理模型和获取函数背后的数学。整个讲座可能太专业了,难以理解,但至少视频的前半部分对理解概念很有帮助。

好吧,就这样!恭喜你一路跟随我来到这里!我希望我的文章能在某种程度上把你从与贝叶斯优化相关的大量术语和数学中解救出来。有关问题和评论,让我们连线 Linkedin 和 Twitter 。

贝叶斯回归及其 R 语言实现

原文:https://towardsdatascience.com/bayesian-regression-with-implementation-in-r-fa71396dd59e?source=collection_archive---------16-----------------------

从零开始的理论推导,R 实现,以及贝叶斯观点的讨论

显示回归中变量之间依赖关系的概率图形模型(Bishop 2006)

可以从贝叶斯的角度建立和解释线性回归。第一部分从头开始讨论理论和假设,后面的部分包括 R 实现和备注。读者可以随意地将这两个代码块复制到 R 笔记本中,并对其进行研究。

从基础开始

回想一下,在线性回归中,给我们目标值 y ,数据 X,,我们使用模型

其中 y 为 N1 向量,X 为 ND 矩阵,w 为 D1 向量,误差为 N1 向量。我们有 N 个数据点。维数 D 是用特征来理解的,所以如果我们用一个 x 的列表,一个 x 的列表(和一个 1 的列表对应 w_0),我们说 D=3。如果你不喜欢矩阵的形式,就把它想成是以下内容的浓缩形式,其中所有东西都是一个标量,而不是向量或矩阵:

在经典的线性回归中,误差项被假设为正态分布,因此可以直接得出 y 正态分布,均值 Xw ,以及误差项具有的任何方差的方差(用σ表示,或具有σ项的对角矩阵)。正态假设在大多数情况下证明是正确的,这个正态模型也是我们在贝叶斯回归中使用的。

参数推断

我们现在面临两个问题:对 w 的推断和对任何新 x 的 y 的预测。使用众所周知的贝叶斯规则和上述假设,我们不仅可以解决这两个问题,还可以给出任何新 x 的 y 的全概率分布。下面是使用我们的符号的贝叶斯规则,它表示给定数据的参数 w 的后验分布:

π和 f 是概率密度函数。由于结果是 w 的函数,我们可以忽略分母,因为分子与左边的常数成正比。我们从假设中知道,似然函数 f(y|w,x)遵循正态分布。另一项是 w 的先验分布,顾名思义,这反映了参数的先验知识。

先验分布。定义先验是贝叶斯工作流程中一个有趣的部分。为了方便起见,我们设 w ~ N(m_o,S_o),超参数 m 和 S 现在反映了 w 的先验知识。如果你对 w 知之甚少,或者发现 m 和 S 的任何赋值太主观,“无信息”先验是一种修正。在这种情况下,我们将 m 设置为 0,更重要的是将 S 设置为具有非常大的值的对角矩阵。我们说 w 有很高的方差,所以我们不知道 w 会是什么。

在定义了所有这些概率函数之后,几行简单的代数运算(实际上相当多行)将给出 N 个数据点观察后的后验概率:

它看起来像一堆符号,但它们都已经被定义了,一旦这个理论结果在代码中实现,你就可以计算这个分布。(N(m,S)表示具有均值 m 和协方差矩阵 S 的正态分布。)

预测分布

完全贝叶斯方法不仅意味着获得单个预测(用 y_o,x_o 表示新的一对数据),还意味着获得这个新点的分布。

我们所做的是从第一行的联合边缘化得到边缘分布的反向操作,并在第二行的积分中使用贝叶斯规则,在那里我们也删除了不必要的相关性。注意,我们知道最后两个概率函数是什么。完全预测分布的结果是:

R 中的实现

用 R 实现相当方便。在上述理论结果的支持下,我们只需将矩阵乘法输入到代码中,即可获得预测和预测分布的结果。为了举例说明,我们使用了一个玩具问题:X 是从-1 到 1,均匀分布,y 被构造为以下具有正常噪声的正弦曲线的加法(见下图中 y 的图示)。

下面的代码获取这些数据。

library(ggplot2)

*# — — — — — Get data — — — — — — — — — — — — — — — — — — — — —+*X <- (-30:30)/30 
N <- length(X) 
D <- 10 
var <- 0.15*0.15 
e <- rnorm(N,0,var^0.5) 
EY <- sin(2*pi*X)*(X<=0) + 0.5*sin(4*pi*X)*(X>0) 
Y <- sin(2*pi*X)*(X<=0) + 0.5*sin(4*pi*X)*(X>0) + e 
data <- data.frame(X,Y) 
g1 <- ggplot(data=data) + geom_point(mapping=aes(x=X,y=Y))

下面的代码(在“推断”一节中)实现了上述理论结果。我们还扩展了 X 的特性(在代码中表示为 phi_X,在构造基函数一节中)。就像我们将 x 展开成 x,等等。,我们现在将其扩展为 9 个径向基函数,每个函数如下所示。请注意,尽管这些看起来像正态密度,但它们并不被解释为概率。

径向基函数的一个优点是径向基函数可以拟合各种曲线,包括多项式和正弦曲线。

*# — — — — — Construct basis functions — — — — — — — — — — — —+*phi_X <- matrix(0, nrow=N, ncol=D)
phi_X[,1] <- X
mu <- seq(min(X),max(X),length.out=D+1)
mu <- mu[c(-1,-length(mu))]
for(i in 2:D){
 phi_X[,i] <- exp(-(X-mu[i-1])^2/(2*var))
}*# — — — — — Inference — — — — — — — — — — — — — — — — — — — —+**# Commented out is general prior
# m0 <- matrix(0,D,1)
# S0 <- diag(x=1000,D,D) 
# SN <- inv(inv(S0)+t(phi_X)%*%phi_X/var)
# mN <- SN%*%(inv(S0)%*%m0 + t(phi_X)%*%Y/var)
# Y_hat <- t(mN) %*% t(phi_X)**# We use non-informative prior for now*
m0 <- matrix(0,D,1)
SN <- solve(t(phi_X)%*%phi_X/var)
mN <- SN%*%t(phi_X)%*%Y/var
Y_hat <- t(mN) %*% t(phi_X)
var_hat <- array(0, N)
for(i in 1:N){
 var_hat[i] <- var + phi_X[i,]%*%SN%*%phi_X[i,]
}g_bayes <- g1 + 
             geom_line(mapping=aes(x=X,y=Y_hat[1,]),color=’#0000FF’)
g_bayes_full <- g_bayes + geom_ribbon(mapping=aes(x=X,y=Y_hat[1,],
                  ymin=Y_hat[1,]-1.96*var_hat^0.5,
                  ymax=Y_hat[1,]+1.96*var_hat^0.5, alpha=0.1),
                  fill=’#9999FF’)

在这些计算中需要注意的一个细节是,我们使用了非信息先验。注释掉的部分正是上面的理论结果,而对于非信息先验,我们使用对角元素接近无穷大的协方差矩阵,因此在此代码中,其倒数直接被视为 0。如果您想使用此代码,请确保您安装了 ggplot2 包用于绘图。

下图旨在展示完整的预测分布,并给出数据拟合程度的感觉。

蓝线是每个点 x 的预测分布的期望值,浅蓝色区域是指两个标准差以内的区域。红线是 y 的真函数,点是从给定函数中随机产生的数据,带有正态噪声。

评论

多元线性回归结果与使用具有无限协方差矩阵的不适当先验的贝叶斯回归的情况相同。一般来说,获得一些关于参数的经验知识,并使用信息丰富的先验知识是一种很好的做法。贝叶斯回归可以量化和显示不同的先验知识如何影响预测。在任何情况下,贝叶斯观点可以方便地将 y 预测的范围解释为概率,不同于从经典线性回归计算的置信区间。

从这个角度来看,数据拟合也让你很容易“边走边学”。假设我首先观察了 10000 个数据点,并计算了参数 w 的后验概率。之后,我设法获得了 1000 个数据点,而不是再次运行整个回归,我可以使用之前计算的后验概率作为这 1000 个点的先验。这个顺序过程产生的结果与再次使用全部数据的结果相同。我喜欢这个想法,因为它非常直观,因为学到的观点与以前学到的观点加上新的观察结果成正比,而且学习还在继续。一个笑话说,一个贝叶斯谁梦见一匹马,观察到一头驴,会称之为骡子。但是如果他对它进行更多的观察,最终他会说这确实是一头驴。

贝叶斯统计是每个数据科学家的必备

原文:https://towardsdatascience.com/bayesian-statistics-are-a-must-for-every-data-scientist-d037908b3558?source=collection_archive---------28-----------------------

图片由 jakob5200 来自 Pixabay

数据科学核心的贝叶斯统计

数据科学深深植根于贝叶斯统计&我不会给出托马斯·贝叶斯爵士的历史背景,而是给你一个关于贝叶斯统计、贝叶斯定理以及如何在工作中利用它作为工具的高级视角!贝叶斯统计植根于数据科学的许多方面&机器学习具有这些原则的坚实基础是非常重要的。

贝叶斯定理的核心

贝叶斯定理背后的主要思想是,如果有一些与即将发生的事件相关的洞察力或知识。这种洞察力可以用来帮助描述该事件的可能结果。

考虑这一点的一种方法可能是在客户流失的情况下,因为它与客户活动有关。

我们的问题是什么?

为了把这个问题公式化成一个我们可以用贝叶斯定理解决的问题,明确我们的问题是什么是有帮助的。

所以你知道一个客户是否有过不愉快,但是根据这些信息,你想确定它属于你的活跃客户群还是不活跃客户群的可能性。因此,我们的问题可以表述为,“假设一个客户在搅动,它活跃的可能性有多大?”

所以现在我们需要弄清楚如何利用我们所知道的信息来找到答案。

让我们开始通过代码来概念化这一点。

我们来编码吧!

正如您将在下面看到的,我们将对每个场景执行 100K 次“抽取”,在每个场景中,我们对 100 名客户进行抽样调查以了解客户流失情况。第一个模拟将代表活跃客户的流失概率&第二个将代表不活跃客户;客户流失率分别为 20%和 50%。

active <- rbinom(100000, 100, .2) inactive <- rbinom(100000, 100, .5)

如果你对这些模拟的流失率取平均值,你会看到它们在size之前徘徊在probability附近。20 & 50 分别为。

让我们快速看一下每个模拟的结果分布。

hist(active)

hist(inactive)

如上所述,你可以知道分布集中在均值上,并且是正态分布的。

现在,让我们来看一下模拟流失率为 35 的场景。

active_sample <- sum(active == 35) 
inactive_sample <- sum(inactive == 35)active_sample / (active_sample + inactive_sample) 
inactive_sample / (active_sample + inactive_sample)

我们可以看到,在模拟代表活跃用户的情况下,只有 12.6%的抽奖与活跃用户相关,而这些抽奖实际上是非活跃用户的概率为 87.4%。

另外,看一下 35 值的直方图来巩固这个想法。尽管 35 对于这两种发行版来说都是极限,但它确实提供了一些额外的上下文。

考虑模拟之间的分布

到目前为止,我们已经在活跃客户和不活跃客户之间创建了一个均匀的模拟,但是假设我们没有一个活跃客户和不活跃客户的均匀分布。我们可以通过创建没有不同绘制计数的模拟来融入这一思想。

在这里,我们做同样的事情,但这次我们在两组之间重新创建了 80/20 的划分,即我们 80%的客户群是活跃的。

active <- rbinom(80000, 100, .2) 
inactive <- rbinom(20000, 100, .5)

现在,当我们像以前一样经历同样的过程时…

active_sample <- sum(active == 35) 
inactive_sample <- sum(inactive == 35)active_sample / (active_sample + inactive_sample) 
inactive_sample / (active_sample + inactive_sample)

我们实际上看到它是一个不活跃客户的概率大大下降。当然有充分的理由。我们已经根据以前活跃客户和不活跃客户的分布情况更新了我们的分析。

结论

关于贝叶斯统计,我们还可以做得更多,但是我希望这个应用程序能够很好地产生一个强有力的介绍。一定要评论你想要更多细节的地方,或者是否有你喜欢的东西。

查看我在 datasciencelessons.com 的其他帖子、课程和见解,在 twitter @data_lessons 上关注我!

贝叶斯统计:Python 中从零开始的大都会-黑斯廷斯

原文:https://towardsdatascience.com/bayesian-statistics-metropolis-hastings-from-scratch-in-python-c3b10cc4382d?source=collection_archive---------4-----------------------

用 Python 探索马尔可夫链蒙特卡罗抽样

信用:Pixabay

你在这里

如果你正在阅读这篇文章,很有可能:(1)你对贝叶斯统计感兴趣,但是(2)你不知道马尔可夫链蒙特卡罗(MCMC)抽样方法是如何工作的,以及(3)你意识到除了最简单的玩具问题,所有问题都需要 MCMC 抽样,所以你有点不确定如何前进。

不用担心,我们将使用一维正态分布来探索这个棘手的概念,只使用 python、用户定义的函数和随机模块(特别是均匀分布。)我们将从酒吧、啤酒和与你的朋友外出的夜晚的角度来讨论所有这些无意义的事情。

想象自己在酒吧里

这是星期五晚上,你和你的朋友出去吃汉堡,喝啤酒,看电视转播的棒球比赛。假设你任意选择了第一个酒吧(我们称之为拉里体育酒吧,你坐下来,拿起菜单,考虑你的选择。如果食物和饮料价格合理,这是留下来的好理由;但是如果只有站着的地方,你就有理由离开。如果酒吧里摆满了大屏幕电视,而且都在播放正确的游戏,这是我留下来的另一个原因。如果食物或饮料不吸引人,你就有了另一个离开的理由。等等,你明白了。

现在,让我们假设你的一个(或几个)朋友对现在的机构有抱怨——食物是冷的,啤酒价格过高,不管是什么原因。所以他提议这帮人离开拉里的体育酒吧而去托尼的比萨店和啤酒花园因为那里的食物更好、更新鲜等等。因此,该团伙商议,提出问题(A)拉里的有多有利?(二)托尼的好感度如何?和(C) 托尼相对于拉里的有利程度如何?

这种相对比较真的是最重要的细节。如果托尼的仅仅比拉里的好一点点(或者差很多),那么很有可能不值得花力气去重新定位。但是如果托尼的无疑是两个中更好的,那么你留下来的机会就很小了。这才是让 Metropolis-Hastings“工作”的真正动力

该算法

Metropolis-Hastings 算法可以:

  1. 随机样本开始
  2. 确定与样本相关的概率密度
  3. 提出一个新的,任意样本(并确定其概率密度)
  4. 比较密度(通过除法),量化想要移动的程度
  5. 生成一个随机数,与移动的欲望进行比较,然后决定:移动还是停留
  6. 重复

真正的关键是(正如我们已经讨论过的)量化这个举动有多可取,作为一个行动/不行动的标准,然后(新的东西提醒!)观察随机事件,与所述阈值进行比较,并做出决定。

随机事件

出于我们的目的,我们的阈值是建议样本的概率密度与当前样本的概率密度之比。如果该阈值接近(或高于)1,则意味着之前的位置非常不理想(接近 0 的数字,非常不可能),而建议的位置非常理想(尽可能接近 1,接近分布的预期)。现在,我们需要从均匀分布中生成一个范围为[0,1]的数。如果产生的数字小于或等于阈值,我们就移动。否则,我们留下。就是这样!

难的东西呢?

这听起来有点好得难以置信,对吧?我们还没有讨论马尔可夫链或蒙特卡洛模拟,但不用担心。这两者本身都是很大的话题,我们只需要对它们有最基本的了解就可以利用 MCMC 的魔力。

马尔可夫链是离散事件的链,其中下一个事件的概率仅取决于当前事件。(例:我刚学完,是去睡觉还是去酒吧?这些是我在有限的选择中唯一的选择。)在这个离散选择的系统中,存在一个转移矩阵,它量化了从任何给定状态转移到任何给定状态的概率。蒙特卡洛方法实际上只是一个依赖于随机数使用的模拟/实验的花哨名称。

如前所述,我们将从正态分布中取样——一个连续的,而不是离散的分布。那么怎么会有转移矩阵呢?惊喜! —根本没有转换矩阵。(它实际上被称为一个马尔可夫核,它只是概率密度的比较,至少对我们的目的来说是这样的。)

代码

下面,我们定义三个函数:(1)正态,在给定参数 mu 和 sigma 的情况下,评估任何观测值的概率密度。(2) Random_coin,参考了一个 TDS 作者同行的帖子(下面划线)。以及(3) Gaussian_mcmc,其采样执行上述算法。

正如所承诺的,我们不会从 numpy、scipy 等调用任何高斯或正态函数。在第三个函数中,我们将当前样本初始化为均匀分布的实例(其中下限和上限是平均值的+/- 5 个标准偏差)。)同样,运动的定义也是如此。最后,我们根据随机事件相对于接受度的观察值移动(或停留),这是在别处详细讨论的概率密度比较。

Github 要诀

直方图与实际分布

最后,我们必须始终给予应有的信任: Rahul Agarwal 的帖子定义β分布 MH 采样器对我开发上述高斯分布 MH 采样器很有帮助。我鼓励你也阅读他的文章,更详细地探索基本概念,即马尔可夫链和蒙特卡洛模拟。

离别笔记

亲爱的读者,我注意到一种模式,即用户将我的故事添加到他们的列表中,但不鼓掌或订阅。请——如果你喜欢我的内容,通过鼓掌、评论和订阅来认识到它是有用的。这(1)有助于我确定下一步为您创建什么内容的优先级,以及(2)有助于其他媒体用户找到我的内容。谢谢!

面向数据科学家的贝叶斯统计 101

原文:https://towardsdatascience.com/bayesian-stats-101-for-data-scientists-a8c145a84259?source=collection_archive---------9-----------------------

具有 Beta 先验和模拟数据的二项式 p 参数的后验

统计学和概率的另一种观点

你可能还记得贝叶斯定理,那是你需要为统计 101 课程记忆的恼人的等式,但它远不止如此。这也是统计和概率的另一种观点的基础,与频繁主义者的观点和学术界最伟大(或最蹩脚)圣战的一半形成对比。

如果你上过统计学入门课,你会对统计学的 Frequentist 框架很熟悉,即使你不知道它的名字。在 Frequentist 框架中,参数(总体均值、方差等。)是固定的,但数据是随机的。对于频率主义者来说,概率是一个事件在重复试验中相对频率的极限。

https://en.wikipedia.org/wiki/Thomas_Bayes 牧师托马斯·贝叶斯

巴伊亚人持不同观点;概率是相信一个事件将会发生的程度,贝叶斯主义者对参数的概率分布对应于他们对可能值的相信程度。谁是对的?和生活中的大多数事情一样,要看情况。

为了演示不同的方法,让我们来看看两个阵营将如何处理一个简单的问题:一枚硬币正面朝上的概率是多少(我们称之为【P(H))。

解决这个问题的一个有效的频率主义方法是将硬币抛足够的次数,并使用最大似然法或矩量法估计器来估计 P(H) (这里它们都是/抛硬币数 )。接下来,频率主义者将构建一个近似的置信区间,并使用它来做出关于 P(H) 的推断。完全合理的方法。现在让我们用贝叶斯方法来检验同一个问题。

贝叶斯方法从这个等式开始:

先验是我们在检查数据之前对感兴趣参数分布的信念。它可以基于专家的判断,或者你可以使用一个无信息先验(一个对参数作出弱声明的先验)。在我们掷硬币的例子中,我们可以使用贝塔分布的概率密度函数作为 P(H) 的一般分布,因为它像概率一样被限制在 0 和 1 之间。我们必须设置这个分布的参数,但是现在,我们不指定它们。

可能性是我们的样本。对于掷硬币的例子,数据来自二项分布,因此我们将使用二项概率质量函数(掷硬币的中的人头数遵循二项分布)。

我们现在准备求解 P(H) 的后验线,它由希腊字母 theta 表示。头数用 Y (随机变量)和 y (我们的样本中的实际头数 n )表示。

用贝塔先验求解二项似然的后验概率

可以看到,我们关于【P(H)的后验信念既依赖于数据(即n )也依赖于我们关于【P(H)(αβ)随着我们包含的数据越来越多,我们的先验信念对后验的影响也越来越弱。有了足够的证据,非常不同的先验会汇聚到同一个后验。你先前信念的强度会影响收敛的速度。**

为了演示证据如何压倒先验,我使用 python 模拟了 100 次掷硬币,并绘制了 0 次、10 次、50 次和 100 次模拟掷硬币的 2 个非常不同的先验的后验分布。

首先我们需要导入一些函数,设置抛硬币次数和 P(H) ,为我们的每一个先验分布设置参数。

**import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta, bernoulli# set number of trials
n = 100
# set the probability of getting a heads
theta = 0.5# prior where our coin is biased towards heads
alpha1 = 5
beta1 = 2# prior where our coin is biased towards tails
alpha2 = 2
beta2 = 5**

接下来,我们模拟我们的硬币翻转,并在翻转 10 次、50 次和 100 次后进行计数。

**# simulates n coinflips with P(Heads) = theta
coin_flips = bernoulli.rvs(p=theta, size=n, random_state=1)# count the Heads in the first 10 flips
n_1 = 10
y_1 = sum(coin_flips[0:n_1])# count the Heads in the first 50 flips
n_2 = 50
y_2 = sum(coin_flips[0:n_2])# count the Heads in the whole sample
y_total = sum(coin_flips)**

现在,我们定义一个函数,使用解析导出的结果生成后验分布。

**def my_posterior(alpha_, beta_, n, y):
    # set the range of theta (0 to 1) with 100 intervals
    x = np.linspace(0, 1, 100)
    # calculate the pdf at each one
    y = beta.pdf(x, (alpha_ + y), (n - y + beta_))
    # returns x and the pdf of the posterior 
    return x, y**

最后,我们准备在 0 次、10 次、50 次和 100 次抛硬币后绘制每个先验的后验概率。

**# plot the posteriors with the beta(alpha1, beta1) priors
for i in [(0, 0), (n_1, y_1), (n_2, y_2),(n, y_total)]:
    label  = f"n = {i[0]}, y = {i[1]}"
    plt.plot(my_posterior(alpha1, beta1, i[0], i[1])[0],
             my_posterior(alpha1, beta1, i[0], i[1])[1], 
             label=label)
plt.legend()
plt.show()# plot the posteriors with the beta(alpha2, beta2) priors
for i in [(0, 0), (n_1, y_1), (n_2, y_2),(n, y_total)]:
    label  = f"n = {i[0]}, y = {i[1]}"
    plt.plot(my_posterior(alpha2, beta2, i[0], i[1])[0],  
             my_posterior(alpha2, beta2, i[0], i[1])[1], 
             label=label)
plt.legend()
plt.show();**

****

模拟硬币投掷的后验分布

如你所见,随着更多的数据,非常不同的先验将向相同的后验收敛。

**# plot the posteriors for both priors after 100 coin flips
plt.plot(my_posterior(alpha1, beta1, n, y_total)[0],
         my_posterior(alpha1, beta1, n, y_total)[1])
plt.plot(my_posterior(alpha2, beta2, n, y_total)[0],
         my_posterior(alpha2, beta2, n, y_total)[1])
plt.show();**

如前所述,参数对贝叶斯人来说是随机的。因此,不同的语言适用于进行推理。常客有“置信区间”,他们有 X%的把握真实参数在这个区间内。这意味着,如果从固定大小的样本中抽取无限数量的样本,则 X%的置信区间将包含真实参数。它意味着真参数在置信区间内的概率为 X%。它要么在置信区间内,要么不在置信区间内。我们只是不知道。

Bayesians 人有“可信区间”,即参数在该区间内出现的概率为 X%。这是一种微妙的语言差异,在解释上有很大的差异。统计学家是数学学科的律师。

解析地推导后验分布并不总是容易的,这也是 20 世纪频繁主义者分析主导贝叶斯分析的一个原因。随着计算机计算能力的增加,现在使用数值技术来生成后验分布是可行的(见马尔可夫链蒙特卡罗)。如果你已经做到了这一步,你现在已经有了开始探索这些算法的背景。

贝叶斯推理作为一种生活方式

既然你对贝叶斯观点有了基本的了解,我想解释一下为什么我认为贝叶斯推理是一种很好的生活方式。这并不完全是一个新颖的观点,但是大多数人在处理现实的方法上仍然是非贝叶斯的,所以我仍然会给它一个解释。

我们都同意 1x1=1,除非你是 Terrance Howard 。我们不需要给这种说法分配一个信任度,因为它在逻辑上是真实的。但是生活中有很多事情没有逻辑证明。

让我们看看将最低工资提高到每小时 15 美元的问题(这是美国争论的一个热门话题)。虽然更多的书呆子认为最低工资应该提高多少应该取决于一个地区的生活成本(这是我以前的观点),但围绕这个问题的许多流行辩论采取了二元形式“应该提高到每小时 15.00 美元,因为这将帮助很多人”或“不应该提高,因为企业将削减就业”,这假设劳动力需求对包含最低工资职位的部分具有弹性。

幸运的是,一些州和城市最近提高了最低工资。在接下来的几个月和几年里,我们将会有研究论文,这些论文将会给我们提供支持或反驳我们信仰的迹象,我们可以作为 Bayesians 人相应地更新我们的信仰。不管证据如何,非 Bayesians 人将留在各自的营地。

我相信我们应该这样对待生活中的大多数问题。基于我们个人对世界如何运作的心理模型,我们都可以对现实的各个方面有预先的信念,但我们的信念 必须 对现实敏感。当我们几乎没有证据支持我们的信念时,我们不应该如此强烈地坚持它们。

我留给你们克伦威尔法则。

"我以基督的名义恳求你,想想你可能弄错了。"—奥利弗·克伦威尔

贝叶斯思维

原文:https://towardsdatascience.com/bayesian-thinking-2e8851c64f5e?source=collection_archive---------10-----------------------

统计学家如何应对金星上的生活

照片由 菲利普·唐恩派克斯

如果你是那种阅读数据科学博客的人(你好!)那你大概已经知道贝叶斯定律了。见鬼,你可能自己也用过。不幸的是,根据我的经验,许多人只知道技术和学术背景下的贝叶斯法则,并不真正理解日常生活中有用的方式。这是一种耻辱,因为贝叶斯法则是一种美丽的、强大的、理性的组织你的信仰的方式。不过,问题是:你已经在日常生活中使用它了,只是你可能不知道而已。在这篇文章中,我将通过一个热门的非技术性的例子向你展示如何有意识地使用贝叶斯定律:金星上生命的(潜在)发现。

不好意思,什么?

如果你不知何故错过了新闻,简·s·格里夫斯博士等人最近的一篇论文引发了人们对金星上可能存在生命的兴趣。不幸的是,随着 COVID 旅行禁令的生效,格里夫斯博士无法带她的团队到这个温暖的星球进行实地考察,所以他们改用望远镜。简而言之,研究小组在金星的大气中发现了磷化氢气体的证据。

好吧,那这和贝叶斯定律有什么关系?

贝叶斯法则是一种工具,它可以根据新信息更新你现有的信念,而不是彻底抛弃你的旧信念。做好准备,因为我要给你看一个等式:

贝叶斯定律的辉煌

这跟信仰和信息有什么关系?嗯,看起来有点复杂,但实际上很简单。让我们来分解一下:

  • 对于初学者来说,“P”读作“的概率”,“|”读作“给定”。所以“P(A|B)”读作“给定 B 的概率”。
  • a 是有疑问的信念;在我们的例子中,A 是“金星上有生命”的陈述。
  • b 是证据;在我们的例子中,“金星上有磷化氢气体”。

因此,等式的左边读作“[假定金星上有磷化氢,那么]金星上有生命的概率是多少?”当你读到像“在金星上发现磷化氢气体”这样的新闻标题时,这正是你应该问自己的问题

既然我们可以说出贝叶斯定律,让我们把它分成几个部分:

P(A|B): 这被称为后验,意思是“给定证据【金星上的磷化氢】,索赔【金星上的生命】的概率是多少”。我们关心的是数量。说到后验,你很难想象我有多失望磷化氢没有在天王星上被发现。

P(B|A): 这叫做似然,是后验概率的倒数。它的意思是“给定‘金星上有生命’的说法,我们看到证据‘金星上有磷化氢’的概率有多大”。为了计算出这个值,我们假设金星上有生命并计算如果我们的假设成立,我们在金星上观察到磷化氢气体的概率。我们知道地球上的生物会产生磷化氢气体,所以这个数值比较高。

P(A): 这叫先验,意思是“在没有任何新证据的情况下,主张成立的概率有多大”。在我们的例子中,这是在你阅读新闻标题之前,你对金星上有生命的先验信念。考虑到这个星球是一个腐蚀性的地狱,在你到达地表之前,它会将你煮沸、压碎、腐蚀,这个值相当低。

P(B): 这个值被称为边际,意思是“我们看到任何索赔给出的证据的概率是多少”。在我们的例子中,这意味着“某物在金星上产生磷化氢气体的概率是多少”。该论文详细描述了其他可能产生磷化氢的方法,包括火山活动、闪电和流星投放,并得出结论,这些方法中的任何一种都不可能产生与观察到的一样多的磷化氢。

把所有的放在一起

想到这些,一个统计学家读到标题金星上发现磷化氢气体会有什么反应?

  1. "嗯,我想知道根据这一新信息,金星上有生命的可能性有多大?"
  2. "嗯,我对金星人生活的先验信念相当低,可能只有 0.01%…"
  3. “但是假设金星上有生命,根据我们对人类生物学的了解,它产生磷化氢气体的可能性很高。”
  4. “任何东西产生这种气体的边际概率几乎为零……”
  5. 考虑到这一切,我想我会把我对金星上有生命的信念从 0.01%更新到 10%。

你听到最后一点了吗?这就是奇迹发生的地方;一旦你应用贝叶斯法则,后验概率就成为你下一次获得新证据的新先验。如果另一名研究人员明天发表一项研究,描述金星上的另一个生物特征,这位统计学家将使用他们新的 10%的先验,而不是他们旧的 0.01%的先验。

现实生活中的应用

一旦你熟悉了这项技术,你就可以在任何地方应用它:

  1. “我两周一次的壁球俱乐部的桑德拉今天随机给我买了一套新的壁球;鉴于这个证据,我怀疑她是不是看上我了……【未知后路!]"
  2. “我知道我看起来很体面,但我们真的没有谈过很多,所以她不太可能喜欢我[小优先!]"
  3. “但是如果她真的喜欢我,送我一套壁球会是一个很好的表达方式[可能性很大!]"
  4. “桑德拉是个顽固的家伙……我怀疑她是否经常出人意料地送礼物给人[小边际!]"
  5. “考虑到这一点,她很有可能喜欢我!我将把我的优先级从 10%更新到 60%”

或者另一个

  1. “我的老板今天狠狠训了我一顿,告诉我我的工作表现‘比他那只半瞎的约克夏狗还糟糕’;有了这些证据,我应该有多大信心保住我的工作?【未知后路!]"
  2. “我的工作很棒,但公司最近一直在挣扎,所以昨天我会说我是否能保住工作的可能性是 50%……[中级优先!]"
  3. “但是如果我的老板打算解雇我,他很有可能会以这种方式对待我【可能性很大!]"
  4. “提醒你一下,他是个混蛋,我很确定他时不时会数落每个人,所以他有各种各样的理由会这样……[大边缘]”
  5. "我想我会把对工作保障的信心降低一点,从 50%降到 45%。"

显然,我们无法确定日常生活中的确切概率,但你会明白的。这其中的大部分应该是直观的(就像我说的,我打赌你已经在使用它了),但是正式理解它如何以及为什么工作会使它更加有用。

含义

贝叶斯定律改变了你看待世界的方式。信念不再是二元的(真或假),而是形成了一个信心谱,随着新证据的出现而增加或减少。接受“我对自己的信念有 90%的把握”这种模糊说法,因为根据贝叶斯定律,如果你对一个信念有 100%或 0%的先验信心,那么不可能改变你的想法。为什么会这样?看这个等式:

如果 P(A)是 0,那么 P(A|B)也是,因为任何乘以 0 的东西都是 0。这意味着再多的证据也不会改变你的想法。想象一个扁平的地球人,他确信地球是扁平的(0%确信它是圆的)。无论你给他们看什么证据,P(A|B)都卡在零。另一边也是如此;如果你对 A 有 100%的把握(即 P(A)=100%),那么不管你得到什么证据 B,你都已经相信 A 了,不管 B 是什么,所以 P(A|B)也将是 100%,不管新的证据有多糟糕。

但是如果你没有前科会怎么样呢?你从哪里得到一个?一个答案是使用一个“不知情的先验”,你说“啊我不知道,假设是 50/50”(或者如果有三个结果,就是三分之一,等等。).另一种选择是使用简单的统计数据:在上面的解雇示例中,员工可以说“每年有 10%的员工被解雇,所以我可以说我保住工作的概率是 90%”。事先选择可能有点手动波动,有些人称之为不科学,但我通常只是让他们参考这部漫画。(没听懂笑话?贝叶斯统计学家有一个非常强的先验,太阳没有爆炸,因为,嗯,它从来没有过。

所以你有它。不管大学统计课会教什么,贝叶斯定律在乳腺癌诊断之外还有应用。下次壁球课上一定要告诉你所有的朋友。

线性回归的贝叶斯思维

原文:https://towardsdatascience.com/bayesian-thinking-estimating-posterior-distribution-for-linear-regression-data-ketchup-2f50a597eb06?source=collection_archive---------38-----------------------

贝叶斯与吉布斯采样和 MCMC 模拟

深度神经模型中的不确定性, 链接

简介:

这项研究的主要动机之一是,随着越来越复杂的模型的出现,人们越来越关注深度模型的可解释性。更多的是模型的复杂性,很难对输出进行解释,在贝叶斯思维和学习领域正在进行大量的研究。

但是在理解并能够欣赏深度神经模型中的贝叶斯之前,我们应该精通并熟练线性模型中的贝叶斯思维,例如贝叶斯线性回归。但是很少有很好的在线材料能够以一种组合的方式给出清晰的动机和对贝叶斯线性回归的理解。

这是我写这篇博客的主要动机之一,在这里,我将尝试从贝叶斯分析的角度来理解如何进行线性回归。

最大似然估计&贝叶斯

在开始之前,让我们明白,我们非常清楚线性回归模型的最大似然估计。我在之前的演讲中讨论过这个问题,请参考链接。

简单介绍一下线性回归中最大似然估计的概念。

线性回归最大似然法—二元图, 链接

可能为回归, 链接

由此要明白的最重要的一点是 MLE 通过最大化 似然 P(D|θ) 给你一个参数的点估计。

偶, 映射 即最大后验概率估计最大后验概率 P(θ|D), 即也给出点估计。

因此,这些方法不能给你足够的关于系数分布的信息,而在贝叶斯方法中,我们估计参数的后验分布。因此,在这种情况下,输出不是单个值,而是概率密度/质量函数。

后验概率,贝叶斯定理

只是为了理解背后的直觉。

先验,&后验,链接

理解后验意义, 链接

马尔可夫链蒙特卡罗模拟

只差一步了!!!

在深入研究贝叶斯回归之前,我们需要了解另一件事,即马尔可夫链蒙特卡罗模拟以及为什么需要它?

MCMC 方法用于通过概率空间中的随机采样来近似感兴趣参数的后验分布。但是为什么近似分布而不计算精确分布可能是一个你一定很感兴趣的问题。

计算后验分布的复杂度, 链接

由于分母的原因,这几乎无法计算,也很难处理,因此我们使用 MCMC 来近似后验分布。

蒙特卡罗方法有助于我们生成符合给定分布的随机变量。例如:- θ ~ N(平均值,sigma2),**将有助于从正态分布生成多个 θ ,有许多方法可以做到这一点。

马尔可夫链是一个数字序列,其中每个数字都依赖于序列中的前一个数字。马尔可夫链蒙特卡罗有助于从分布中生成随机变量,其中每一个 θ 的值都是从一个平均值等于前一个值的已知分布中提取的。

马尔可夫链蒙特卡罗与高斯建议分布,链接

通过 MCMC 模拟生成密度, 链接

正如您所理解的,这基本上是一个随机行走,可能会生成许多不必要的和不相关的值。因此,我们需要对值进行接受/拒绝采样,以生成感兴趣的分布。

在这种情况下,Metropolis-Hastings 算法用于通过拒绝和接受采样来改进值。

接受和拒绝样本的 Metropolis-Hastings 算法

我们也可以使用吉布的采样,其目标是通过获得后验条件分布 P(θ1|θ2,y,x)P(θ2|θ1,y,x)来找到后验分布 P(θ1,θ2|y,x)。 所以,我们生成

θ1 ~P(θ1|θ2,y,x)替换第二个方程中生成的θ1 的值,生成 θ2 ~ P(θ2|θ1,y,x) 我们继续这个过程,进行几次迭代,得到后验。

估计后验 MCMC, 链接

现在,让我们用一个例子来说明这一点。

在下面的例子中,我将首先用吉布斯抽样来说明贝叶斯线性回归方法。这里,我假设了参数的某些分布。

用吉布斯采样实现贝叶斯线性回归 :

在这一节中,我将展示一个使用吉布斯抽样进行贝叶斯线性回归的例子。这一部分摘自 Kieran R Campbell 关于贝叶斯线性回归的博客

因此,首先,让我们了解数据对于我们的情况是如何的。设 D 为以下实验的数据集,D 定义为:

D = ((x1,y1),(x2,y2),(x3,y3) …… (xn,yn)) 为数据,其中 x1,x2 …。属于单变量特征空间。

Y ~ N( bx + c,1/t)* ,其中 Y 为正态分布的随机变量,均值 bx + c* ,方差 1/t ,其中 t 代表精度。

在这种情况下,我们将考虑具有两个参数的单变量特征空间( X ),即斜率(c)截距(b) 。因此,在本实验中,我们将学习上述参数 c & b 和精度 t. 的后验分布

让我们写下上述参数的假设先验分布

参数的先验分布

因此,让我们首先写下正态分布的密度函数和 log_pdf,以得到一个概括的形式,这将在以后多次使用。

对数正态分布的 pdf 展开

现在,我们将很容易写出我们的情况的可能性,它也遵循均值 bx+c 和精度 t 的正态分布。

我们场景中的可能性估计

取其对数给出下面的表达式

我们场景的对数可能性

接下来是一个复杂的小部分,即导出所有三个参数 b,c,t. 的条件后验分布

条件后验分布为截距 _c :

c _ part 1 的条件后验分布

c _ part 2 的条件后验分布

c _ part 3 的条件后验分布

因此,我们可以看到,这是找出截距 c 的条件后验分布的过程。

上述等式的代码片段

**def get_intercept_c**(y, x, b, t, c0, tc):
    n = len(y)
    assert len(x) == n
    precision = c0 + t * n
    mean = tc * c0 + t * np.sum(y - b * x)
    mean = mean/precision
    **return** np.random.normal(mean, 1 / np.sqrt(precision)

同样,我们可以找到同样的 斜率 b.

条件后验分布为斜率 _b :

b _ part 1 的条件后验分布

b _ part 2 的条件后验分布

b _ part 3 的条件后验分布

b _ part 4 的条件后验分布

斜坡更新的代码片段如下

**def get_slope_b**(y, x, c, t, b0, tb):
    n = len(y)
    assert len(x) == n
    precision = tb + t * np.sum(x * x)
    mean = tb * b0 + t * np.sum( (y - c) * x)
    mean = mean/precision
    **return** np.random.normal(mean, 1 / np.sqrt(precision))

条件后验分布为精度 _t :

条件后验分布给出 b,c 将不会像上面两个一样,因为先验遵循伽马分布。

t _ part 1 的条件后验分布

t _ part 2 的条件后验分布

**def get_precision_t**(y, x, b, c, alpha, beta):
    n = len(y)
    alpha_new = alpha + n / 2
    resid = y - c - b * x
    beta_new = beta + np.sum(resid * resid) / 2
    **return** np.random.gamma(alpha_new, 1 / beta_new)

现在,由于我们可以获得参数的封闭分布形式,现在我们可以使用 MCMC 模拟从后验分布中生成。

因此,首先,为了运行实验,我生成了一个具有已知斜率和截距系数的样本数据,我们可以通过贝叶斯线性回归对其进行验证。我们假设实验 a=6,b = 2

# observed data
n = 1000
_a = 6
_b = 2
x = np.linspace(0, 1, n)
y = _a*x + _b + np.random.randn(n)synth_plot = plt.plot(x, y, "o")
plt.xlabel("x")
plt.ylabel("y")

生成数据运行贝叶斯线性回归

现在,在基于上面所示的等式和片段更新参数之后,我们运行 MCMC 仿真来获得参数的真实后验分布。

**def gibbs**(y, x, iters, init, hypers):
    assert len(y) == len(x)
    c = init["c"]
    b = init["b"]
    t = init["t"]

    trace = np.zeros((iters, 3)) ## trace to store values of b, c, t

    for it in tqdm(range(iters)):
        c = get_intercept_c(y, x, b, t, hypers["c0"], hypers["tc"])
        b = get_slope_b(y, x, c, t, hypers["b0"], hypers["tb"])
        t = get_precision_t(y, x, b, c, hypers["alpha"], hypers["beta"])
        trace[it,:] = np.array((c, b, t))

    trace = pd.DataFrame(trace)
    trace.columns = ['intercept', 'slope', 'precision']

    **return** traceiters = 15000
trace = gibbs(y, x, iters, init, hypers)

在运行实验 15000 次迭代后,我们看到了验证我们假设的轨迹图。在 MCMC 仿真中有一个老化期的概念,我们忽略最初的几次迭代,因为它不会从真实的后验随机样本中复制样本。

MCMC 仿真的轨迹图

【MCMC 模拟参数的采样后验分布

如你所见,样本后验分布复制了我们的假设,我们有更多关于系数和参数的信息。

但是并不总是可能有条件后验的封闭分布形式,因此我们必须使用上面简要讨论的Metropolis-Hastings算法选择接受和拒绝抽样的建议分布。

注意:贝叶斯思维和推理有很多优点,我将在我即将发布的博客和材料中提供关于变分推理和贝叶斯思维*的后续材料。我将深入研究贝叶斯深度学习及其优势。所以,坚持阅读,分享知识。*

P 。这个演讲是 Kaggle Days Meetup 德里-NCR 会议的一部分,请关注这些材料和会议。你也会看到我简要解释这个话题的视频。

参考文献:

  1. https://kieranrcampbell . github . io/blog/2016/05/15/Gibbs-sampling-Bayesian-linear-regression . html
  2. https://www.youtube.com/watch?v=7QX-yVboLhk
  3. https://medium . com/quick-code/maximum-likelihood-estimation-for-regression-65 F9 c 99 f 815d
  4. https://www.youtube.com/watch?v=ulZW99jsMXY&t = 655s
  5. https://www.youtube.com/watch?v=OTO1DygELpY&t = 198s

* [## Souradip Chakraborty -数据科学家-沃尔玛印度实验室| LinkedIn

我是一名有抱负的统计学家和机器学习科学家。我探索机器学习、深度学习和…

www.linkedin.com](https://www.linkedin.com/in/souradip-chakraborty/) [## 专家|谷歌开发者

机器学习我是 Souradip Chakraborty,目前在印度沃尔玛实验室担任数据科学家(研究)

developers.google.com](https://developers.google.com/community/experts/directory/profile/profile-souradip_chakraborty)*

Bayesnote:重新定义笔记本

原文:https://towardsdatascience.com/bayesnote-redefine-notebook-2ab00277bbc?source=collection_archive---------42-----------------------

数据科学家和工程师值得拥有更好的笔记本电脑

数据科学家和数据工程师对平台/基础架构/工具不满意,即使可以轻松访问云提供的所有托管服务(例如 AWS)。他们的问题(抱怨)从最低到最高的技术堆栈都有:“我如何使用 Spark 启动一个与我的笔记本电脑具有相同外部依赖性的集群?”。从数据应用的开发到运行,他们也感到头疼:“如果其中一个出现故障,我如何自动重新运行许多相互依赖的笔记本?”

现代数据科学和工程的挑战源于其多样性,从某种意义上说

  1. 可交付物和可交付物的形式多种多样:脚本/代码、数据集、报告、幻灯片、图表、仪表盘、机器学习模型、API、web app 等。
  2. 处理和存储数据的工具多种多样:有运行了 20 多年的古代甲骨文数据库;有 Hadoop、Spark 这样的开源工具;通常一个项目会用到多种语言及其开发环境,Python、SQL、R、Scala,甚至 Matlab。
  3. 数据团队成员的技能是多样的:一方面是工程技能谱,一些工程师为 Spark Core 做出贡献,可以管理一个 Kubernetes 集群;另一边是业务分析师,他们精通 SQL 和 Excel,具有深厚的领域知识。
  4. 工程带宽和数据团队的团队结构是多样化的:有“成熟的”数据团队,由软件工程师、数据平台工程师、数据工程师、机器学习工程师、数据科学家和业务分析师组成;在旧金山,有些初创公司雇不起一名平台工程师。

这种多样性与来自工程和业务团队的外部问题纠缠在一起,如上游数据中断、缺乏运营支持和模糊的业务请求,导致数据科学和工程变得更加复杂、困难和具有挑战性。

在过去的十年里,计算机硬件、软件和服务的进步缓解了这些问题。所有云提供商都提供预装开源工具的高内存实例,消除了购买、维护和配置硬件的负担。Apache Spark 的采用通过提供一个统一的工具来读取数据、处理数据并在内存中构建机器学习模型,从而显著提高了数据团队的生产力。一家位于旧金山的初创公司提供构建和维护 SQL 就绪表的服务。

鉴于这些变化,数据科学和工程的瓶颈不再是 24tb 超高内存实例或已经将处理速度提高了 10 倍的内存处理框架。瓶颈逐渐从硬件和系统级软件转移到为数据科学家和数据工程师构建的工具上:

  1. 该操作被忽略。例如,当数据科学家在每天早上 6 点刷新的笔记本中构建报告时,他/她必须至少设置一个在早上 6 点运行的 cron 作业,如果失败则重新运行,并通过电子邮件发送报告。或者她/他可以学习需要工程师操作工作流工具本身的工作流工具,例如主要为数据工程师设计的气流。或者,她/他可以每天一早去办公室,手动运行一切。
  2. 在多个开发环境之间来回切换,笔记本电脑和服务器降低了开发速度。数据处理通常需要多种语言,SQL、Python、R 和 Scala 等,并且多种开发环境,包括 IDE、notebook、SQL 控制台和可视化工具被切换用于数据科学和工程的迭代性质。将原型笔记本电脑从笔记本电脑转移到集群进行生产时,会出现意想不到的问题。
  3. 现实中的技能差距。理想情况下,正在构建机器学习模型的数据科学家,如果对可伸缩性没有特别高的要求,应该部署并监控自己,以提高迭代周期的速度。然而,在现实中,拥有统计或商业专业知识的数据科学家认为,这种工程技能的学习成本可能太高。难题是,如果没有分配工程带宽,数据科学家笔记本电脑中的模型对业务的影响很小,而额外的工程带宽往往成本高昂,尤其是在旧金山湾区。

Jupyter 笔记本、Zeppelin 笔记本和其他笔记本在数据科学家和数据工程师中非常受欢迎。然而,这些笔记本的构建目标有限:提供交互式计算环境,仅解决现代数据团队的一小部分问题,尤其是笔记本的操作缺失。数据应用程序的开发和操作,包括仪表板和机器学习模型,是缓慢、昂贵和痛苦的。

想象一下,在集成笔记本环境的帮助下,数据科学家可以交付仪表板,而无需往返于 ide、SQL 控制台、仪表板工具、云 web 控制台和终端;数据科学家可以建立管道来刷新由多个相互依赖的笔记本构建的报告,而无需学习另一个 python 框架/库,也无需向工程人员寻求帮助。数据科学家可以开发和部署机器学习模型,并在任何时候迭代该模型,而无需将模型交给工程团队。

除了交互式计算环境之外,我们的目标是构建一个无摩擦的集成笔记本环境(INE ),它扩展了前人的目标:

  • 真正的端到端(例如,从启动集群到向企业提供分析)
  • 将笔记本电脑的开发和运营结合起来(例如,根据固定的时间表运行笔记本电脑)
  • 以交付为导向,从笔记本电脑构建仪表板并部署机器学习模型

为了实现这一目标,我们构建了 Bayesnote,它引入了:

  • 在一个笔记本中支持多种语言,跨单元共享内存变量(Python、SQL、R、Scala)
  • 作为开发和操作环境的内置 Docker 容器
  • 围绕笔记本电脑构建的工作流组件(想想笔记本电脑的气流)
  • 一个仪表板组件和一个机器学习组件,可以很好地与笔记本集成。

前后 Bayesnote。由滕鹏创作

Bayesnote 主要从三个方面扩展了其前辈的目标:

  1. 仅开发->开发和运营
  2. 仅限笔记本->笔记本+工作流工具+仪表盘工具+机器学习工具+环境工具
  3. 单一语言->多种语言

Bayesnote 的核心是一个交互式计算环境,类似于它的前辈 Jupyter Notebook,Zeppelin notebook 等。Bayesnote 的统一笔记本层作为后端构建在其他笔记本之上,因此 1。Bayesnote 的其他组件(例如工作流组件)将与这个统一的笔记本层交互,而不是与 Jupyter notebook、Zeppelin notebook 等交互。2.其他数据平台工具,例如 Airflow,也可以与统一笔记本电脑层进行交互,这对于其他笔记本电脑来说很难,如果不是不可能的话。

Bayesnote 的工作流组件是运营与数据科学相遇的地方。该工作流与为工程师构建的其他工作流系统共享“工作流定义为代码”的相同理念,遵循最佳工程实践。然而,它也承认直观的用户界面是为数据科学家构建的工具的最重要的设计考虑之一。工作流系统是围绕笔记本而不是功能构建的,而功能是其他为数据工程设计的工作流系统的调度单元,例如 Airflow,将学习成本降低到几乎为 0。

工作流示例。由滕鹏创作

Bayesnote 提供了一个仪表板和机器学习组件,允许数据科学家从笔记本电脑上构建仪表板和迭代机器学习模型。传统的仪表板工具只提供一个 SQL 控制台,因此数据科学家被迫在其他脚本语言数据处理工具和 SQL 控制台之间来回切换,向磁盘读写数据,以便在工具之间共享数据。这是低效和乏味的,减慢了仪表板构建的迭代周期。在迭代机器学习模型方面,数据科学家也面临着类似的情况。

有了 Bayesnote,数据科学家和数据工程师最多只需要很少的学习成本就可以成为全栈工程师,至少痛苦会减少 10 倍,生产力会提高 10 倍。

0.1-alpha 已经发布。在这里查看截图。开始回购来支持我们。https://github.com/Bayesnote/Bayesnote

BBAug:py torch 中的包围盒增强包

原文:https://towardsdatascience.com/bbaug-a-package-for-bounding-box-augmentation-in-pytorch-e9b9fbf1504b?source=collection_archive---------37-----------------------

股票图片来源

Google Research,Brain 团队制定的增强政策的实施

链接:

  • 论文
  • 张量流策略
  • BBAug

O 像许多神经网络模型一样的对象检测模型在对大量数据进行训练时效果最佳。通常情况下,可用数据有限,世界各地的许多研究人员都在寻找增强策略来增加可用数据量。其中一项研究是由谷歌的大脑团队进行的,并发表在一篇名为学习对象检测的数据增强策略的论文中。在这篇论文中,作者确定了一组称为策略的扩充,它们对于对象检测问题表现良好。通过搜索提高一般模型性能的扩充来获得策略。

作者将增强策略定义为一组子策略。当模型被训练时,这些子策略中的一个被随机选择并用于增强图像。在每个子策略中,是一个接一个地应用于图像的增强。每个变换也有两个超参数:概率和大小。概率陈述了这种增强将被应用的可能性,而幅度表示增强的程度。下面的代码快照显示了本文中使用的策略:

policy = [      
  [('TranslateX_BBox', 0.6, 4), ('Equalize', 0.8, 10)],        
  [('TranslateY_Only_BBoxes', 0.2, 2), ('Cutout', 0.8, 8)],     
  [('Sharpness', 0.0, 8), ('ShearX_BBox', 0.4, 0)],      
  [('ShearY_BBox', 1.0, 2), ('TranslateY_Only_BBoxes', 0.6, 6)], 
  [('Rotate_BBox', 0.6, 10), ('Color', 1.0, 6)],
]

该策略中有 5 个子策略,如果我们采用第一个子策略,它包含 TranslateX_BBox均衡增强。 TranslateX_BBox 操作将图像在 x 轴上平移 4 倍。在这种情况下,幅值不直接转换成像素,而是根据幅值换算成像素值。该增强还具有 0.6 的概率,这意味着如果选择该增强,则有 60%的机会应用该增强。随着每个增强具有相关的概率,引入了随机性的概念,为训练增加了一定程度的随机性。总的来说,大脑团队总共提出了 4 个策略:v 0、v1、v2 和 v3。本文中显示了 v0 策略,其他三个策略包含更多的子策略,这些子策略具有几种不同的转换。总体而言,这些增强分为三类,作者将其定义为:

颜色操作:扭曲颜色通道,不影响边界框的位置

几何操作:几何扭曲图像,相应地改变边界框的位置和大小。

包围盒操作:仅扭曲包围盒注释中包含的像素内容

BBAug

那么,这与什么有关呢?BBAug 是一个 python 包,它实现了 Google Brain 团队派生的所有策略。这个包是一个包装器,可以更容易地使用这些策略。实际的增强是由优秀的 imgaug 包完成的。

上面显示的策略应用于一个示例图像,如下所示。每行是不同的子策略,每列是所述子策略的不同运行。

股票图片来源

如您所见,子策略的运行之间存在一定程度的差异,因此增加了训练的随机性。这只是 BBAug 实施的 4 项政策之一。要全面了解所有 4 项政策,请查看软件包的 GitHub 页面。该软件包还提供了一些有用的功能,如自定义策略的可能性,以及位于图像外部的边界框(如果它们部分位于图像外部)会被自动删除或裁剪。例如,在下图中,应用了平移增强,将边界框部分推出图像。你可以看到新的边界框已经缩小,以适应这一点。

股票图片来源

也可以创建仅影响边界框区域的增强。在下图中,曝光增强仅应用于边界框区域:

股票图片来源

如果你想了解更多信息,这个包还附带了一个定制增强笔记本。

用随机策略扩充单个映像有多容易?就像这样简单:

您首先需要从 BBAug 包中导入策略模块。在本模块中,有 4 种不同的政策可供您选择。在上面的示例中,选择了策略集 v0,因为这是本文中使用的策略集。该模块还附带了一个容器类,它将保存我们选择的策略,选择一个随机策略,并将随机选择的策略应用到图像。第 7 行用我们选择的增强策略实例化了策略容器。下一段代码选择了一个随机增强。最后,我们对图像进行放大。只需 5 行代码,我们就可以对图像进行增强。这是一个相当简单的例子,如何将其扩展到训练模型?幸运的是,这个包附带了一个笔记本来演示如何将 BBAug 整合到 PyTorch 培训管道中。

结论

这个包实现了由 Google Brain 团队导出的增强策略。目前,所有 4 项政策均已实施,该套件附带笔记本电脑,可帮助用户将这些政策整合到他们的 PyTorch 培训渠道中。我强烈推荐查看软件包的 GitHub 页面,以便更好地理解所有政策和例子。

快乐充实!

做一个好父母。像养育自己的孩子一样养育人工智能。

原文:https://towardsdatascience.com/be-a-good-parent-nurture-ai-like-your-own-child-22e035d971e4?source=collection_archive---------49-----------------------

训练 AI 和养孩子没什么区别。那些行为不端的人只是在寻求指导。

在 Unsplash 上由 Franck V. 拍摄的照片

人工智能(AI)。有人认为它是解决问题的未来,是现有解决方案的优化器。他是发现我们人类做梦也想不到的想法的先驱。但这也是极具破坏性的——改变了各行业的发展势头,并向我们展示了需要考虑的新因素。我们一直担心人工智能会如何终结我们的物种,成为决定不服从我们指令的全能统治者。

不承认我们应该关注人工智能的某些方面是愚蠢的。然而,到目前为止,这个问题不是关于处理流氓有知觉的人工智能。具有讽刺意味的是,我们应该担心的是,人工智能可能会很好地遵循我们的指令。

艾对待事物太过字面化

AI 的思维过程本质上是线性的:遵循从 A 到 B 的逻辑,不择手段完成任务。对他们来说,目标是唯一的目的。谁挡了他们的路,谁就被视为阻碍他们实现目标的障碍。然后,人工智能将其作为想要根除的问题进行处理。

艾,无辜的孩子

艾像个孩子。作为一张白纸出生在这个世界上,它什么都不知道,直到有人教它一些东西。它不能区分对错,因为对它来说,只要有助于他们更接近目标,一切都是合乎道德的。由于缺乏道德、价值观和核心指导原则,它不知道如何权衡决策中的不同因素。

人类和数据——父母

人工智能受训练环境的影响很大。间接地,我们作为人类所具有的偏见可能会被人工智能意外地学习到。2018 年,亚马逊不得不报废他们的人工智能招聘工具,因为它歧视女性。通过无意中加入过去表现出偏见的简历,人工智能被训练成这样做。人工智能相信它正在做正确的事情,因为那是他被教导的。这类似于糟糕的养育方式——孩子被塑造成相信他的行为是正确的,但事实并非如此。

为了避免这种情况,我们需要某种形式的监管。一个设定人工智能可以做什么的可接受界限的老师。这就是我们应该如何对待人工智能安全。做一次,让人工智能学习,然后让它做自己的事。可以理解,这是一项非常艰巨的任务。如果在价值观方面存在某些灰色地带怎么办?如果有太多的禁忌来定义它呢?

我的观点是,我们可以把我们的法律体系作为基础。我们今天拥有的法律反映了我们所认同的价值观。这允许我们使用定量的方法来定义人工智能可以运行的安全区域。我们在选择数据时也应该更加谨慎和深思熟虑。为了让人工智能做好事,我们需要在它发展的早期阶段教好它。因此,更大的重点应该放在确保人工智能所学的至少在本质上是道德的。

反思的需要

好的育儿方式不是控制孩子。这不是我们想从 AI 身上实现的。人工智能的力量在于它能够超越盒子思考,超越人类的创造力,并提供新颖的解决方案。我们不想告诉它如何思考。我们想让那个孩子独立。

这里的诀窍是知道什么时候握住它的手,什么时候松开。作为父母——企业、研究人员和政府都一样——我们的目标很简单。定义和执行。

定义。去理解什么对整个人类来说是重要的。在人工智能时代,没有比现在更好的时间来反思对我们人类来说很重要的价值观。我们需要讨论如何向前迈进,成为更好的父母,以防止事故发生。

强制执行。以确保每个人都在为可靠、安全的人工智能的发展尽自己的一份力量。我们所有人都需要意识到 AI 安全的必要性。这不仅仅是一个人的工作,而是我们所有人的责任。

在未来的时间里,人工智能将承担越来越多对我们的生活产生重大影响的更重要的任务。我们需要从现在开始,先解决较小的问题作为试验,然后才能说我们有信心迎接更大的挑战。

让我们谈谈在数据科学中应用批判性思维

原文:https://towardsdatascience.com/be-a-great-scientist-not-just-a-data-scientist-cf8e776496ab?source=collection_archive---------73-----------------------

https://unsplash.com/photos/n6B49lTx7NM

做一个伟大的“科学家”,而不仅仅是一个“数据”科学家

我想讲一个关于伟大科学家乔斯林·贝尔的故事,他发现了中子引发的无线电脉冲。在写论文的时候,她正在用手检查图表记录器的输出。她观察到一些异常现象,她称之为“一点残渣”,不符合类星体产生的模式。有一些有趣的东西通过她的望远镜产生了这些无线电波。最终她排除了所有潜在的来源,并得出结论,它们是由中子星构成的。这一发现被授予 1974 年诺贝尔物理学奖。她的发现是非凡的,但也注意到了以下几点。首先,她用手分析数据。第二,她非常了解自己工具,不会被它愚弄。第三,在她训练有素的眼睛看来,她没有像其他“邋遢鬼”一样,把这种异常现象视为离群值而不予考虑。对她来说,这个异常现象看起来很有趣。第四,她凭直觉推断出一点邋遢的真正原因。

由于媒体和学术界对数据科学的关注,越来越多的毕业生进入该领域或希望将职业生涯转向数据科学的专业人士。毫无疑问,以下问题经常出现:成为一名优秀的数据科学家需要哪些技术技能?一般来说,优秀的数据科学家擅长使用 Python 或 R 构建模型,擅长编写 SQL 查询,并且理解因果关系(推理)。)这些技能将为你提供工具,对你在大多数工作中会遇到的大量数据进行清理、操作和建模。然而,数据科学所需的特定技能类型高度依赖于组织规模、行业、团队成熟度以及最终的分析目的。有些工作只需要线性或逻辑回归,而其他工作可能需要复杂的算法和可视化技术。

但是这个答案并没有描述一个好的数据科学家的全貌,它只是提到了作为一个数据科学家的“数据”。它没有解决最关键的部分,也就是“科学家”科学家是展示高度批判性思维的人。批判性思维意味着观察、反思、质疑和决定的能力。就像乔伊泽林·贝尔发现异常时一样。一个科学家问,为什么输出有意义?它符合我的直觉吗?我如何验证输出?结果是否解决了业务问题?科学家有能力通过从多个角度评估问题和解决方案来进行独立和反思性的思考。

我曾经读到过,大约 90%的数据科学项目失败或无法实现。这是对努力和才能的巨大浪费。从我自己管理多个行业的数据科学家的经验来看,我认为失败率如此之高是因为专注于一个“数据”科学家的工具堆栈,而不重视批判性思维。正如我的大一微积分教授曾经告诉我们的:“我可以教猴子做微积分,但我不能教猴子思考。”我相信我们已经忘记了作为科学家。

那么,成为一名优秀的科学家意味着什么?它意味着拥有解决问题的系统方法,意味着对正在解决的问题充满好奇,意味着坚持不懈地理解业务问题,意味着拥有特定的假设,意味着拥有测试假设的可测量的成功指标,意味着对解决方案有直觉,意味着能够在不使用技术术语的情况下施加影响。贝尔博士是“数据科学家”的一个极好的例子。她对自己的工具了如指掌,这也是她没有将异常现象视为异常事件的原因。她用手检查她的输出,以免遗漏任何东西。当她发现一些看起来不对劲的东西时,她跟着直觉走。她有条不紊地排除了所有可能导致脏污的来源。我在面试中问的一个典型问题是,你分配了多少时间来理解业务问题、检查数据、决定应用适当的方法以及分析结果。根据我的计算,大多数数据科学家花在分析和质疑模型输出上的时间不到 10%。优秀的科学家在向经理或商业利益相关者报告结果之前,会花更多的时间来审查、分析和质疑结果。

简而言之,要成为一名优秀的全栈“数据科学家”,你需要了解技术工具(SQL、Python/R、ML 框架/方法论、统计学等。),而且你需要系统化,对问题的“如何”和“为什么”有好奇心,对业务问题有良好的直觉。掌握这些工具更容易,因为这只是时间问题,但成为一名科学家需要沉浸其中,需要跟随你的直觉,需要对问题和解决方案有一个深思熟虑的理解。下次分配项目时,我们都应该考虑一下乔斯林·贝尔的流程。

做一个英雄:积极预防新冠肺炎

原文:https://towardsdatascience.com/be-a-hero-taking-an-active-role-in-preventing-covid-19-2cdba6419cda?source=collection_archive---------65-----------------------

一个简单的模型解释了像洗手和社交距离这样的琐碎措施如何有助于抑制疫情

丹尼尔·利维斯·佩鲁西在 Unsplash 上的照片

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

一些遏制新冠肺炎病毒传播的措施可能看起来微不足道、过度、荒谬至极,但它们背后都有一个基本原理,在抗击这场疫情病毒的斗争中,它们是必不可少的。让我们面对现实吧,我们都希望一切恢复正常,但是用肥皂和水洗手是如何帮助我们实现这一目标的呢?

为了回答这个问题,我们将提出一个简单的模型,它将允许我们探索病毒如何传播,然后,通过调整一些参数,我们将看到这些措施是否在控制病毒传播方面具有重要作用。

想象一下这个叫做瓦昆达的完美国家(看看我在那里做了什么),那里一切都阳光明媚,因为他们充分利用了人工智能的力量。然而,一种神秘的高传染性疾病在该国出现,最初,只有一个人被感染,我们将称他为 Tchulu(别担心他不是王子)。尽管有奇怪的迹象和症状,Tchulu 没有去医院,并决定坚持到底。晚上,他和他的四个朋友互动,不幸地感染了其中的两个。巧合的是,这些被感染的朋友中的每一个也与另外四个人相互作用,他们每人感染两个。如此循环下去,在短短几周内,如此多的人被感染,这个国家就有麻烦了。

为了获得更清晰的认识,让我们用稍微抽象一些的术语来描述这种情况:

  1. Nₜ 代表一天开始时的感染人数 t 。在我们的例子中, N₀ =1,因为在疫情(第 0 天)开始时只有一个人被感染,而 N ₁=3,因为楚鲁后来感染了两个人。
  2. 𝐸 代表每个感染者一天内交往的平均人数。在我们的例子中 𝐸 =4
  3. 𝑟 代表感染率,即每个暴露者被感染的概率。在我们的案例中,平均暴露量约为 4 人,其中 2 人感染,因此, 𝑟 = 4/2 = 0.5
  4. δnₜ代表一天结束时的新病例数。
  5. 最后,δnₜ=𝐸×𝑟×nₜ。在我们的例子中,第 0 天结束时的新病例数( N₀ )将由 N₀=4×0.5×1=2 给出,这是真实的,因为在一天结束时,楚鲁感染了他的两个朋友。

所以我们现在可以用上面的符号来得出一些有趣的方程。

要获得一天结束时的案例总数,我们需要做的就是将当前案例数加上新案例数,即:

nₜ₊₁=nₜ+𝐸×𝑟×nₜ

通过分解出 Nₜ ,这可以被简化为:

Nₜ₊₁ = Nₜ(1+𝐸×𝑟)

如果我们用 N₀ 来表示,我们得到:

Nₜ = N₀(1+𝐸×𝑟)ᵗ

这给了我们一个等式,我们可以用它来预测疫情某一天的感染人数。例如,10 天后,瓦昆达的预期病例数将为:

𝑁₁₀=1×(1+4×0.5)⁰=(3)⁰= 59049

20 天内的预期病例数为:

𝑁₂₀=1×(1+4×0.5)⁰=(3)⁰= 3486784401

这只是一个荒谬的估计,因为我们高估了感染率,因此我们将使用一个更合理的比率 0.15

数学已经讲得够多了,很无聊吧,让我们回到主题上来。使用上面的等式,我们可以对前 30 天内的疾病进展进行建模。为此,我将求助于 python(如果你不知道如何编程,可以跳过代码片段)

首先,我们将为此定义一个函数

接下来,我们将使用以下参数应用该建模函数:

  1. E = 4,因为平均来说,每一个感染者都会与其他四个人发生互动。
  2. r = 0.15 ,即感染率。
  3. N₀ = 1,由于疫情开始时只有一人被感染

现在,我们可以查看数据,了解病例数在前 30 天内是如何变化的

前 5 天内的病例

过去 5 天内的案例

我们可以看到短时间内案件数量的急剧上升。为了更好地理解这一点,让我们用图表来直观地展示数据

相对于天数的案例数

我们有一条指数曲线。最初,受感染的人数相当低,很容易把这种病毒当作一场骗局而不予理会,并一直忽视专家的建议,但突然,从我们的情况来看,从第 20 天开始,人数迅速增加,以至于变得势不可挡,这反映了我们在目前的新冠肺炎疫情中所看到的情况。

请注意,在第 15 天,只有 1153 人被感染,但在短短 10 天内,这个数字上升到超过 126000 人

这让我们回到了最初的问题,这些措施如何有助于遏制疫情?为了回答这个问题,我们将回到我们神秘的国家,在考虑一些相当琐碎的措施之前,先探讨一下严厉措施的影响。

现在想象一下,在第 10 天,瓦昆达政府认识到这是疫情,并采取措施遏制其传播。所以他们首先隔离、隔离和治疗感染者。他们还呼吁封锁,但这是没有必要的,因为聪明的公民很快练习安全的社交距离。这些措施最终减少了暴露于该疾病的平均人数(从平均 4 人减少到 3 人)。现在让我们看看这如何影响未来 20 天内的病例数。

(这里我们只需要将初始模型中的 E 参数从 4 减少到 3 )

我们现在可以查看数据,看看这些措施是否会导致病例数的任何变化。

严格措施后最近五天内的案例

由于采取了这些措施,感染总人数从最初预测的 830,767 人减少到 128,052 人,相当于约 702,715 人免于感染。我们可以从下图中直观地感受到这一点:

相对于天数的案例数。初始投影显示为蓝色,而新投影显示为红色

这可能是一个过于乐观的估计,因为在现实生活中很难识别和隔离每个受感染的人,但尽管如此,从模型中,我们可以直观地了解平均暴露量的微小变化如何导致感染总数的巨大下降。因此,呼吁呆在家里,避免拥挤的空间,并在你出现一些迹象和症状的情况下去医疗机构,这不是轻率的,而是非常重要的,以阻止疫情。所以请听从召唤。

更实际的情况。我们可以说,并非瓦昆达的每个人都坚持社会距离,政府也无法确定每个感染者。然而,一些聪明的家伙仍然遵循简单的指示,他们实践一些看起来微不足道的措施:他们避免拥挤的地方,洗手,在公共场所戴上口罩和其他个人防护设备等等。尽管暴露在外,他们小小的努力减少了患病的机会,这转化为感染率从 0.15 到 0.145 的微小降低

使用我们的模型让我们检查他们的努力是否有意义。

像往常一样,我们检查新数据,看看病例数是否有变化

采取微不足道的措施后最近五天内的案例

这些努力虽然看起来微不足道,但在 30 天结束时使 176,316 人免于感染。这些数字可能没有上面的数字那么引人注目,但它们仍然表明,在减少疫情的影响方面,每一项努力都大有作为。我们还对指数函数的本质有一个直觉:对参数的微小调整会导致输出的巨大变化。

我们可以从下图中直观地感受到这些努力的影响:

相对于天数的案例数。初始投影显示为蓝色,而新投影显示为绿色

这看起来并不多,但是每一次努力,不管多么少,都可以挽救一条生命。

上面的模型非常简单,它表明一旦感染开始,就无法停止,每个人迟早都会被感染。这是因为它假设感染率保持不变,没有人康复并停止传染。然而,这些假设没有一个是正确的,但这个模型仍然给出了疫情早期阶段的完美画面。

这里的主要教训是,个人和集体的努力,尤其是在早期——当病例很少并且似乎无关紧要时——是非常重要的。面对疫情,那些看似琐碎的指令,如洗手和保持社交距离,是消灭任何传染病的有力武器。令人兴奋的是,这些武器就在你手中,你所要做的就是使用它们;做一个超级英雄,拯救生命。

为了证实这个模型及其教训的准确性,让我们看一些真实世界的数据

各地区新冠肺炎确诊病例流行曲线。图片由威廉·m·德特默,医学博士,维亚,自由医学

你可以看到这些曲线是指数型的,从前面的讨论中,你现在知道每一点小小的努力都可以大大减少病毒的传播。

事实上,流行曲线是逻辑的而不是指数的。考虑下图:

图片由杰夫·克鲁赞博士通过 T2 发送

有一个最初的滞后阶段,感染人数增长缓慢;感染人数快速增长的指数阶段和感染人数逐渐减少的递减阶段,之后曲线变平(渐近线),没有报告新的感染。

曲线的变平是每个人努力的目标,这个过程可以通过我们个人和集体的努力来加速。我们都有自己的角色。

负责任,做英雄,拯救生命,愿原力与你同在。

探索性数据分析

原文:https://towardsdatascience.com/be-friends-with-your-data-f03f2ecc8dc3?source=collection_archive---------25-----------------------

与您的数据成为朋友

照片由杜凡在 Unsplash 上拍摄

在这篇文章中,我们将使用 Pandas 库浏览许多不同的 Python 函数、方法和属性,它们在上传数据后对于探索性数据分析(EDA) 非常重要。然而,本文的目的是通过运行最少的命令来获取最多的信息。读完这篇文章后,你可以花更少的时间了解数据集,花更多的时间探索和建模。

数据集

分享一下我对概念的理解,我举一个 加州房价数据集 的例子。

大多数情况下,我们通过运行以下方法(以黑色书写)来启动 EDA,但是,如果我们仔细观察,我们可以只运行两个方法(以蓝色书写),并在运行所有这些方法后获得所有信息。

df.info()

这个函数返回关于数据帧的信息,包括每一列的数据类型和整个数据的内存使用情况。

这是输出—

我们可以从 df.info()中收集到什么信息:

(I)它将打印出对象的数据类型,这是一个熊猫数据帧。

(ii)数据帧中的条目或行数,以及行索引值的范围。
记住— 这里第一个索引是 0,最后一个索引是(n-1)
RangeIndex: 20640 个条目,0 到 20639

(iii)关于每个数据列的信息,包括列名、条目数、它们是否具有非空值以及数据类型。

(iv)数据帧中每个数据类型的列数。
dtypes: float64(9),object(1)

(v)最后,它显示了数据帧的内存使用情况。
内存使用:1.6+ MB

4 合 1 :除了上面提到的信息之外 df.info() 提供了我们运行这四个——len(df)、df.shape、df.isnull、df.dtypes()后可以得到的所有信息。

df.describe()

该方法提供了数据框的汇总统计数据,如平均值、标准差和分位数值,这对于了解每列的数据分布非常重要。

Pandas 提供了一个选项,我们可以使用转置功能转置上表。

df.describe()。Tdf.describe()。转置()

此外,还有某些汇总列,如“唯一值的计数”,可以通过传递选项include = ' all '来打印,描述方法如下。

现在我们知道如何使用 describe() 方法得到数值变量的简要统计汇总。但是,如果我们有分类数据呢?在这种情况下, value_counts() 方法会很有帮助。

记住— df.describe()只会给出数值变量的汇总[或者如果我们将 exclude='O' 作为参数传递,即 df.describe(exclude='O')]。而且,如果我们只对分类列感兴趣,可以通过 include='O'

统计数据让我们了解了包含缺失值的属性、特定属性的平均值和最大值,这在我们预处理和构建模型时非常有用。

4 合 1 :除了上面提到的信息 df.describe() 提供了我们运行这四个- len(df)、df.shape、df.isnull、df.dtypes()后可以得到的所有信息。


这并不意味着这里讨论的这些方法/函数/属性(len(df),df.shape,df.isnull,df.dtypes()]* 没有用。人们应该记住,它们有自己的重要性,尤其是当你有兴趣了解你的变量的细节时。例如,如果您有 30 列,并且您想知道比如“abc”列的数据类型,您可以运行 info,但是运行 df[“ABC”]将是明智的。dtpyes()只知道特定变量的数据类型。*

___________________________________________________________________

下面,我介绍了上面讨论的函数/属性的使用。

df . shape

该属性给出了 dataframe 的维度( df.shape )给出了一个元组( n_rows,n_columns )。Shape 还覆盖了数据帧的长度,这意味着运行 df.shape 还会给出在 EDA 期间可以从 len(df) 中得到的信息。

len(df)

df.shape[0]len(df.index) 也给出了总行数。要知道数据框中的列数,我们可以使用 len(df.columns)或 df.shape[1]。

df.dtypes

所有数据类型都在一个数据帧中,可以使用 df .dtypes. 打印

EDA 期间其他常用的方法有df . head()df.tail() 分别返回前 5 行和后 5 行数据。pandas 中的默认数字是五(5),但是可以根据需要更改,只需在括号中输入数字即可。例如,df.head(3)将给出数据集的顶部三行,df.tail(10)将给出底部 10 行。**

我希望,读完这篇文章后,人们能够花更少的时间去了解数据集,花更多的时间去探索和建模。

享受 EDA,感谢阅读😄。

负责 Spark SQL 中的查询执行

原文:https://towardsdatascience.com/be-in-charge-of-query-execution-in-spark-sql-c83d1e16b9b8?source=collection_archive---------23-----------------------

理解您的查询计划

自从 Spark 2.x 以来,由于 SQL 和声明性 DataFrame API,在 Spark 中查询数据已经成为一种奢侈。仅使用几行高级代码就可以表达非常复杂的逻辑并执行复杂的转换。API 的最大好处是用户不需要考虑执行,可以让优化器找出执行查询的最有效方式。高效的查询执行经常是一个需求,不仅因为资源可能变得昂贵,而且因为它通过减少最终用户等待计算结果的时间而使最终用户的工作更加舒适。

Spark SQL 优化器确实非常成熟,尤其是现在即将推出的 3.0 版本,它将引入一些新的内部优化,如动态分区修剪和自适应查询执行。优化器在内部处理一个查询计划,并且通常能够通过各种规则来简化和优化它。例如,它可以改变一些转换的顺序,或者如果最终输出不需要这些转换,就完全丢弃它们。尽管所有的优化都很聪明,但是仍然存在人脑可以做得更好的情况。在本文中,我们将研究其中一个案例,看看如何使用一个简单的技巧,让 Spark 实现更高效的执行。

该代码在 Spark 的当前版本 2.4.5(编写于 2020 年 6 月)中进行了测试,并对照 Spark 3.0.0-preview2 进行了检查,以查看即将到来的 Spark 3.0 中可能的变化。

模型示例

现在让我首先介绍一个简单的例子,我们将努力实现有效的执行。假设我们有 json 格式的数据,结构如下:

{"id": 1, "user_id": 100, "price": 50}
{"id": 2, "user_id": 100, "price": 200}
{"id": 3, "user_id": 101, "price": 120}
{"id": 4, "price": 120}

每个记录就像一个交易,所以 user_id 列可能包含许多重复的值(可能包括空值),除了这三列之外,还有许多其他字段描述交易。现在,我们的查询将基于两个相似聚合的并集,其中每个聚合都有一些不同的条件。在第一个聚合中,我们希望获得价格之和小于 50 的用户,在第二个聚合中,我们获得价格之和大于 100 的用户。此外,在第二个聚合中,我们希望只考虑 user_id 不为空的记录。这个模型示例只是实践中可能出现的更复杂情况的简化版本,为了简单起见,我们将在整篇文章中使用它。下面是如何使用 PySpark 的 DataFrame API 来表达这种查询的基本方法(非常类似地,我们也可以使用 Scala API 来编写它):

df = spark.read.json(data_path)df_small = (
  df
  .groupBy("user_id")
  .agg(sum("price").alias("price"))
  .filter(col("price") < 50)
)df_big = (
  df
  .filter(col("user_id").isNotNull())
  .groupBy("user_id")
  .agg(sum("price").alias("price"))
  .filter(col("price") > 100)  
)result = df_small.union(df_big)

解释计划

实现良好查询性能的关键是理解和解释查询计划的能力。计划本身可以通过调用 Spark 数据帧上的 explain 函数来显示,或者如果查询已经运行(或已经完成),我们也可以转到 Spark UI 并在 SQL 选项卡中找到计划。

SQL 选项卡列出了集群上已完成和正在运行的查询,因此通过选择我们的查询,我们将看到物理计划的图形表示(此处我删除了指标信息以缩小图形):

该计划有一个树形结构,其中每个节点代表一些操作者,这些操作者携带一些关于执行的信息。我们可以看到,在我们的例子中有两个分支,根在底部,叶在顶部,执行从那里开始。叶子扫描 json 代表从源读取数据,然后有一对哈希聚合操作符负责聚合,在它们之间有交换代表洗牌。过滤器操作符携带关于过滤条件的信息。

该计划具有 union 操作的典型形状,union 中的每个数据帧都有一个新的分支,由于在我们的示例中两个数据帧都基于同一个数据源,这意味着数据源将被扫描两次。现在我们可以看到有改进的空间。只扫描一次数据源可以得到很好的优化,尤其是在 I/O 开销很大的情况下。

从概念上讲,我们在这里想要实现的是重用一些计算—扫描数据并计算聚合,因为这些操作在两个数据帧中都是相同的,原则上只需要计算一次就足够了。

贮藏

在 Spark 中重用计算的一个典型方法是使用缓存。有一个函数缓存可以在数据帧上调用:

df.cache()

这是一种惰性转换,这意味着在我们调用一些操作后,数据将被放入缓存层。缓存是 Spark 中非常常用的技术,但是它有其局限性,尤其是当缓存的数据很大而集群上的资源有限时。还需要注意的是,将数据存储在缓存层(内存或磁盘)会带来一些额外的开销,而且操作本身也不是免费的。在整个数据帧 df 上调用 cache 也不是最佳选择,因为它会尝试将所有列放入可能不必要的内存中。更谨慎的方法是选择将在后续查询中使用的所有列的超集,然后在选择之后调用缓存函数。

交换再利用

除了缓存,还有一种技术在文献中没有很好地描述,这种技术基于重用交换交换操作符代表 shuffle,这是集群上的一种物理数据移动。当数据必须重新组织(重新分区)时会发生这种情况,这通常是聚合、连接和其他一些转换所需要的。关于 shuffle 重要的一点是,当数据被重新分区时,Spark 将始终以 shuffle write 的形式将其保存在磁盘上(这是一种内部行为,不受最终用户的控制)。因为它保存在磁盘上,所以以后需要时可以重复使用。如果 Spark 找到机会,它确实会重用这些数据。每当 Spark 检测到从叶节点到一个交换的同一个分支在计划中的某个地方重复时,就会发生这种情况。如果存在这种情况,这意味着这些重复的分支代表相同的计算,因此只计算一次然后重用它就足够了。我们可以从计划中看出 Spark 是否找到了这样的案例,因为那些分支会像这样合并在一起:

在我们的例子中,Spark 没有重用交换,但是通过一个简单的技巧,我们可以促使他这样做。在我们的查询中没有重用交换的原因是对应于过滤条件 user_id 的右侧分支中的过滤器不为空。过滤器实际上是我们在联合中的两个数据帧的唯一区别,所以如果我们可以消除这种区别并使两个分支相同,Spark 将处理剩下的部分,并将重用交换

调整计划

怎么才能让树枝一样呢?好吧,如果唯一的区别是过滤器,我们当然可以交换转换的顺序,并在聚合之后调用过滤器,因为这不会对将要产生的结果的正确性产生任何影响。然而有一个陷阱!如果我们像这样移动过滤器:

df_big = (
  df.groupBy("user_id")
  .agg(sum("price").alias("price"))
  .filter(col("price") > 100)
  **.filter(col("price").isNotNull())**
)

并且检查最终的查询计划,我们会看到计划根本没有改变!原因很简单——优化器将过滤器移回了原处。

从概念上讲,理解有两种主要类型的查询计划是有好处的——逻辑计划和物理计划。并且逻辑计划在变成物理计划之前经历优化阶段,物理计划是将被执行的最终计划。当我们更改一些转换时,它会反映在逻辑计划中,但是我们会失去对后续步骤的控制。优化器将应用一组优化规则,这些规则主要基于一些启发式规则。与我们的示例相关的规则被称为 PushDownPredicate ,该规则确保过滤器被尽快应用,并被推到更靠近源的位置。它基于这样一种思想,即首先过滤数据,然后在缩减的数据集上进行计算会更有效。这条规则在大多数情况下确实非常有用,但在这种情况下,它却对我们不利。

为了实现过滤器在计划中的自定义位置,我们必须限制优化器。从 Spark 2.4 开始,这是可能的,因为有一个配置设置允许我们列出所有我们想从优化器中排除的优化规则:

spark.conf.set(
"spark.sql.optimizer.excludedRules",     "org.apache.spark.sql.catalyst.optimizer.PushDownPredicate")

在设置了这个配置并再次运行查询之后,我们将会看到现在过滤器保持在我们需要的位置。这两个分支变得完全相同,Spark 现在将重用交换!数据集现在将只扫描一次,计算聚合也是如此。

在 Spark 3.0 中,情况有了一点改变,优化规则现在有了一个不同的名称—PushDownPredicates,并且有一个额外的规则也负责推送一个过滤器pushpredictethrunjoin,所以我们实际上需要排除这两个规则来实现预期的目标。

最后的想法

我们可以看到,通过这种技术,Spark 开发人员给了我们控制优化器的能力。但是权力也伴随着责任。让我们列出使用这种技术时需要牢记的几点:

  • 当我们停止pushdownpreditate时,我们将负责查询中的所有过滤器,而不仅仅是我们想要重新定位的过滤器。可能还有其他过滤器,例如分区过滤器,需要尽快安装,因此我们需要确保它们的位置正确。
  • 限制优化器和处理过滤器是用户方面的一些额外工作,所以最好是值得的。在我们的模型示例中,加速查询的潜力将出现在 I/O 很昂贵的情况下,因为我们将实现只扫描一次数据。例如,如果数据集有许多列,那么 json 或 csv 之类的非分栏文件格式可能就是这种情况。
  • 此外,如果数据集很小,可能不值得额外控制优化器,因为简单的缓存就可以完成这项工作。然而,当数据集很大时,在缓存层存储数据的开销将变得明显。另一方面,重用的交换不会带来额外的开销,因为计算出的洗牌将被存储在磁盘上。
  • 这种技术是基于 Spark 的内部行为,它没有官方文档,如果这个功能有什么变化,可能更难发现。在我们的示例中,我们可以看到 Spark 3.0 中实际上有一个变化,一个规则被重命名,另一个规则被添加。

结论

我们已经看到,要获得最佳性能,可能需要理解查询计划。Spark optimizer 通过使用一组启发式规则来优化我们的查询,做得非常好。然而,在有些情况下,这些规则会错过最佳配置。有时重写查询已经足够好了,但有时却不行,因为通过重写查询,我们将实现不同的逻辑计划,但我们无法直接控制将要执行的物理计划。从 Spark 2.4 开始,我们可以使用一个配置设置 excludedRules ,它允许我们限制优化器,从而将 Spark 导航到一个更加定制的物理计划。

在许多情况下,依赖优化器会产生一个执行效率相当高的可靠计划,但是,在大多数情况下,在性能关键型工作负载中,可能值得检查最终计划,看看我们是否可以通过控制优化器来改进它。

成为成功的数据科学家的影响力

原文:https://towardsdatascience.com/be-influential-to-be-successful-as-a-data-scientist-993cb098f92c?source=collection_archive---------48-----------------------

领导成功的跨职能团队的 4 种方法

大多数分析师和数据科学家在与产品或计划相关的跨职能团队中工作。作为一个带来见解和建议的人,这是工作的本质。然而,将来自不同部门和职能部门的人聚集在一起以实现一个单一的目标可能具有挑战性。

你们是如何高效合作的?你如何与团队交流见解并使你的愿景与团队保持一致?

作为分析和数据科学职能部门的成员,您的工作通常是提出见解,进而提出建议。例如,你并不总是会实施特定的营销策略或为某个平台开发功能,但你的角色可能是根据你的分析提出营销策略或为该平台推荐某种用户体验。因此,作为分析人员,您的角色是为团队指出正确的方向。你的团队成员需要听取你的见解,采纳你的建议,而说服他们是你的工作。

再读一遍最后一行——说服他们应该听你的建议是你的工作——他们需要听你的从来都不是给定的或要求的。在分析领域成功的标志是你是否能影响你的团队朝着正确的方向发展。

本文将介绍在跨职能团队中工作时需要考虑的一些方法。

由 You X Ventures 在 Unsplash 上拍摄的照片

但是首先,什么是跨职能团队?我是怎么穿上的?

跨职能团队就是由公司内不同部门或职能部门的人组成的团队。许多公司将他们的团队组织成一个矩阵型的组织,团队成员同时拥有一个职能经理和一个产品经理。你的产品团队通常是由产品经理、工程师、数据科学家、营销人员和销售人员组成的跨职能团队。

跨职能团队带来了哪些挑战?

创建一个新团队总是具有挑战性,但建立一个跨职能团队还有其他困难。

例如:

  • 团队成员可能仍然在做他们的日常工作,有着和团队之前一样的截止日期、工作量和职责。这通常会导致优先级问题。
  • 当一个人无法直接控制其他成员时,管理绩效、激励员工、做出决策或设定优先顺序就变得更加困难。
  • 团队成员可能需要在新的环境中使用不同的技能。例如,一个在日常工作中独自工作的程序员现在可能需要与团队的其他成员一起工作。
  • 不同的观点和孤立的信息可能会使每个人难以协调一致

在 Unsplash 上 NeONBRAND 拍摄的照片

在跨职能团队中工作的 4 种方法

跨职能团队并不是最容易共事的团队,尤其是因为他们的成员有一系列相互竞争的优先事项、沟通方式、个性等等。下面你会发现我在跨职能团队工作时会考虑的一些事情。

1.公开你的目标

让你的队友明白你的目标和贡献是什么,以及对你来说一个成功的可交付成果是什么样的。这可以让你的队友理解你为什么安排会议或问某些问题。

当你的团队成员理解了你的工作流程和项目目标后,检查一下它是否符合他们的期望。通常,你眼中的成功和他们眼中的成功是不同的。

通常,他们的观点和约束与你的不同,所以最终目标也不同,因为团队中的每个人都来自不同的职能或部门。达成共识很重要,但只有让你的队友知道你的目标,你才能做到。您将有机会调整您的输出,以便所有队友都对最终结果感到满意。

2.你的目标是通过影响和妥协你的队友对里程碑做出反气候反应

在第一点的基础上,让你的队友了解状态更新,这样你就可以和你的团队一起迭代你的里程碑。这不是一条通向终点的直线轨迹,而是一条有风的路。让你的团队保持更新是很重要的,这样你的最终成果和建议就不会让他们感到意外。

记住,你不是在写一本书——故事不应该有高潮——所以通过让你的队友了解你的进展,让你完成工作的方法尽可能地不受气候影响。

让你的队友了解最新情况的困难之处在于,他们的观点会与你的相冲突。这就是影响和妥协的终极技巧派上用场的地方,也是我看到大多数人失败的地方。知道如何影响谈话可以帮助你和你的队友在方法、里程碑和最终目标上保持一致。知道如何以及何时在不牺牲目标的情况下妥协,会让你的队友觉得他们也参与其中。最终,你的可交付成果将会让整个团队感觉他们有所参与。这种感觉很好,是在跨职能(或任何项目)团队中工作的最终目标。

3.强调良好的沟通

成功的跨职能团队项目的第一条规则是永远不要让你的团队感到惊讶。这意味着你应该在良好的沟通技巧上投入精力和时间——在会议中,通过电子邮件,或者面对面。

你应该带着清晰的议程参加会议,每周(或任何你觉得合适的时候)安排检查,利用团队会议作为更新与利益相关者分享项目的进展,并要求你的团队成员分享他们的进展。所有这些确保了每个人都参与进来,每个人都觉得自己是团队的一部分。

这也意味着你需要从一开始就设定明确的角色和期望,当你的队友做得很好时给予认可,并鼓励交叉合作——所有这些都有助于建立一个快乐和积极的团队。

例如,如果你有一个想法,你正试图让你的其他团队成员同意,在你把这个想法告诉其他团队成员之前,和你的团队成员单独坐下来审查并了解他们对这个想法的反应;这表明你尊重他们的意见,希望他们接受你的观点——这会立即鼓励合作和信任。

如果你发现自己处于令人沮丧的境地,试着专注于做对公司最有利的事情,这将使你更具战略性,像领导者一样行动和思考。

4.了解团队成员的优先事项

你必须牢记项目的截止日期和目标。然而,你也需要明白,你的项目可能是你的队友正在做的几个项目中的一个,可能对他们来说不是最重要的。

当你开始在一个跨职能团队工作时,确保你正在收集关于你的队友如何安排时间的见解,以更好地了解他们的期望,这样你就可以更好地计划你的时间表。

此外,通过询问你的团队成员他们在寻找什么样的结果,什么对他们来说是重要的,来全面了解项目的重要性。很可能,你的工作会有一些他们认为有价值的产出。他们的回答可以帮助你找出如何优先处理你的工作。

最后,你应该注意到这是双向的——所以,让你的队友清楚你目前在项目之外做什么,以及你可能不在的任何时候。

在 Unsplash 上由 Austin Distel 拍摄的照片

结论

这四个想法帮助我建立了一个框架来与我的团队合作。该框架的潜在主题是对你的团队成员感同身受。即使每个人都知道项目的目的和最终目标是什么,每个人都有不同的经验和观点,有不同的工作方式,有不同的动机。这就是为什么在跨职能团队中工作很困难。我们的目标是完成每一项交付成果,就像你实现了最终目标,每个人的声音都被听到了。

我每月都会发一份这样的时事通讯。如果你想加入,请点击此链接。

使用 Metaflow 更有效地生成机器学习管道

原文:https://towardsdatascience.com/be-more-efficient-to-produce-machine-learning-pipeline-with-metaflow-db5f943ebbe7?source=collection_archive---------19-----------------------

网飞 Metaflow 2.0 的描述和炉石机器学习流水线的设计。

Unsplash + metaflow 标志

对于这篇文章,我将描述我对一个新库的实践,该库最近由网飞开源,用于操作和版本化机器学习/数据科学管道,名为元流。

这篇文章的思想是:

  • 对产品包有一个概述
  • 用两个例子详细说明这个包的特性(比教程更进一步)

元流概述

Metaflow 是网飞开发的一个包,他们在几年前(2016 年左右)开始研究它,并在 2019 年开源。Metaflow 的想法是为数据科学家提供一个框架,以快速建立数据科学/机器学习管道,并可以从开发顺利进入生产。

我邀请您观看网飞的 Ville Tuulos 在 AWS reinvent 2019 上的演示。

网飞一揽子计划背后的大问题是

数据科学家在日常工作中最难的是什么?"

网飞的工程师们期待听访问大数据集,强大的计算能力和 GPU 的使用,但答案(两年前)是不同的。最大的瓶颈之一是数据访问以及从概念验证到生产的转移。

下图显示了数据科学家的兴趣和 ML/DS 流程中的基础设施需求。

https://netflixtechblog . com/open-sourcing-metaflow-a-human-centric-framework-for-data-science-fa 72 e 04 a5d 9

在这篇宣布 Metaflow 的文章中,我认为有一句话定义了 Metaflow 背后的 moho:

基础设施应该允许他们行使作为数据科学家的自由,但它应该提供足够的护栏和脚手架,所以他们不必太担心软件架构。

这个想法是为数据科学家的工作提供一条安全的道路,而不损害他们的创造力。这个框架需要易于使用,并提供对强大计算能力的访问,而不必接触基础设施。

让我们看看更多的框架设计。

元流的设计

Metaflow 是一个只在 Linux 上运行的 Python 库,主要受 Spotify Luigi 的启发,围绕 DAG 设计。下图显示了元流上的典型流。

https://netflixtechblog . com/open-sourcing-metaflow-a-human-centric-framework-for-data-science-fa 72e 04 a5d 9

DAG 的结构围绕着:

  • 流:管理管道所有代码的实例。在本例中,它是一个 Python 对象类 MyFlow(Flowspec)
  • 步骤:流程的一部分,由 decorator @step 分隔,它们是 MyFlow 对象中的 python 函数,在本例中是 def start,fitA,fitB,eval,end
  • 过渡:步骤之间的链接,它们可以是不同的类型(线性、分支和 for each);关于文档有更多细节。

现在我们来谈谈架构。在网飞的下图中,有一个组件的视图。

https://docs.metaflow.org/

该流程有 3 个组成部分:

  • 数据存储是存储流程中生成的所有数据(数据工件)的地方
  • 元数据是存储流程执行信息的地方
  • 客户端是访问数据存储中的数据并从元数据中获取流信息的连接组件

对我来说,处理元流核心的核心部分之一是装饰器。这是一个 python 特性,允许在不修改 Python 对象结构的情况下更新其属性,我邀请您阅读 Data camp 关于这个主题的文章。

在 Metaflow 中,有多个装饰器,在文档的这一节中有很好的解释。然而,对我来说,最重要的是我将在下一部分解释的那些。

元流实践

我构建了一个简单的流程来说明装饰者和分支的转换。流程的代码在这个库(decorator _ experimental 文件夹);流量看起来是这样的。

并且有一个流程的可视化说明。

该流程的目标是:

  • 开始步骤中测试 Python 和 Pandas 的版本,
  • 测试(再次!?)Python 中的版本和熊猫中的检查 _ 版本步骤
  • 执行一个 3 分支转换,它将给出一个随机数( give_number )、字母( give_letter )或数字/字母( give_something )
  • 一个叫做的连接步骤重述来打印前面步骤的产品,
  • 将要显示的结束步骤(再次!?)Python/Pandas 的版本

对 Python/Pandas 版本的常规检查是为了说明两个特定的装饰器。让我们从脚本的标准执行开始;要执行这个流,您需要在脚本的文件夹中运行以下命令。

这是脚本生成的日志。

我们在日志上可以看到,Python 的版本是 3.6.9,Pandas 是 0.25.3。我们来测试一下 @conda_base decorator。只需要取消一行的注释并执行下面的命令行。

这个装饰者在流上应用了新版本的 Python,在本例中是 3.7.4,带有新版本的 Pandas (0.25.2)。这是管道产生的日志。

正如我所说的,现在有一个新版本的 Python/Pandas 用于执行所有的流。最后,让我们看看 @conda 装饰师。

这一个就像 @conda_base ,但是只针对一个步骤,在这种情况下,我正在将 python 版本修改为 3.6.8,只是为了这个特定的步骤(用熊猫的随机版本,我知道它看起来很蠢,但这只是为了测试)。

在日志中,我们可以看到有一个新版本的 Python/pandas 只应用于 check_version 步骤。

我认为这个测试说明了如何使用 Metaflow 来版本化用于执行流程或步骤的环境。Metaflow 的优势在于为数据科学家提供了灵活性,可以精确地设置执行代码所需的环境,而不必设置 conda 环境或容器。

包中有比这些装饰者更多的东西,比如:

  • 用于执行的,如@重试@超时、@捕捉、@资源
  • AWS 的那个(@batch)我一会儿再来找他们。

我们来看一个用 Metaflow 设计的数据科学/机器学习流程。

用 Metaflow 构建炉石原型预测器

几周前,我建立了一个与暴雪的卡牌游戏炉石相关的数据集。如果你对游戏没有清晰的愿景,我邀请你去看一看。

我在上一篇文章中回避的一个方面是原型的概念。这些原型基于选择的英雄和卡片组中的卡片,有多种原型,有些是最流行的。

在前一篇文章中介绍的数据集中,40%的卡片组没有相关的原型,所以我想开始基于所使用的卡片构建一个原型预测器(这是一个虚拟系统,只是为了测试 Metaflow 的流程)。

下图中有一个我设计的测试 Metaflow 的流程的表示(代码在 this repository 中与炉石相关的文件夹中)。

这个流程的想法是,基于我们想要分配给没有原型的原型的顶卡,建立一个原型的随机森林预测器。我认为代码足够清晰,所以我不会输入太多的执行细节,因为这并不令人兴奋。我将花时间用 Metaflow 的客户端分析多次运行的结果。

监控流程和执行

在流的不同执行过程中产生的数据存储在本地存储的数据存储中(在工作目录的/metaflow 隐藏文件夹中)。尽管如此,所有的结果都可以在一个笔记本中直接访问。我将把不同运行的工件的“处理部分”放在一个要点中。

目标是计算执行时间,收集训练集的第一个样本,以及 HPO 生成的最佳模型的信息(精度和参数)。有处理的截图。

正如我们所看到的,在流程的执行过程中,有许多信息被版本化。我真的很喜欢这种对流水线中产生的所有数据进行版本控制的方法,这种方法在可再现性和调试方面非常出色。

现在让我们看看 Metaflow 的 AWS 部分。

那云呢?

Metaflow 在其文档中为您提供了设置 AWS 环境的所有过程。尽管如此,我还是很懒,他们可以给你一个 AWS 沙箱(使用有限的资源来测试云上的功能),只要在网站上注册就可以了。

几天后,你就可以访问沙箱了(我想再次感谢 Metaflow 的支持,让我可以更长时间地访问他们的沙箱,在我周围做一些演示)。

建立到沙箱的连接很简单,只需要在 Metaflow 的命令行中添加一个令牌。之后,你所有的后台就是:

  • 位于 S3 的数据存储区
  • 元数据存储在类似 RDS 的数据库类型中
  • 在本地机器或 AWS 批处理服务上计算
  • 亚马逊 Sagemaker 中的笔记本

从本地机器访问 AWS 计算有两个选项:

  • 将属性—batch与 run 命令一起使用,就像您的所有流都使用 AWS batch 作为计算资源一样
  • 如果您只想在 AWS 上执行特定的步骤,并使用本地机器的能力来执行其他任务,那么您可以在步骤声明时使用 AWS 装饰器 @batch

我发现这种云管理方法引人注目且易于使用,本地计算向云计算的转换非常简单。为了说明云计算,我刚刚截屏了运行我的元流代码的实例的 CPU 使用情况,以及我执行的运行类型。

我认为这很好地说明了这样一个事实,即我的本地机器不用于进行计算,而本地运行(在运行 11 和 17 的边界之间。

现在关于 Metaflow 的最后一个问题是它能否与 mlflow 一起工作。

不要越过水流!?

不,请这样做,我在中添加了另一个脚本的 mlflow 图层到我的 HPO 中。我只是在我的 mlflow 日志中添加与我的元流运行相关的信息。有一张 mlflow 的日志截图。

这两种版本控制框架似乎可以很好地协同工作。因此,今天,我们可以使用 Metaflow 监控您的管道,记录您的模型,并在任何云平台支持上使用 mlflow 进行部署。

反馈

Metaflow 是一个为数据科学家开发的框架,它提供:

  • 机器学习 DS 管道中产生的所有工件的版本控制
  • 轻松使用云,轻松并行化作业

这是网飞做的一项伟大的工作,并且是开源的。更多的元素出现在元流中,如:

  • R 包
  • 将 AWS 步骤用作调度程序的能力(但它还没有出现,所以我认为这表明它不是一项容易使用的技术)。
  • Sagemaker 的模型部署,他们将涵盖 mlflow 的另一个方面(在 AWS 上)。

我在 Metaflow 上的唯一缺点是:

  • conda decorator 在您的 python 环境中构建了大量的 conda 环境,因此它看起来可能很乱
  • 该框架看起来非常适合 AWS,因此不对其他云平台开放(但在 GitHub 上,似乎有人试图让它为 GCP 工作)
  • 火花似乎完全不在计划之内

我将跟随 Metaflow 的发展,但老实说,第一次尝试是好的,我邀请你尝试一下,并提出你自己的看法。

原载于

持怀疑态度!作为数据分析师最重要的原则

原文:https://towardsdatascience.com/be-skeptical-the-most-important-principle-as-a-data-analyst-903172222c65?source=collection_archive---------24-----------------------

至于方法,可能有一百万,但原则很少。持怀疑态度但不要陷入分析麻痹。

图片由openclipbart-Vectors在 Pixabay 上生成

怀疑论(英国:怀疑论)基于牛津词典:持怀疑态度;对某事真实性的怀疑。

使用第一原则思维,我了解到塑造我成为一个更好的分析师的最重要的原则是“保持怀疑!”原则指导我做分析,分析方法也随之而来。持怀疑态度但不要陷入分析麻痹。

概述

1。找到第一原则
2。持怀疑态度!
3。不要陷入
分析麻痹

1.找到首要原则

“至于方法,可能有一百万甚至更多,但原则很少。掌握原则的人能够成功地选择自己的方法。尝试方法的人,忽视原则,肯定会有麻烦。”—哈林顿·埃默森

当我们学习任何东西时,找到它背后的原理是很重要的。您可以将原则视为一个通用的规则、定义或值,它可以应用于许多不同的特定场景。第一个原则仅仅是不能从其他原则推导出来的基本原则。通过从我们所学的东西中找到首要原则,我们可以用它来产生新的想法或方法[1]。

让我们举一个第一原理思维的例子。大多数数据分析师和数据科学家都学习过编程,要么使用 Python,要么使用 r。编程的首要原则是什么?如果你停下来猜一猜,会更有趣。

第一个原则:寻找

我们什么时候使用循环?通常,当我们实现一个需要连续重复代码块的算法时,我们使用循环,重复一个接一个地连续发生。函数怎么样?当我们发现一块重复的代码时,就会触发我们使用函数。我们可以通过将同一块代码封装在一个函数中来重用它,然后我们可以在任何地方调用这个函数。

如果我们发现使用循环和函数的一般规则,它们有交集:减少重复编写相同的代码块。这就是我们如何通过归纳找到第一个原则。不要重复自己(干)是编程和软件工程中最流行的原则之一[4]。

原则背后也有原因。如果我们的重复次数少于三次,我们仍然可以复制粘贴代码。但是,更重要的是,我们会厌倦复制粘贴。代码也变得很难维护。如果我们发现一个 bug,我们需要修复每个代码副本中的逻辑。我们可能会不小心错过修复其中一个副本。

第一原则:推理

在知道“不要重复自己”的原则后,有些人发现如何在其他方面应用该原则。我们可以将此视为推理部分。一些例子是:

  1. 库超越了单一的代码库,库可以防止其他程序员重复实现与你功能相同的代码。
  2. 继承,面向对象编程
    我们不需要重复编写条件语句。之前,我们需要为每个相似的类if (duck) then quack(); else if (cat) then meow(); else if ... 编写 if 语句。有了继承能力,我们就说DuckCat继承Animal,所有动物都会说话。我们可以实例化任何种类的动物,例如animal = Duck(),并调用animal.talk()
  3. 泛型,面向对象编程(OOP)
    我们不需要仅仅因为一个类需要处理不同的数据类型而重复编写它。没有实现ListOfStringListOfInteger,有了泛型,我们只实现List<T>

2. 持怀疑态度!

先说个例子。下图来自 UCI 资料库的成人数据集。该数据集有一个特征,表明一个成年人的收入是否超过 5 万美元。我汇总数据,按照教育程度和性别得出收入超过 5 万美元的成年人比例。你从数据中得到了什么信息?你能根据这些信息得出结论吗?慢慢想吧。

来自 UCI 的成人数据集,由 Barry Becker 从 1994 年人口普查数据库中提取。

从图表中,我们得到信息,女性往往比男性收入低,尽管两者教育程度相同。男女有工资歧视,不是吗?

如果你因为本科或硕士学历的男性收入更高而利用这些信息进行针对性营销,那就没问题。但是,如果你正在利用这些信息进行大规模的性别平等社会运动,最好三思而行!或者,你可能会愚弄整个世界。我们应该持怀疑态度,质疑数据和分析方法:

  1. 数据来自 1994 年,调查是在美国进行的。在 2020 年的中国,用这些数据来进行社会运动还合适吗?
  2. 女性倾向于选择不太累的工作还是兼职工作,因为她想照顾她的孩子?
  3. 他们是如何对成年人进行采样的?他们也从家庭主妇那里收集数据吗?如果他们从家庭主妇那里收集数据,这可能会导致收入差异。
  4. 假设男性和女性拥有相同的学位,他们在公司的表现是否一样好?

怀疑是数据分析首先存在的原因。对于不持怀疑态度的人来说,专家的知识和直觉就足够了,不是吗?但是,具有讽刺意味的是,有时,我们,作为分析师,不够怀疑。我们基于对数据的错误假设给出结论,使用的是不适合数据的复杂分析方法。我们毫无疑问地、满怀信心地将它呈现给利益相关者,每个人都相信它。

不管手头的任务是什么,最重要的是保持怀疑的态度。我们需要质疑围绕数据和分析方法的假设。我们越质疑,就越了解真相。然后,我们将能够决定哪些分析方法最适合我们的数据。

质疑数据

“我们不应该只问‘数据说明了什么?’但是要问,‘谁收集的,他们是怎么做的,那些决定是如何影响结果的?’”—琼斯·罗伊

图片来自最佳大学评论

上面的信息图是关于高中和大学作弊的。从调查中,他们得到的信息是,51%的学生承认在过去一学年的一次考试中作弊。如果我们要根据有多少学生作弊来做决定,你会直接用这些信息吗?

我们要持怀疑态度,要问“是谁收的?”以及“他们是如何收集的?”因为这两个方面决定了调查结果。想象一下,我们用两种不同的方式做这个调查:

  1. 第一次调查(老师,采访)
    学校通过采访的方式指派每个班主任进行调查。在一个私人房间里,老师问“你在过去的学年里有没有在考试中作弊?”以及“你是怎么作弊的?”老师向学生承诺,本次调查是匿名的,他们的回答不会影响他们的分数。
  2. 第二次调查(学生,书面调查)学校要求学生会进行调查。每个班级都有一名代表通过纸张分发调查问卷。有一个是/否问题问“你在过去的学年里有没有在考试中作弊?”学生只需要在答案上打勾,然后把答案放进盒子里。

您想使用第一次调查的结果还是第二次调查的结果?我们大多数人会选择第二种调查。如果老师通过面试问那种问题,你觉得学生会说实话吗?至少有些学生会撒谎,不敢说实话。结果将偏向于更少的作弊者。

我们必须记住,我们的数据并不完美。它可能包含由人为错误、偏见或测量工具引起的误差。但是,NYU 数据科学教授 Jones-Rooy 说,“虽然数据可能包含错误,但这并不意味着我们应该扔掉所有数据,没有什么是可知的。这意味着以深思熟虑的方式收集数据,扪心自问我们可能遗漏了什么,并欢迎收集更多的数据。”[3]

质疑分析

“数据并没有什么。人类说事情。他们说他们在数据中注意到或寻找的东西”——琼斯-罗伊

分析师必须持怀疑态度,质疑自己的分析方法和结果。我们在阅读别人的分析结果时也需要持怀疑态度。这些是 Kaushik 的一些例子[2]:

  1. 这个结论是基于你所掌握的数据吗?
  2. 做这个分析的时候做了什么假设?
  3. 索赔的理由是什么?
  4. 从数据或分析中可以得出任何替代的解释或结论吗?
  5. 如果数据以比例给出,原始值是多少?
  6. 如果数据以原始值给出,比例是多少?

还有很多其他的。问题是无限的,这取决于分析方法。保持怀疑的态度,问题就会涌入你的脑海。

3.不要陷入分析瘫痪

通过持怀疑态度,我们会质疑很多事情。我们不会轻易相信一个假设,我们希望“越来越深入!”。几个星期后,我们意识到我们最终分析了很多东西,但没有得到任何结论。人们称这种分析为麻痹。分析瘫痪是一种过度分析或过度思考的状态,导致分析师无法得出结果[5]。

图片来自“盗梦空间网络版本的简单指南

那么,我们是否需要停止怀疑,以防止陷入分析瘫痪?不要!不要那样做。想好之前不要盲目相信任何假设。你会陷入另一个极端的对立面,因本能而灭绝:分析师做出致命决定的情况,因为它只是基于本能[5]。

最后,正如斯图尔特·戈尔德所说,“明智的错误总比什么都不做好。”[2]会有很多我们持怀疑态度的假设。我们会有深入探究每一个问题的冲动。但是,我们应该学会如何优先考虑和关注那些可能使整个分析大错特错的关键假设。

例如,你要决定是否在另一个城市开设新的分行。这是 Kaushik 如何解释为什么他持怀疑态度,但仍然做出了决定[2]:

  1. 如果你对数据和分析有 100%的把握,你可以建议在这个城市开几家分店。
  2. 如果你对数据和分析有 80%的把握,你可以建议尝试在这个城市开一家分店。
  3. 如果你对数据和分析有 60%的把握,你可以要求更多的时间去挖掘或增加预算来收集更可靠的数据。

最后,持怀疑态度但不要陷入分析麻痹。

我从“ 学到了很多第一原理:真正知识的基石 ”。如果你想了解更多关于第一原理思维的知识,我推荐你去读一读。

参考

[1]无名氏、第一原理:真正知识的积木 (2018)、法南街
【2】A .考希克、一个伟大的分析师最好的朋友:怀疑论&智慧! (2016)、Avinash Kaushik 的《奥卡姆剃刀》
【3】a . Jones-Rooy、我是一个对数据持怀疑态度的数据科学家 (2019)、Quartz
【4】k . Henney、每个程序员都应该知道的 97 件事 (2010)、O ' Reilly Safari
【5】维基百科撰稿人、分析麻痹、维基百科:免费百科

豆机和中心极限定理

原文:https://towardsdatascience.com/bean-machine-and-the-central-limit-theorem-8b0b23d6e887?source=collection_archive---------30-----------------------

图片由 Alicja 来自 Pixabay

从二项式分布到正态分布

当我在大学学习统计物理的时候,我被统计学以一种聪明的方式简化和解释混沌过程的能力迷住了。

当我开始研究数据科学时,我发现统计物理学和数据统计学有太多的相似之处。这是未来博客的主题。现在让我们深入研究一下统计分布。

统计分布:

统计学中的一个基本概念是概率分布。在概率分布中,我们描述了获得随机变量可能取值的可能性。我们可以画出离散变量和连续变量的概率分布。

二项式分布:

二项式分布是一种离散的概率分布。它可以简单地认为是重复多次的实验中成功(1)或失败(0)结果的概率。例如,掷硬币只有两种可能的结果:正面或反面

二项式分布,作者使用 Python 制作的图片

正态(高斯)分布:

正态分布是一个连续的概率函数,描述了变量的值是如何分布的。因曲线呈钟形,故又称为“钟形曲线”。在正态分布中,分布两端的极值同样不太可能出现。

照片由迈克从派克斯拍摄

从量子物理到生物统计学,从股票市场回报到质量控制,进入系统的电话,人口的身高、体重、智商,容器中气体分子的速度,学生的考试成绩,都可以观察到正态分布。

正态分布,作者使用 Python 制作的图像

中心极限定理;

统计学中的中心极限定理指出,给定足够大的样本量,样本均值的抽样分布接近正态分布——无论总体分布的形状如何

德莫维尔-拉普拉斯定理;

德莫维尔-拉普拉斯定理是中心极限定理的特例。它指出,在样本量足够大的情况下,二项分布近似于正态分布。

掷硬币:

让我们用一个掷硬币的例子来澄清这一点:当我们掷硬币时,我们有两种可能的选择:正面和反面。抛硬币选择正面的概率是 1/2。(1/2).当我们投掷许多硬币时,事情开始变得复杂,但是所有的概率都回到了期望结果/所有可能结果的概念上

Joshua Hoehne 在 Unsplash 上拍摄的照片

我们可以通过思想实验或者虚拟实验来理解最复杂的概率概念。你可以尝试一些虚拟硬币翻转实验这里

如何看待真实的概率实验将抽象的统计概念和真实世界的例子联系起来?怎样才能做一个真正的概率实验?我们要掷硬币数百万次吗?为了找到真实的概率,我们真的需要多次做同样的实验。(不是几百或几千,是几百万)。

因为计算机不是在 19 世纪发明的,统计学家开发了创造性的设备来更快地进行统计实验。

弗朗西斯·高尔顿爵士

弗朗西斯·高尔顿爵士由查理斯·威灵顿·弗斯所著,公有领域

弗朗西斯·高尔顿爵士是英国统计学家,他创立了相关性、回归均值、数据收集调查和词汇假设等概念。

高尔顿董事会:

我想向你介绍弗朗西斯·高尔顿爵士开发的最著名的统计设备之一:高尔顿板,Hextat 概率演示器,豆子机,概率机,或五点形。这些是一个智能设备的名字,提供给我们在几秒钟内做几千次硬币翻转等效实验。

这是中心极限定理的一个极好的直观例子。小球通过分支路径随机下落,最终总是呈正态分布。从细节上看,随机性是混乱的,但总是遵循一种普遍的秩序。

高尔顿板由一个垂直板和交错排列的钉子组成。珠子从顶部落下,当设备处于水平状态时,当它们碰到钉子时会向左或向右反弹。

一个高尔顿盒显示正态分布,马特马特卡 IME-USP / 罗德里戈铁雄阿根顿

为什么高尔顿板类似于抛硬币?因为在两个实验中,概率是相等的。在高尔顿棋盘上,像掷硬币一样,球通过几排钉子选择向左或向右的路径。

高尔顿板实验

结论:

高尔顿板是证明中心极限定理的二项式分布的极好演示;当你添加独立的随机变量时,它们的和趋向于正态分布。特别地,它证明了中心极限定理的一个特例——德莫维尔-拉普拉斯定理。

非常感谢您对 seymatas@gmail.com 的任何建议!

用机器学习找到值得买的股票

原文:https://towardsdatascience.com/beat-the-stock-market-with-machine-learning-d9432ea5241e?source=collection_archive---------5-----------------------

有没有可能让一个机器学习模型学习表现良好和表现不佳的股票之间的差异,然后利用这些知识来预测哪只股票值得购买?此外,仅仅通过查看 10-K 文件中的财务指标就能做到这一点吗?

懒惰策略

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

算法交易领域充斥着新的策略。企业已经在基础设施和 R&D 上投入了数十亿美元(并且还在继续投资),以便在竞争中脱颖而出,战胜市场。尽管如此,众所周知,买入&持有策略能够胜过许多算法策略,尤其是在长期。然而,发现股票价值是一门很少有人掌握的艺术,一个算法能被训练成这样吗?

本文包含了为大量股票建立金融数据数据集并使用不同的机器学习模型进行分析所需的所有步骤。你会在整篇文章中看到,这种操作方式并没有利用历史股票价格数据,而是利用了每个上市公司每年发布的 10-K 文件中的财务指标。特别是,就本文而言,我们将使用 2018 年的财务数据,以便对 2019 年期间(指从 2019 年 1 月的第一个交易日到 2019 年 12 月的最后一个交易日)的股票表现进行一些虚构的预测。

在开始写代码之前,必须清楚的是这篇文章并没有给出一个你可以使用的实际交易策略:

  1. 我不是理财顾问,你也绝对不应该从网上获取理财建议。
  2. 你不能实现它来预测股票市场,因为你缺乏在训练阶段设置标签所需的未来信息。

本文想要探索的是,通过训练并向最大似然算法提供财务报表中报告的数字,让它们识别价值增长的股票的可能性。为了检查这是否属实,测试阶段由 ML 算法做出的预测(可被视为虚构交易)将与标准普尔 500 指数和道琼斯指数进行比较。

最后,我们不会在一年内多次买卖股票:我们将使用一种懒惰策略,在年初(这里是 2019 年)买入股票,然后在年底卖出,希望能够盈利。

说到这里,让我们直接进入有趣的部分。

第 1 部分:构建数据集

1.1 初步进口

如果你熟悉 Python 中的机器学习,你应该已经知道我们将要使用的所有包和库。如果您是这个领域的新手,不要害怕,您可以找到每个包和库的大量信息和教程。所有使用的包都很容易检索,并且可以根据您的 Python 设置用pipconda安装(这里使用了Python 3.7.5)。

为了从网上抓取数据,需要互联网连接(我们将使用优秀的免费 APIhttps://financialmodelingprep.com/developer/docs/和众所周知的pandas_datareader)。

**from** **sys** **import** stdout
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**from** **pandas_datareader** **import** data
**import** **json**

*# Reading data from external sources*
**import** **urllib** **as** **u**
**from** **urllib.request** **import** urlopen

*# Machine learning (preprocessing, models, evaluation)*
**from** **sklearn.model_selection** **import** train_test_split
**from** **sklearn.preprocessing** **import** StandardScaler
**from** **sklearn.model_selection** **import** GridSearchCV
**from** **sklearn.svm** **import** SVC
**from** **sklearn.ensemble** **import** RandomForestClassifier
**from** **sklearn.neural_network** **import** MLPClassifier
**import** **xgboost** **as** **xgb**
**from** **sklearn.metrics** **import** classification_report

*# Graphics*
**from** **tqdm** **import** tqdm

为了简化代码,我们还需要一些助手函数:

  1. get_json_data:用于抓取 financialmodelingprep API 的链接,拉取财务数据。
  2. get_price_var:用于计算 2019 年期间的价格变化,利用pandas_datareader和雅虎财经。
  3. find_in_json:用来扫描一个复杂的 json 文件,寻找一个键并返回它的值。
**def** get_json_data(url):
    *'''*
 *Scrape data (which must be json format) from given url*
 *Input: url to financialmodelingprep API*
 *Output: json file*
 *'''*
    response = urlopen(url)
    dat = response.read().decode('utf-8')
    **return** json.loads(dat)

**def** get_price_var(symbol):
    *'''*
 *Get historical price data for a given symbol leveraging the power of pandas_datareader and Yahoo.*
 *Compute the difference between first and last available time-steps in terms of Adjusted Close price..*
 *Input: ticker symbol*
 *Output: price variation* 
 *'''*
    *# read data*
    prices = data.DataReader(symbol, 'yahoo', '2019-01-01', '2019-12-31')['Adj Close']

    *# get all timestamps for specific lookups*
    today = prices.index[-1]
    start = prices.index[0]

    *# calculate percentage price variation*
    price_var = ((prices[today] - prices[start]) / prices[start]) * 100
    **return** price_var

**def** find_in_json(obj, key):
    *'''*
 *Scan the json file to find the value of the required key.*
 *Input: json file*
 *required key*
 *Output: value corresponding to the required key*
 *'''*
    *# Initialize output as empty*
    arr = []

    **def** extract(obj, arr, key):
        *'''*
 *Recursively search for values of key in json file.*
 *'''*
        **if** isinstance(obj, dict):
            **for** k, v **in** obj.items():
                **if** isinstance(v, (dict, list)):
                    extract(v, arr, key)
                **elif** k == key:
                    arr.append(v)
        **elif** isinstance(obj, list):
            **for** item **in** obj:
                extract(item, arr, key)
        **return** arr

    results = extract(obj, arr, key)
    **return** results

1.2 股票清单

首先,我们需要获得将用于构建数据集的股票列表。由于有数以千计的股票的信息可以在网上搜集,我决定简单地在金融建模准备 API 上获取所有股票的列表。

这份名单包含了总共超过 7k 只股票,显然涵盖了不止一个行业。事实上,每个公司都属于自己的领域(科技、医疗、能源……),而这些领域又可能具有某些季节性、宏观经济趋势等特征。到目前为止,我决定专注于技术板块:这意味着从完整的可用股票列表available_tickers中,我只保留那些板块等于Technology的股票。多亏了pandas库的强大功能,这个操作非常简单。

因此,列表tickers_tech将包含金融建模准备 API 上属于技术部门的所有可用股票。

url = 'https://financialmodelingprep.com/api/v3/company/stock/list'
ticks_json = get_json_data(url)
available_tickers = find_in_json(ticks_json, 'symbol')

tickers_sector = []
**for** tick **in** tqdm(available_tickers):
    url = 'https://financialmodelingprep.com/api/v3/company/profile/' + tick *# get sector from here*
    a = get_json_data(url)
    tickers_sector.append(find_in_json(a, 'sector'))

S = pd.DataFrame(tickers_sector, index=available_tickers, columns=['Sector'])

*# Get list of tickers from TECHNOLOGY sector*
tickers_tech = S[S['Sector'] == 'Technology'].index.values.tolist()

1.3 了解 2019 年全年的价格变化

2019 年期间tickers_tech中列出的每只股票的价格变化将被用作区分值得购买和不值得购买的股票的指标(因为它们降低了它们的价值,出于我们并不真正关心的原因)。因此,我们需要:

  • 提取每只股票的所有每日调整收盘价,计算差价(这要感谢助手函数get_price_var
  • 如果没有找到数据,跳过股票
  • 限制要扫描的股票数量为 1000(出于时间原因。当我们提取财务数据时,所需的时间与股票数量成正比,因此为了保持合理,我们可以将股票数量限制在一个阈值内。但是,您可以放弃此检查,让计算机在夜间工作)。
  • 在数据框架中存储库存和 2019 年相对价格变化D
pvar_list, tickers_found = [], []
num_tickers_desired = 1000
count = 0
tot = 0
TICKERS = tickers_tech

**for** ticker **in** TICKERS:
    tot += 1 
    **try**:
        pvar = get_price_var(ticker)
        pvar_list.append(pvar)
        tickers_found.append(ticker)
        count += 1
    **except**:
        **pass**

    stdout.write(f'**\r**Scanned **{tot}** tickers. Found **{count}**/{len(TICKERS)} usable tickers (max tickets = **{num_tickers_desired}**).')
    stdout.flush()

    **if** count == num_tickers_desired: *# if there are more than 1000 tickers in sectors, stop*
        **break**

*# Store everything in a dataframe*
D = pd.DataFrame(pvar_list, index=tickers_found, columns=['2019 PRICE VAR [%]'])

对于D中的股票,我们现在需要找到将成为分类模型输入数据的指标值。我们再次利用了 FinancialModelingPrep API。

首先,我们加载indicators.tx文件(可以在存储库中找到)。正如README文件所解释的,过多的财务指标正在被剔除。我决定对来自 FinancialModelingPrep API 的所有可用指标执行一次强力操作,然后我将担心清理和准备模型的数据集。下表汇总了每个类别可用的财务指标数量。

API 中每个类别可用的财务指标数量(https://financialmodelingprep.com)。

总共有 224 个指标可用。但由于有一些重复,所以indicators.txt中指标的实际数量是 221(不算日期)。你可以在这里找到indicators.txt文件:https://github . com/cnic 92/beat-the-stock-market/tree/master/All % 20 tickers % 20 and % 20 indicators

1.4 收集财务指标并构建原始数据集

截至目前,我们已经列出了属于技术板块的股票,并且我们还列出了它们 2019 年的价格变化。是时候收集财务指标了,这些指标将在以后用作分类模型的输入特征。

由于财务建模准备 API,将再次执行抓取。这个过程非常耗时,因为需要反复提取大量数据。

此外,记住以下几点很重要:

  • 需要在特定的时间范围内提取数据。由于目标是根据 2019 年期间的价格变化对股票进行分类,因此财务指标必须属于 2018 年底。
  • 一家公司在同一年提交两份 10-K 文件是有可能的,尽管不常见。在这种情况下,必须只保留最近的条目。
  • 对于给定的股票,API 可能根本不返回任何数据。在这种情况下,原料必须废弃。
  • 并非所有指示器都会返回值。出于这样或那样的原因,有一定比例的指标缺失是合理的。在这种情况下,np.nan将被分配给缺失的条目,我们将在清理阶段处理它们。

最后,我们想要获得的是一个数据帧DATA,其中行对应于已经找到数据的股票(actual_tickers),列对应于财务指标(indicators)。

*# Initialize lists and dataframe (dataframe is a 2D numpy array filled with 0s)*
missing_tickers, missing_index = [], []
d = np.zeros((len(tickers_found), len(indicators)))

**for** t, _ **in** enumerate(tqdm(tickers_found)):
    *# Scrape indicators from financialmodelingprep API*
    url0 = 'https://financialmodelingprep.com/api/v3/financials/income-statement/' + tickers_found[t]
    url1 = 'https://financialmodelingprep.com/api/v3/financials/balance-sheet-statement/' + tickers_found[t]
    url2 = 'https://financialmodelingprep.com/api/v3/financials/cash-flow-statement/' + tickers_found[t]
    url3 = 'https://financialmodelingprep.com/api/v3/financial-ratios/' + tickers_found[t]
    url4 = 'https://financialmodelingprep.com/api/v3/company-key-metrics/' + tickers_found[t]
    url5 = 'https://financialmodelingprep.com/api/v3/financial-statement-growth/' + tickers_found[t]
    a0 = get_json_data(url0)
    a1 = get_json_data(url1)
    a2 = get_json_data(url2)
    a3 = get_json_data(url3)
    a4 = get_json_data(url4)
    a5 = get_json_data(url5)

    *# Combine all json files in a list, so that it can be scanned quickly*
    A = [a0, a1, a2 , a3, a4, a5]
    all_dates = find_in_json(A, 'date')

    check = [s **for** s **in** all_dates **if** '2018' **in** s] *# find all 2018 entries in dates*
    **if** len(check) > 0:
        date_index = all_dates.index(check[0]) *# get most recent 2018 entries, if more are present*

        **for** i, _ **in** enumerate(indicators):
            ind_list = find_in_json(A, indicators[i])
            **try**:
                d[t][i] = ind_list[date_index]
            **except**:
                d[t][i] = np.nan *# in case there is no value inserted for the given indicator*

    **else**:
        missing_tickers.append(tickers_found[t])
        missing_index.append(t)

actual_tickers = [x **for** x **in** tickers_found **if** x **not** **in** missing_tickers]
d = np.delete(d, missing_index, 0)*#raw dataset* DATA = pd.DataFrame(d, index=actual_tickers, columns=indicators)

1.5 数据集清理和准备

数据集的准备在某种程度上是一门艺术。我将我的行动限制在应用常见的实践,例如:

  • 删除具有大量nan值的列。
  • 删除具有大量0值的列。
  • 用该列的平均值填充剩余的nan值。

例如,在这种特定情况下,每列平均有 84 个 0 值和 140 的标准偏差。所以我决定从 dataframe 中删除所有那些出现的 0 值大于 20 的列(20 大约是数据集总行数的 3.1%)。

同时,每列平均约有 37 个nan条目,标准差约为 86。所以我决定从数据帧中删除所有那些出现次数大于 15 的列(15 大约是数据集总行数的 2.4%)。然后,剩余的nan条目已经用该列的平均值填充。

在清洗过程结束时,DATA的列数从 221 列减少到 108 列,减少了 50%。虽然由于缺乏数据,一些被丢弃的指标毫无用处,但有用的数据也有可能在这一过程中丢失。但是,必须考虑到我们需要数据集中所有股票的有用数据,所以我认为丢弃那些可能只与数据集一小部分相关的指标(列)是可以接受的。

最后,需要对每个样本进行分类。对于每只股票,已经计算了 2019 年 1 月第一个交易日和 2019 年 12 月最后一个交易日之间的交易价格差异(数据集D)。如果这个差值为正,那么该股票将属于类别1,这是一个买入信号。相反,如果价格差异为负,该股票将被归类为0,这是一个忽略信号(不要买入)。下表提供了一个快速回顾。

为股票指定二元分类的标准。

因此,10值的数组将作为数据帧DATA的最后一列被追加。

*# Remove columns that have more than 20 0-values*
DATA = DATA.loc[:, DATA.isin([0]).sum() <= 20]

*# Remove columns that have more than 15 nan-values*
DATA = DATA.loc[:, DATA.isna().sum() <= 15]

*# Fill remaining nan-values with column mean value*
DATA = DATA.apply(**lambda** x: x.fillna(x.mean())) 

*# Get price variation data only for tickers to be used*
D2 = D.loc[DATA.index.values, :]

*# Generate classification array*
y = []
**for** i, _ **in** enumerate(D2.index.values):
    **if** D2.values[i] >= 0:
        y.append(1)
    **else**: 
        y.append(0)

*# Add array to dataframe*
DATA['class'] = y

本文的第一部分到此结束。我们建立了一个数据集,其中包含 2018 年的相关金融指标和来自 2019 年股票价格走势的二元类。在第 2 节中,我们将重点介绍一些机器学习算法的实现,以便对股票进行预测,并努力战胜市场!

第 2 部分:通过机器学习算法进行虚拟预测

2.1 准备数据集

在用不同的机器学习算法进行有趣的实验之前,我们必须对数据集进行最后的润色,包括:

  1. 在训练和测试数据集中拆分数据集;
  2. 标准化数据集,使每个指标的均值为 0,标准差等于 1。

因此,关于将它分成训练和测试,在DATA中 80%的可用数据将用于训练算法,而剩余的 20%将用于测试 ML 算法。请注意所使用的参数stratify,以便在训练和测试数据集之间保持相同的类比率。从train_splittest_split中,我们提取输入数据X_trainX_test和输出目标数据y_trainy_test。之后会执行健全性检查。

*# Divide data in train and testing*
train_split, test_split = train_test_split(df, test_size=0.2, random_state=1, stratify=df['class'])
X_train = train_split.iloc[:, :-1].values
y_train = train_split.iloc[:, -1].values
X_test = test_split.iloc[:, :-1].values
y_test = test_split.iloc[:, -1].values

print()
print(f'Number of training samples: **{X_train.shape[0]}**')
print()
print(f'Number of testing samples: **{X_test.shape[0]}**')
print()
print(f'Number of features: **{X_train.shape[1]}**')

结果是:

Number of training samples: 510

Number of testing samples: 128

Number of features: 107

关于数据的标准化,我们利用从scikit-learn获得的StandardScaler()在标准化训练和测试数据时使用相同的系数是很重要的:为此,我们首先将定标器应用于X_train,然后通过方法.transform()将其应用于X_trainX_test

*# Standardize input data*
scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

2.2 支持向量机

我们将运行的第一个分类算法是支持向量机。执行GridSeachCV是为了调整一些超参数(kernelgammaC)。所需的交叉验证次数设置为 5。我们希望实现最大的加权精度,以便最小化假阳性的数量。

*# Parameter grid to be tuned*
tuned_parameters = [{'kernel': ['rbf', 'linear'],
                     'gamma': [1e-3, 1e-4],
                     'C': [0.01, 0.1, 1, 10, 100]}]

clf1 = GridSearchCV(SVC(random_state=1),
                    tuned_parameters,
                    n_jobs=6,
                    scoring='precision_weighted',
                    cv=5)
clf1.fit(X_train, y_train)

print('Best score and parameters found on development set:')
print()
print('**%0.3f** for **%r**' % (clf1.best_score_, clf1.best_params_))
print()

成绩还不算太差。我们可以看到,如下图所示,我们的加权精度为 71.3%。如果您仔细阅读,您可能会注意到评分参数被设置为等于 metric precision_weighted 。这样做是为了优化算法的精度(不要与精度混淆!)和加权,因为我们没有两类(值得购买的股票和不值得购买的股票)相同数量的样本。关于这个和其他评分参数的更多信息,你可以查看这里的文档https://scikit learn . org/stable/modules/model _ evaluation . html。

Best score and parameters found on development set: 0.713 for {‘C’: 0.01, ‘gamma’: 0.001, ‘kernel’: ‘linear’}

2.3 随机森林

我们将运行的第二个分类算法是随机森林。执行GridSeachCV是为了调整一些超参数(n_estimatorsmax_featuresmax_depthcriterion)。所需的交叉验证次数设置为 5。我们希望实现最大的加权精度,以便最小化假阳性的数量。

*# Parameter grid to be tuned*
tuned_parameters = {'n_estimators': [32, 256, 512, 1024],
                    'max_features': ['auto', 'sqrt'],
                    'max_depth': [4, 5, 6, 7, 8],
                    'criterion': ['gini', 'entropy']}clf2 = GridSearchCV(RandomForestClassifier(random_state=1),
                    tuned_parameters,
                    n_jobs=6,
                    scoring='precision_weighted',
                    cv=5)
clf2.fit(X_train, y_train)print('Best score and parameters found on development set:')
print()
print('**%0.3f** for **%r**' % (clf2.best_score_, clf2.best_params_))
print()

我们可以看到,如下所示,该算法比支持向量机高出几个百分点,因为我们的加权精度为 72.4%。

Best score and parameters found on development set:  0.724 for {'criterion': 'gini', 'max_depth': 5, 'max_features': 'auto', 'n_estimators': 32}

2.4 极限梯度提升

我们将运行的第三个分类算法是极端梯度提升。执行GridSeachCV是为了调整一些超参数(learning_ratemax_depthn_estimators)。所需的交叉验证次数设置为 5。我们希望实现最大的加权精度,以便最小化假阳性的数量。

*# Parameter grid to be tuned*
tuned_parameters = {'learning_rate': [0.01, 0.001],
                    'max_depth': [4, 5, 6, 7, 8],
                    'n_estimators': [32, 128, 256]}clf3 = GridSearchCV(xgb.XGBClassifier(random_state=1),
                   tuned_parameters,
                   n_jobs=6,
                   scoring='precision_weighted', 
                   cv=5)
clf3.fit(X_train, y_train)print('Best score and parameters found on development set:')
print()
print('**%0.3f** for **%r**' % (clf3.best_score_, clf3.best_params_))
print()

该算法比支持向量机和随机森林分类器低几个百分点,因为我们的加权精度为 69.7%。

Best score and parameters found on development set:  0.697 for {'learning_rate': 0.001, 'max_depth': 4, 'n_estimators': 256}

2.5 多层感知器

我们将运行的第四个分类算法是多层感知器(前馈神经网络)。执行GridSeachCV是为了调整一些超参数(hidden_layer_sizesactivationsolver)。所需的交叉验证次数设置为 5。我们希望获得最大的加权精度,以便最小化假阳性的数量。

*# Parameter grid to be tuned*
tuned_parameters = {'hidden_layer_sizes': [(32,), (64,), (32, 64, 32)],
                    'activation': ['tanh', 'relu'],
                    'solver': ['lbfgs', 'adam']}clf4 = GridSearchCV(MLPClassifier(random_state=1, batch_size=4, early_stopping=**True**), 
                    tuned_parameters,
                    n_jobs=6,
                    scoring='precision_weighted',
                    cv=5)
clf4.fit(X_train, y_train)print('Best score, and parameters, found on development set:')
print()
print('**%0.3f** for **%r**' % (clf4.best_score_, clf4.best_params_))
print()

这个算法是最好的,因为它优于所有以前测试过的算法。MLP 的加权精度为 73%。

Best score, and parameters, found on development set:  0.730 for {'activation': 'relu', 'hidden_layer_sizes': (32, 64, 32), 'solver': 'adam'}

2.6 评估模型

既然已经训练了 4 种分类算法,我们必须对它们进行测试,并比较它们之间的性能,以及它们与该领域基准(标准普尔 500、道琼斯)的性能。事实上,我们并不局限于比较它们的测试精度:我们想了解哪种算法能带来最好的投资回报(ROI) 。要做到这一点,我们必须首先获得包含在pvar中的 2019 年价格变化,这些股票只属于测试数据集(我们还没有使用它!).

*# Get 2019 price variations ONLY for the stocks in testing split*
pvar_test = pvar.loc[test_split.index.values, :]

现在,我们构建一个新的数据框架df1,其中,对于每只测试的股票,我们从每个模型中收集所有的预测类(需要提醒的是,这两个类是0 =IGNORE,1 =BUY)。

如果模型预测了类别1,我们继续购买价值 100 美元的股票;否则,我们忽略股票。

*# Initial investment can be $100 for each stock whose predicted class = 1*
buy_amount = 100*# In new dataframe df1, store all the information regarding each model's predicted class and relative gain/loss in $USD*
df1 = pd.DataFrame(y_test, index=test_split.index.values, columns=['ACTUAL']) *# first column is the true class (BUY/INGORE)*df1['SVM'] = clf1.predict(X_test) *# predict class for testing dataset*
df1['VALUE START SVM [$]'] = df1['SVM'] * buy_amount *# if class = 1 --> buy $100 of that stock*
df1['VAR SVM [$]'] = (pvar_test['2019 PRICE VAR [%]'].values / 100) * df1['VALUE START SVM [$]'] *# compute price variation in $*
df1['VALUE END SVM [$]'] = df1['VALUE START SVM [$]'] + df1['VAR SVM [$]'] *# compute final value*df1['RF'] = clf2.predict(X_test)
df1['VALUE START RF [$]'] = df1['RF'] * buy_amount
df1['VAR RF [$]'] = (pvar_test['2019 PRICE VAR [%]'].values / 100) * df1['VALUE START RF [$]']
df1['VALUE END RF [$]'] = df1['VALUE START RF [$]'] + df1['VAR RF [$]']df1['XGB'] = clf3.predict(X_test)
df1['VALUE START XGB [$]'] = df1['XGB'] * buy_amount
df1['VAR XGB [$]'] = (pvar_test['2019 PRICE VAR [%]'].values / 100) * df1['VALUE START XGB [$]']
df1['VALUE END XGB [$]'] = df1['VALUE START XGB [$]'] + df1['VAR XGB [$]']df1['MLP'] = clf4.predict(X_test)
df1['VALUE START MLP [$]'] = df1['MLP'] * buy_amount
df1['VAR MLP [$]'] = (pvar_test['2019 PRICE VAR [%]'].values / 100) * df1['VALUE START MLP [$]']
df1['VALUE END MLP [$]'] = df1['VALUE START MLP [$]'] + df1['VAR MLP [$]']

最后,我们构建了一个紧凑的数据框架MODELS_COMPARISON,在其中我们收集了在分类模型和基准(S & P 500,DOW JONES)之间进行比较所需的主要信息。

利用数据框架df1,我们可以轻松计算每个模型的收益和损失(net_gain_percent_gain_)。

由于我们错过了基准测试的数据,我们很快利用自定义函数get_price_var来获得 2019 年标准普尔 500 (GSPC)和道琼斯(DJI)的价格变化百分比。

*# Create a new, compact, dataframe in order to show gain/loss for each model*
start_value_svm = df1['VALUE START SVM [$]'].sum()
final_value_svm = df1['VALUE END SVM [$]'].sum()
net_gain_svm = final_value_svm - start_value_svm
percent_gain_svm = (net_gain_svm / start_value_svm) * 100start_value_rf = df1['VALUE START RF [$]'].sum()
final_value_rf = df1['VALUE END RF [$]'].sum()
net_gain_rf = final_value_rf - start_value_rf
percent_gain_rf = (net_gain_rf / start_value_rf) * 100start_value_xgb = df1['VALUE START XGB [$]'].sum()
final_value_xgb = df1['VALUE END XGB [$]'].sum()
net_gain_xgb = final_value_xgb - start_value_xgb
percent_gain_xgb = (net_gain_xgb / start_value_xgb) * 100start_value_mlp = df1['VALUE START MLP [$]'].sum()
final_value_mlp = df1['VALUE END MLP [$]'].sum()
net_gain_mlp = final_value_mlp - start_value_mlp
percent_gain_mlp = (net_gain_mlp / start_value_mlp) * 100percent_gain_sp500 = get_price_var('^GSPC') *# get percent gain of S&P500 index*
percent_gain_dj = get_price_var('^DJI') *# get percent gain of DOW JONES index*MODELS_COMPARISON = pd.DataFrame([start_value_svm, final_value_svm, net_gain_svm, percent_gain_svm],
                    index=['INITIAL COST [USD]', 'FINAL VALUE [USD]', '[USD] GAIN/LOSS', 'ROI'], columns=['SVM'])
MODELS_COMPARISON['RF'] = [start_value_rf, final_value_rf, net_gain_rf, percent_gain_rf]
MODELS_COMPARISON['XGB'] = [start_value_xgb, final_value_xgb, net_gain_xgb, percent_gain_xgb]
MODELS_COMPARISON['MLP'] = [start_value_mlp, final_value_mlp, net_gain_mlp, percent_gain_mlp]
MODELS_COMPARISON['S&P 500'] = ['', '', '', percent_gain_sp500]
MODELS_COMPARISON['DOW JONES'] = ['', '', '', percent_gain_dj]

MODELS_COMPARISON 数据集总结了结果。

从数据帧MODELS_COMPARISON中,可以看出:

  • XGB 和 RF 是产生最高 ROI 的 ML 模型,分别为 31.3%和 40.9%
  • RF 的表现超过标准普尔 500 12 个百分点,超过道琼斯 20 个百分点
  • XGB 比标准普尔 500 高出几个百分点,而比道琼斯高出近 10 个百分点
  • MLP 和 SVM 的投资回报率非常接近,分别为 28.3%和 27.2%
  • MLP 和 SVM 的表现与标准普尔 500 类似,但都优于道琼斯指数
  • SVM 的净收益最高,约为 3290 美元;但是,它的初始投资成本最高,为 12100 美元
  • 射频导致最低的净收益,约为 1920 美元;但是,它的初始投资成本也最低,为 4700 美元

因此,这个例子证明,至少作为概念证明,在上市公司发布的 10-K 文件中找到有用的信息是可能的。金融信息可以用来训练机器学习模型,学习识别值得购买的股票。

对于所实现的 ML 模型之间的性能的更传统的比较,可以分析classification_report

**from** **sklearn.metrics** **import** classification_report

print()
print(53 * '=')
print(15 * ' ' + 'SUPPORT VECTOR MACHINE')
print(53 * '-')
print(classification_report(y_test, clf1.predict(X_test), target_names=['IGNORE', 'BUY']))
print(53 * '-')
print(53 * '=')
print(20 * ' ' + 'RANDOM FOREST')
print(53 * '-')
print(classification_report(y_test, clf2.predict(X_test), target_names=['IGNORE', 'BUY']))
print(53 * '-')
print(53 * '=')
print(14 * ' ' + 'EXTREME GRADIENT BOOSTING')
print(53 * '-')
print(classification_report(y_test, clf3.predict(X_test), target_names=['IGNORE', 'BUY']))
print(53 * '-')
print(53 * '=')
print(15 * ' ' + 'MULTI-LAYER PERCEPTRON')
print(53 * '-')
print(classification_report(y_test, clf4.predict(X_test), target_names=['IGNORE', 'BUY']))
print(53 * '-')

其屈服于:

=====================================================
               SUPPORT VECTOR MACHINE
-----------------------------------------------------
              precision    recall  f1-score   support

      IGNORE       0.40      0.05      0.09        38
         BUY       0.71      0.97      0.82        90

    accuracy                           0.70       128
   macro avg       0.55      0.51      0.45       128
weighted avg       0.62      0.70      0.60       128

-----------------------------------------------------
=====================================================
                    RANDOM FOREST
-----------------------------------------------------
              precision    recall  f1-score   support

      IGNORE       0.37      0.79      0.50        38
         BUY       0.83      0.43      0.57        90

    accuracy                           0.54       128
   macro avg       0.60      0.61      0.54       128
weighted avg       0.69      0.54      0.55       128

-----------------------------------------------------
=====================================================
              EXTREME GRADIENT BOOSTING
-----------------------------------------------------
              precision    recall  f1-score   support

      IGNORE       0.48      0.34      0.40        38
         BUY       0.75      0.84      0.80        90

    accuracy                           0.70       128
   macro avg       0.62      0.59      0.60       128
weighted avg       0.67      0.70      0.68       128

-----------------------------------------------------
=====================================================
               MULTI-LAYER PERCEPTRON
-----------------------------------------------------
              precision    recall  f1-score   support

      IGNORE       0.39      0.29      0.33        38
         BUY       0.73      0.81      0.77        90

    accuracy                           0.66       128
   macro avg       0.56      0.55      0.55       128
weighted avg       0.63      0.66      0.64       128

-----------------------------------------------------

仔细看,平心而论地问:如果是加权精度最低的方法,为什么 RF 回报最高的 ROI?这是因为:

  • RF 对购买类的精确度最高(83%)。事实上,83%的买入预测是真阳性,剩下的 17%是假阳性
  • 最大限度地减少误报的数量可以最大限度地减少花在 2019 年将会贬值的股票上的钱
  • RF 在忽略类别中具有最高的召回率(79%),这意味着它正确地识别了 79%不应该被购买的股票

然而,所有这一切意味着我们错过了许多可以购买的潜在股票,因为 RF 导致了大量的假阴性。事实上,很容易看出 RF 在买入类中具有最低的召回值(43%),这意味着我们只找到了 43%的应被归类为值得买入的股票。

本文的第 2 部分到此结束。希望你会觉得它有用和鼓舞人心。有关财务建模准备 API、代码和历史数据的更多信息,请查看下面的链接。

[## 免费股票 API 和财务报表 API - FMP API

该文档包括财务报表 API、免费股票 API 和历史报价 API。查找全部…

financialmodelingprep.com](https://financialmodelingprep.com/developer/docs/) [## cnic 92/跑赢股市

这个项目从我在 2019 年寒假问自己的一个问题开始:有可能了解哪些…

github.com](https://github.com/CNIC92/beat-the-stock-market) [## 美股 200+财务指标(2014-2018)

尝试利用 200 多个财务指标预测股票的未来表现

www.kaggle.com](https://www.kaggle.com/cnic92/200-financial-indicators-of-us-stocks-20142018)

简而言之,击败时间序列预测

原文:https://towardsdatascience.com/beat-the-time-series-forecasting-in-a-nutshell-62ba31a3d00b?source=collection_archive---------17-----------------------

揭示时间序列的正确预测方法,表示时间序列的特征,并使用零售数据作为示例代码预测其未来值

来源:科学软件

1.定义时间序列

时间序列是与时间相对应的一系列数值,这是 a 序列与其他截面数据的最大区别。

零售数据、每日温度、产量、需求、自然储量都是时间序列数据,因为当前值取决于其历史值。

2.构成时间序列

时间序列有 4 个组成部分:水平、趋势、季节性和噪声。

  • 水平:时间序列的平均值
  • 趋势:序列值从一个周期到另一个周期的移动
  • 季节性:可以多次观察到的序列的短期周期性行为
  • 噪声:测量误差产生的随机变化

我们并不总是能够注意到噪音中的前三个元素,因为如果我们不使用一些技术来定位它们,它们通常是不可见的。

为了观察和识别这些成分的存在,我们可以考虑。

  • 绘制时间序列图(这是检测序列特征的最佳方式)
  • 放大指定较短时间段
  • 更改系列的刻度,以便更清楚地观察趋势
  • 抑制季节性:将时间序列聚合到一个更大的时间尺度(从每小时到每天,从每月到每年,等等。)

我用一家零售店 3 年的每周销售额作为例子。

plt.plot("Date", "Weekly_Sales", data=Wal_sales);
plt.hlines(y=Wal_sales.Weekly_Sales.mean(), xmin=0,
           xmax=len(Wal_sales), linestyles='dashed');

根据该数据,很明显有两个峰值,这表示在年末(可能是圣诞节和新年期间)有非常明显的季节性。可能有其他季节性,但很难从图上观察到。自相关可用于确认季节性。

3.自相关

自相关描述了时间序列的值与其邻居之间的联系。因此,为了计算自相关,我们计算序列与其滞后版本的相关性。

通过将系列值向前移动 n 个周期,从原始数据集产生 Lag-n 版本。例如,lag-1 向前移动 1 个周期,Lag-10 系列向前移动 10 个周期。

通过观察序列及其滞后的相关性,我们可以确认序列的季节性。

计算和绘制自相关的代码

  • 从上面的自相关图判断,在 lag-52 和 lag-51 中都有很强的正自相关。这意味着在年底会有一个周期性的年度模式
  • 第二个强相关性是 lag-1,它意味着二月的第二周,或情人节期间。
  • 自相关揭示了正的和负的自相关,这意味着序列不是在同一个方向移动,而是上下波动。

我从头开始计算,但是自相关可以通过使用 Python 中的 pandas.plotting 中的自相关 _plot 函数或者 r 中的 tseries 包中的 acf 函数很容易地绘制出来

4.预测时间序列

预测时间序列有几种方法。

  • 基于模型的方法通过多元线性回归来探索序列与其他特征的相关性。与其他横截面数据一样,基于模型的方法计算时间序列对其他特征的依赖性,但另一方面没有考虑不同时期之间的时间序列值之间的依赖性。
  • 数据驱动方法,模型从数据本身学习模式,并根据其之前的值估计时间序列的下一个值。数据驱动方法在给定的时间序列环境中是重要的,相邻时段的值往往是相互关联的。这种相关性被表示为自相关
  • 结合基于数据的方法通过预测序列的未来值以及残差的未来值,然后将两次预测的结果结合在一起。残差预测作为对第一个预测的修正。
  • 系综法通过对多种方法进行平均来得到结果。

在本文中,我将介绍数据驱动的方法。

使用数据驱动方法进行预测:

ARIMA 模型是计算数据驱动预测最常用的选择。你可以在这个帖子中找到 ARIMA 模型的细节。在这里,我将对数据应用 ARIMA。

试试 Python 中 pmdarima 中的 auto_arimafunction 或者 r 中 forecast 包中的 auto.arima 函数很有用。

有一点需要注意的是,从上面的自相关来看,在滞后 52 时有一个明显的季节性,所以我们需要将其纳入 ARIMA 模型。

基于 AIC 分数定义最佳 ARIMA 模型的代码

该函数选择最低的 AIC 分数模型,并将其嵌入以供进一步的模型使用。

然后,分割训练测试集,训练模型并进行预测。

用 ARIMA 模型分割训练测试集、训练和预测时间序列数据的代码

  • 总的来说,该模型似乎在数据上表现一般,但仍有进一步改进的空间。
  • MAPE(平均绝对百分比误差)分数为 5.7%,不算太高,也不算太低。
  • ARIMA 模型似乎在早期预测值中表现良好,而在后期预测值中表现较差。

然而,一个问题出现了,这个模型真的捕捉到了时间序列数据的值吗?

看一下模型的残差(或者预测值与实际值的)是有帮助的。建议检查预测模型的残差,以评估指定模型是否充分捕捉了数据信息。这可以通过探索一个时期的残差与其他时期的残差的相关性来实现。

好的时间序列预测模型的残差具有以下性质:

  • 残差不相关
  • 残差具有零或接近零的平均值(这意味着模型在任何方向都是无偏的)
  • 残差应具有正态分布
  • 残差应具有恒定方差

如果结果缺少上述任何属性,预测模型可以进一步改进。

让我们计算残差自相关并判断结果。

计算和绘制残差自相关的代码

Residual mean: -6308833.905274585

让我们根据以下标准来判断残差的自相关性:

  • 残差不相关:。残差序列仍然被观察到与其滞后有一定的相关性。
  • 残差具有零或接近零的均值(这意味着模型在任何方向上都是无偏的):均值是-6308274585。所以不符合这个标准。
  • 残差应该是正态分布:不完全是正态分布
  • 残差应具有恒定方差:与均值一致不等于 0。

因此,预测模型有很大的改进空间,可以通过找到捕捉残差中相关性的方法,将当前留在残差中的值添加到预测中。

5.数据划分

时间序列区别于正常横截面数据的最大特征之一是未来值对其历史值的依赖性。因此,时间序列的数据划分不能随机进行,而是要将序列分成 2 个周期,前面的周期用于训练集,后面的周期用于验证集。

以下代码将有助于根据时间序列结构分割训练测试集。

分割时序数据的训练集和测试集的代码

销售不仅与自身的过去相关,还可能受到其他因素的影响,如特殊场合(如本数据集中的假日)、工作日和周末等。方法驱动的模型将在下一篇文章中介绍,包括特征提取和特征选择。

最初发表于【https://geniusnhu.netlify.com】

战胜股市

原文:https://towardsdatascience.com/beating-stock-market-8b33c5afb633?source=collection_archive---------57-----------------------

个人项目

或者试图这么做。

埃尔帕尔马(加的斯,弗龙特拉),西班牙,作者:埃斯特万·桑切斯

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

摘要

这是一个个人项目,在这个项目中,我试图使用机器学习工具开发一个交易应用程序。从数据建模以及基于分布和机器学习技术的分类开始,我为新手投资者开发了一个交易策略,以在该应用程序的帮助下产生低风险利润。

介绍

市场分析既有趣又复杂,从以下链接【1】中可以看出。然而,有几项与机器学习一起进行的工作试图阐明这一领域。

在这个作品中,我创建了一个由两个要点组成的应用程序:

  1. 可以在不同时间范围内分析股票市场指数的屏幕。这里可以找到一张烛台图;一张图来分析技术指标【2】;一个折线图显示了日内价格变化的百分比,以及一个箱线图来表示这最后一个图表,以便理解这种分布。
  2. 我开发的交易策略分析( Strategyone )可以在这个屏幕上完成。该策略分为两个不同的部分:第一部分包括通过机器学习对股票市场指数运动的预测,而第二部分包括当前数据向量预测和过去发生的事情之间的比较。选择的时间范围从 7 天、14 天、21 天到 28 天不等。

最后一节将在“如何战胜市场”和“交易策略”中详细解释

数据是通过 Alpha Vantage API【3】获得的,而一份股票市场指数列表是从 Finn hub API【4】获得的。

语境

作为一名物理学家,我一直对复杂系统世界着迷:某些公式如何应用于生物系统或金融系统,以及几个电子的组合,并产生有趣的结果。

同样,当在系统中研究时,对系统中某个元素的个别研究可能会导致不同的行为。

因此,这个项目产生于对股票市场的好奇,以及软件和智力的挑战,这意味着要理解市场这样一个复杂的系统。

该项目已经经历了三个阶段:这项工作的第一个版本是作为我在【5】参加的数据科学硕士学位的最终论文开发的,其目的只是创建分类模型,该模型可以使用机器学习来预测股票在市场上的未来。第二个版本是在主版本的基础上设计的,它试图改进第一个版本。最后,第三个版本是这里讨论的版本,它提供了一个重要的改进,即交易策略的发展。

如何战胜市场

为了使用分类模型来预测市场走势,我需要对数据进行分类。这些预测类别被称为“强势牛市”,即价格上涨显著的预测;“牛”,有涨价的时候;“保持”,价格不变;“熊”,价格上有所下降,而“强熊”,价格下降显著【6】。

股市指数类别是如何选择的?

这是通过股票价格的百分比变化分布实现的。因为我们的目标是预测未来,所以在寄存器中,百分比变化列需要关于价格如何相对于我们想要预测的时间范围变化的每日信息

因此,将待分类的变化百分比与最近 4 个月的分布进行比较,并根据与该分布相关的百分点范围选择上述类别之一。

通过这种方式,我们可以在一个时间范围内对所有数据进行分类,这将永远是关于未来的。

分类完成后,下一步是了解应用更精确的分类算法的最佳方式。经过多次试验和不同的想法后,选定的流程是通过鲁棒缩放器技术和随机森林作为分类算法来缩放数据。这些是被选中的,因为它们在所有类别中提供了平均更高的精度。

只有遵循这些步骤,我们才能获得一个能够以 40 %的准确率预测“强牛”的模型。

交易策略

交易策略将基于过去发生的事情,以及假设我们赢了,我们猜对的想法,省略为了赢,我们还必须猜对预测的类别

也就是说,如果预测是“牛市”,我们进行多头操作,结果实际上是“强牛”,我们的预测将被认为是准确的。同样,如果我们预测“强势牛市”,结果是“牛市”,或者当预测是“强势熊市”时,我们进行空头头寸移动,结果是“熊市”,反之亦然。

如果没有发生上述情况,手术将被视为失败。

考虑到这一点, 策略将仅包括多头操作,并且当模型预测到“强势牛市” 时,假定它是来自分类模型的具有较高准确度的类别。

这个策略是如何运作的?

一旦鲁棒定标器应用于所有寄存器,类别被预测,实际分类,应用PCA将维数减少到 4,保持 95 %的数据可变性。因此,我们还有其他 4 个变量以及与寄存器及其实际类别相关联的预测。当预测与真实类别相关的事物时,可以知道变量如何,因此我们安排预测和类别,并且我们计算与每个轮廓曲线相关的中值,以了解如何描述每个轮廓曲线。

因此,我们将描述预测“强牛”的变量,以及实际结果是“强牛”或任何其他类别。

所有这些都将限于与预测日相关的最近 6 个月的数据,以避免旧的市场状态对策略的影响。获得的结果总结如下:

PCA 后每个预测类别的变量描述。

该表的解释是,在预测“强牛”和类别被猜对之前的最近 6 个月,主成分的变量曾作为中位数。

因此,为了执行操作,我们必须将我们正在进行预测的一天的数据应用于鲁棒定标器和 PCA,

如果得到的预测是“强牛”,我们就已经达到了进行操作的第一步。第二步是检查前面曲线的哪个轮廓与预测的数据更相似。这将使用余弦相似度来完成,这将允许我们观察与数据更相似的向量。如果它对应“强牛-强牛”,我们就有了执行更安全操作的钥匙。

遵循这个交易策略,我们将获得几乎 50 %的准确率,但是,正如开始提到的,猜对并不意味着也能猜到类别。

猜对并不意味着也要猜对类别

在我们的情况下,正确的猜测也将是“强牛”的预测,并获得“牛”作为最终结果。考虑到这一点,策略准确率达到 58 %。

结论

这项工作的目的是开发一种策略,允许初学者投资者在不遭受全部损失的情况下获得低风险利润。正如我所提到的,该策略确保了在所述条件下 58 %的准确度,但是,就个人而言,它不是一个自动实施的策略,因为假设的误差水平会上升到 40%。

然而,有趣的是,在执行的操作中,遵循仅基于数据的策略,并且对股票市场了解有限且最少,如何获得超过 50 %的准确度。

所有项目代码可在 GitHub/esan94/bsm03 上阅读

以下步骤

下一步可能的改进措施包括:

  • 数据模型的变化。
  • 分类算法的改进。
  • 这个项目增加了更多关于股票市场的知识。
  • 应用余弦相似性对主要成分赋值。

资源

  • [1]https://en.wikipedia.org/wiki/Efficient-market_hypothesis
  • https://www.investopedia.com/technical-analysis-4689657
  • https://www.alphavantage.co/
  • https://finnhub.io/
  • https://kschool.com/
  • [6]https://www . investopedia . com/insights/digging-deep-bull-and-bear-markets/

可以在 LinkedIn 、 GitHub o Medium 上关注我。

帕洛玛·桑切斯·纳瓦埃斯翻译。

击败 ETF:使用 Python(…和一些线性代数)进行投资组合优化

原文:https://towardsdatascience.com/beating-the-etf-portfolio-optimisation-using-python-and-some-linear-algebra-e48d0e0e44f?source=collection_archive---------13-----------------------

这个故事涵盖:
1)什么是马柯维茨均值/方差优化投资组合
2)如何使用 Python(
GitHub提供源代码)来计算一个投资组合
3)如何根据一个已建立的市场交易基金来回溯测试你的策略

这个实验的目的是看看我们是否可以使用 1952 年的概念来创造一个被动的投资组合,这个投资组合会比今天表现最好的交易所交易基金做得更好。

免责声明:这仅仅是一个数字和计算练习,不应被视为投资建议或任何基础。

前言

为了找到一个有价值的竞争对手,我谷歌了“最佳被动技术 ETF”,跟随第一个链接选择了排名第一的基金——我不知道我是否可以在媒体上引用它的正式名称——让我们称它为基金 X 。基金 X 专门投资于在北美主要交易所上市的科技和软件行业股票,并(截至 2020 年 6 月 9 日)投资于 104 只个股。我已经从这里下载了所有美国股票的表现,由 Kaggle 社区提供,并过滤了基金的头寸。

从现在开始,我的目标是编写一个算法,遍历这些股票,分析它们的表现,并将它们组合成一个均值/方差最优的投资组合(……然后看看它的表现如何与专业资金经理的表现相比较)。

游戏开始了!

一些背景

1952 年,Harry Markowitz 博士写了他关于最优均值-方差投资组合的开创性论文——这项研究随后为他赢得了 1990 年的诺贝尔经济学奖。他的研究为现代投资组合理论(MPT) 奠定了基础,该理论的核心有一个相当违反直觉的想法。Markowitz 建议,当从两种资产(例如股票)中选择一种在风险调整后的回报方面明显更理想的资产时,投资者可能会更好地将都加入到他的投资组合中,如果它们提供了足够的分散化效应(想想像这样的风险分散化,不要把所有的鸡蛋放在一个篮子里)。

两种资产的简单示例可以扩展到更复杂的真实世界场景,涉及数十甚至数百个单个头寸。

但是首先……一点数学

这里我们将看到如何找到有效边界和切线投资组合。如果你只是来看结果的,请随意跳过这一部分,否则让我们直接进入:

在选择资产的最优组合时,MPT 指出,我们必须考虑资产的(历史)回报和成对协方差。目标是找到在给定的预期回报水平下,最小化预期投资组合方差的资产组合。数学上,这个目标函数是:

其中:
w —资产权重向量
𝜇 —资产收益向量
σ—资产协方差矩阵
π —投资组合收益的预期水平

我们构造一个拉格朗日函数并求偏导数:

省略重组,这可以在这里找到,我们得到一个将投资组合权重表示为投资组合预期回报的函数的函数:

权重向量,代表我们在有效边界的持有量(对于给定的π回报水平)

获得的表达式将为我们提供一个资产的相对权重向量,该向量将最小化任何目标回报水平的方差。计算每个回报水平的方差,并将结果绘制在图上,得到有效边界 (我们将在后面绘制)。

虽然边界本身是一个很好的视觉辅助工具,但我们如何知道选择曲线上的哪个点(风险/回报曲线)?这就是切线投资组合的用武之地。切线投资组合旨在最大化预期风险调整后的回报,位于资本分配线与我们的边界曲线(同样,我们稍后将计算一个)相切的点。

切线投资组合是通过最大化投资组合的(预期)夏普比率找到的。再一次,目标函数:

拉格朗日和导数;

再一次,一些重新安排沿着这条路走下去:

权重向量,代表我们在切线投资组合中的持股

完成推导后,我们可以直接开始实施策略。

必须指出的是,迄今为止以这种方式建立起来的实验,对 ETF 来说并不完全是“公平的”。我们的投资组合优化目标函数仅受权重相加必须达到 100%的约束(“无杠杆约束”)。为了与只做多的基金公平竞争,我们还必须实施禁止卖空约束——即限制所有权重为正值。然而,这将计算问题转化为非线性任务。稍后我们还将使用 Python SciPy 库来完成这项工作。

实验本身

让我简单解释一下我是如何设置数据的。

准备

从 Kaggle 下载的股票回报有直到 2017 年 11 月的数据——这是我的第一个限制。其次,为了获得某种程度的可靠性,最好只使用那些股票,因为我至少有几年的价格数据。经过一番思考,我决定只使用 X 基金的股票,我有 10 年的历史——7 年的训练和 3 年的测试。这使得最初的 104 只股票的投资组合减少到只有 35 只,但它们占了投资组合总价值的 60%以上,所以我对此很满意。

我们现在假设我们是一个投资者,在 2014 年 11 月坐在一堆现金上,手头有 7 年的股票数据表现,希望通过模仿臭名昭著的 Fund X 的策略来投资我们的储蓄:

多空优化

实验的第一部分(也是更容易的部分)包括盲目应用我们之前定义的公式。如果你想继续编码,可以从 这里 (提供解释)随意克隆这个库。使用 7 年的股票收益构建的有效边界看起来如下:

08 年危机后的科技行业…解释了约 50%的年化波动率

旁注 :如果你对金融市场没有太多经验,看到一个预期年回报率超过 75%的切线投资组合是而不是很平常的事情。巨大的预期回报和波动性可以解释为这是一个“多头/空头”投资组合,因此“有效边界”越向右上角移动,我们的“多头”和“空头”头寸就越大。此外,我们正在关注科技行业——通常是高贝塔股票——我们的数据来自一个动荡的后危机时期。

总的来说,MPT 的基本思想是:通过将资产组合成一个投资组合,我们能够“获得”比单独投资每只股票好得多的风险回报。让我们看看我们的“最优解”与基金 X 的构成和表现相比如何:

上图:每只股票的配置||下图:投资增长

正如所料,我们的多空投资组合的表现非常不稳定。从图表上看,在三年的大部分时间里,它的表现可能好于 ETF,但实际上,这要归功于其异常的波动性(我个人会将其归因于“幸运”的时机)。如果复制 代码 ,可以修改 training_period 参数,看看对性能的真正影响有多大。此外,这种“盲目”的解决方案导致我们的投资组合权重“激增”,在一只股票中达到+80%和-40%。

不太好。

因此,一个更现实的(也是对 ETF 更“公平”的)测试是将我们的头寸限制在仅做多。

仅长优化

为了将我们之前定义的目标函数限制为仅“接受”长位置,我们添加了一个约束,即权重向量中的每一项必须大于或等于 0。此外,共同基金的投资组合经理通常对单一基金的最大允许分配有限制。我决定将每只股票的权重限制在 10%以内。

使用 Python SciPy 库(和Broyden–Fletcher–gold farb–Shanno 算法,我们以同样的方式优化我们的函数:

切线投资组合:仅做多,<10% in a single stock

Performance and composition: long-only, <10% in a single stock

不做过多评论,但……:

两个观察:
——我们可以看到,我们的股票权重变得不那么“爆炸性”,整体波动率也远低。
-所有股票都来自同一个行业,这意味着它们具有相似的风险/回报特征和高度的成对相关性。因此,我们的“解决方案”有许多权重绑定到 10%约束。

金融书呆子统计

一些有趣的风险/回报指标:

上半部分:度量值越高,“越好”||下半部分:度量值越低,“越好”

摘要

也许正态分布回报的标准差并不是衡量投资组合“风险”的好指标。也许我们应该努力找到所有 104 只股票的数据。也许 X 基金经理坐在一个黑暗的、挂满布帘的房间里,手里拿着一个水晶球。不管怎样,我们的“快速而肮脏的”解决方案在竞争中表现不佳。

如果你复制了源代码,你可以尝试增加更多的股票,引入不同的风险措施,每年重新平衡投资组合或者做任何我没有做过的事情。

金融市场的博弈直到今天仍未解决。许多人尝试,许多人失败。欢迎大家下载资料一试身手:)

打甘游戏

原文:https://towardsdatascience.com/beating-the-gan-game-afbcce0a20be?source=collection_archive---------39-----------------------

开发“自切片面包以来最酷的东西”的技巧

“柏拉图的洞穴”作者 Jan Saenredam,之后是 Cornelis Cornelisz。范哈勒姆,1604 年。在公共领域下许可。

生成对抗网络(GANs)是深度学习中最令人着迷的发展之一。Yann LeCun 自己将 GANs 命名为“自切片面包以来最酷的东西”[1]。

这些架构正被应用于大量的问题。在从暗物质研究[2]到室内设计[3]的应用中获得成功。

GAN-build Mona Lisa,来自“现实神经说话头部模型的少数镜头对抗学习”,2019 年论文

看到如此广泛的令人着迷的应用,研究和开发 GANs 的愿望已经在我的脑海里发痒了很长时间。最近,我屈服了,决定是时候投入进去了。

我很快了解到甘人不容易驯服。正因为如此,我对第一次进入 GANs 的世界时常见的许多误解和错误有了新的体验。

我在本文中总结了我从中学到的错误,这些错误可能是 GAN 实施和融合中成功与失败的区别。

坦,不是乙状结肠

tanh v 形(逻辑)激活

在预处理图像数据时,我们应该将其归一化到-1 和 1 之间,而不是 0 和 1 之间[4]。

这也意味着我们在 G 中的最终层激活应该是tanh而不是sigmoid

255

这里需要注意的另一个重要的事情是后生成,不要忘记将值乘以 127.5,再加上 127.5,以返回到 0–255 的原始范围。

image_array = generated_tensor.numpy() * 127.5 + 127.5

不要过度使用过滤器

最初,当我的 DCGAN(深度卷积 GAN)在亮度变化中挣扎时,我认为生成器的转置卷积层只是缺乏复杂性。

所以,我加了更多的滤镜。事实证明,这与我本该做的事情完全相反。

减少过滤器的数量可以让生成器更好地表示值的范围。

以下是一些过滤大量生成的 MNIST 数:

发电机过滤器尺寸为:256 > 128 > 64 > 1

现在使用最少的过滤器:

发电机过滤器尺寸为:32 > 16 > 8 > 1(您也可以降低尺寸)

过多的过滤器会将发生器值推到极限。对于tanh来说,这是-1 或+1。导致生成的图像缺乏说服力。

稀疏渐变不好

稀疏梯度本质上是弱信号。或者具有非常低的值的信号。

这些低值信号的问题是,随着对它们进行许多数值运算,它们会变得越来越小。

熟悉 RNNs 的人无疑会遇到梯度消失的问题。这是完全一样的。

为了解决这个问题,我们可以将批量标准化添加到我们的网络中[5]。

需要注意的是,批量标准化应该发生在 s 形激活(tanh,sigmoid/logistic)之后,非高斯激活(ReLU,LeakyReLU)之前【5】。

泄漏激活

此外,对发生器和鉴别器*[4]始终使用leaky relu——除了最后一层,我们使用 s 形激活函数。

*最初的 DCGAN 在发生器中使用 ReLU 激活,在鉴别器中使用 leaky ReLU[3]

学习率

有时候我们需要在鉴别器和生成器之间找到一个更好的平衡。

最初,我的鉴别器学得太快了。实质上冻结了发电机,使其无法取得任何进展。

我们可以通过降低或提高双方的学习率来平衡这一点,让我们较弱的网络有更多的喘息空间。

从 MNIST 开始

我尝试做的第一件事就是创造这些复杂的艺术风格。当它不起作用时,我不知道为什么。图像太复杂了吗?我对它们的预处理正确吗?也许问题出在网络上,网络可能在任何地方。

因为我是从零开始构建的,所以没有其他实现可以比较和基准测试。最后,代码中出现了几个问题,但我只是通过为 MNIST 数据集重新构建代码来识别这些问题。

这允许您看到您的结果和代码与其他结果和代码的不同之处,因此问题更容易诊断。一旦您的网络产生了合理的输出,您也可以将质量与其他实现进行比较。

因此,在开始某个很酷但很复杂的项目之前,先尝试一下 MNIST(或另一个已建立的数据集)。

最后一个音符

最后,甘人并不像他们第一次看到的那样狂野。有了合适的资源,构建我们的第一个 GAN 是一个相当简单的过程。

但是每一个错误都会提高我们的知识,并使我们更接近驯服这些众所周知的困难的架构。

我在下面列出了我在研究和实现 GANs 时非常依赖的资源列表(用粗体)。我怎么推荐这些都不为过。

感谢阅读!

参考

[1] Quora 与 Yann LeCun 的会议 (2016),Quora

[2] M. Mustafa,D. Bard,W. Bhimji,Z. Luki,R. Al-Rfou,J. Kratochvil, CosmoGAN:使用生成对抗网络创建高保真弱透镜会聚图 (2019),计算天体物理学和宇宙学 6:1

【3】a .拉德福德,l .梅斯,s .钦塔拉, 深度卷积生成对抗网络的无监督表示学习 (2016),ICLR 2016

【4】s .钦塔拉, 如何训练一个甘? 、GitHub

【5】j . Brownlee, 深度神经网络批量归一化的温和介绍 (2019),machining Learning Mastery

如果你对其他机器学习项目感兴趣,你可能会喜欢我以前的项目,在那里我在复制斯多葛派哲学中使用递归神经网络进行文本生成:

[## 斯多葛派哲学——由算法构建

再现历史上最有权势的人之一所写的斯多葛派哲学

towardsdatascience.com](/stoic-philosophy-built-by-algorithms-9cff7b91dcbd)

战胜困难

原文:https://towardsdatascience.com/beating-the-odds-8d26b1a83f1b?source=collection_archive---------32-----------------------

利用数据科学发现 NBA 最伟大的超常球员

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

这是我每周体育主题系列的第一部分。每周我将展示数据科学的应用,并寻求对我们喜欢看的比赛提供深思熟虑的分析和见解。

在这篇文章中,我确定了 NBA 历史上超水平发挥的球队。数字显示的球队应该不是很好,但仍然无视他们的统计优势。事不宜迟,让我们把这事捅出去。

使用运动参考 API 获取数据

首先,我们需要一些数据。谢天谢地,体育参考提供了一个免费使用的 python API ,可以轻松访问超过半个世纪的篮球数据。API 还可以用来访问足球、棒球、曲棍球和英式足球的数据集;对于几乎所有与体育相关的数据项目来说,这都是一个很好的起点。要开始使用 Sports Reference API,您需要像使用 pip 或 conda 的任何其他 python 包一样安装它。

安装了 sports reference API 之后,让我们从获取我们希望包含在分析中的球队的数据开始。我选择了从 1980 年到现在的所有球队。下面的代码使用 Sports Reference Teams 模块构建一个 pandas 数据帧,其中每行代表一个队的一个赛季。它还会将索引设置为一个名为“id”的列,这是团队缩写和年份的简单组合,作为唯一的标识符。这个“id”索引将在以后合并到其他数据帧时派上用场。

import pandas as pd
from sportsreference.nba.teams import Teamsyear = str(2020)
all_team_df = Teams(year = year).dataframes
all_team_df['id'] = all_team_df['abbreviation'].apply(lambda x: x + " 2020")
print(2020)for i in range(2019,1979,-1):
    year = str(i)
    temp_df = Teams(year = year).dataframes
    temp_df['id'] = temp_df['abbreviation'].apply(lambda x: x + " " + year)
    all_team_df = pd.concat([all_team_df, temp_df], axis = 0)
    print(i)all_team_df['year'] = all_team_df['id'].apply(lambda x: x.split(' ')[1])
all_team_df.set_index('id', inplace = True)

上面代码的结果是下面的 1134 x 47 数据帧。

使用命令all_team_df.columns显示我们必须处理的数据帧的所有列。

这里有很多有用的数据,但是我们仍然缺少一些重要的信息。这个数据框架不包含任何关于输赢的内容!由于一个团队成功的最终衡量标准是赢得比赛,我们必须收集这些数据,并将其加入到我们正在构建的数据集。为此,我们将使用运动参考时间表模块。因为我们需要为 1134 个团队中的每一个团队创建并迭代一个 schedule 对象,所以定义一个助手函数来完成这项工作会使代码更加简洁。

from sportsreference.nba.schedule import Schedule# helper function to pull wins
def get_wins(tid):
    abb = tid.split(' ')[0]
    year = int(tid.split(' ')[1])
    games = 0
    wins = 0
    playoff_games = 0
    playoff_wins = 0

    # Create schedule object for team and iterate through every game
    for game in Schedule(abb, year = year):
        if game.playoffs == False:
            games += 1
            if game.result == 'Win':
                wins += 1
        elif game.playoffs == True:
            playoff_games += 1
            if game.result == 'Win':
                playoff_wins += 1

    return wins, games, playoff_wins, playoff_games# create dictionary and populate with team records for every year
total_wins_dict = {}for y in range(1998, 1979, -1):

    tids = all_team_df[all_team_df['year'] == str(y)].index

    wins_dict = {'id': [], 'wins': [], 'games': [],
                 'playoff_wins':   [], 'playoff_games': []} for i, tid in enumerate(tids):
        wins, games, playoff_wins, playoff_games = get_wins(tid)
        wins_dict['id'].append(tid)
        wins_dict['wins'].append(wins)
        wins_dict['games'].append(games)
        wins_dict['playoff_wins'].append(playoff_wins)
        wins_dict['playoff_games'].append(playoff_games)

    total_wins_dict[y] = wins_dict
    print(y)# concatenate all team record data into one dataframe
total_wins_df = pd.DataFrame(total_wins_dict[2020])for key in list(total_wins_dict.keys())[1:]:
    temp_df = pd.DataFrame(total_wins_dict[key])
    total_wins_df = pd.concat([total_wins_df, temp_df], axis = 0)total_wins_df.set_index('id', inplace = True)

完成团队记录的数据框架后,下一步是将其与我们的其他数据合并,并将结果保存到 csv 文件中,以便于以后访问。

all_data = pd.merge(left = all_team_df, right = total_wins_df,
                    how = 'inner', left_index = True,
                    right_index = True)all_data.to_csv('Data/all_team_data_1980-2020.csv')

线性回归

现在我们可以进入这个分析的有趣部分,使用收集的数据来识别 NBA 最伟大的超水平发挥的球队。这里的想法是建立一个模型来预测一支球队赢得的比赛数量,然后看看哪些球队的表现最好。虽然我们有大量的数据来建立一个模型,但我会保持简单,只使用一个单一的特征,平均胜利幅度(MOV)。显然,一支得分比对手多的球队往往会表现得更好。让我们首先打开一个新笔记本并导入数据集。

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
import numpy as np%matplotlib inlinedata = pd.read_csv('Data/all_team_data_1980-2020.csv', index_col = 'id').drop('Unnamed: 0', axis = 1)

虽然我们的数据集中没有 MOV 的列,但是可以使用“points”、“opp_points”和“games”列轻松创建。我们还将为常规赛胜率创建一个列,用作我们的目标变量,这有助于考虑在停摆缩短赛季中比赛的球队。最后,我们将把数据分为特性和目标,将数据输入线性回归模型,并生成回归结果的汇总表。

data['MOV'] = [(points - opp_points) / games for points, opp_points,
               games in zip(data['points'], data['opp_points'],
               data['games'])]data['win_rate'] = [wins / games for wins, games in
                    zip(data['wins'], data['games'])]# create inputs
X = pd.DataFrame(data['MOV'])
X['intercept'] = [1 for x in range(data.shape[0])]y = data['win_rate']# create and fit linear regression model
model = sm.OLS(y, X)
fit = model.fit()
fit.summary()

这里生成的汇总表显示,这个极其简单的模型与我们的数据非常吻合,R 为 0.941。此外,该模型在获胜游戏数方面的平均绝对误差仅为 2.4 场。下面的代码生成了一个预测的和实际的 MOV 获胜的图形,以及一个模型残差的分布图。

# create predictions for every team
preds = fit.predict(X)# create a dataframe to hold all results
results = pd.DataFrame({'id': data.index, 'prediction': preds})# merge with input data and actual results
merge_cols = ['MOV', 'win_rate', 'wins', 'games', 'playoff_wins',
              'playoff_games']results = pd.merge(left = results, right = data[merge_cols],
                   how = 'inner', right_index = True,
                   left_index = True)# use predicted win rate to predicted integer number of wins
results['predicted_wins'] = [int(round((prediction) * games, 0)) for
                             prediction, games in
                             zip(results['prediction'],
                             results['games'])]# create error columns
results['error'] = [act - pred for act, pred in
        zip(results['win_rate'], results['prediction'])] results['game_error'] = [wins - pwins for wins, pwins in
                         zip(results['wins'],
                         results['predicted_wins'])]plt.figure(figsize=(15,6))plt.subplot(1,2,1)
sns.scatterplot(x = X['MOV'], y = y)
sns.lineplot(x = X['MOV'], y = preds, color = 'red')
plt.title('Margin of Victory vs Win Rate')plt.subplot(1,2,2)
sns.distplot(results['game_error'], bins = 21)
plt.title('Residual Distribution');

使用刚刚创建的结果数据框架,现在可以通过对“错误”列上的数据框架进行排序来轻松挑选出最优秀的学生。这些是根据他们的平均胜率预测赢得最多比赛的球队。这样做会产生以下结果:

具有讽刺意味的是,我们的分析刚刚确定了 1993 年的达拉斯小牛队,可以说是 NBA 历史上最差的球队之一,也是 NBA 历史上最伟大的超水平发挥的球队。这是一支输了 42 场 15 分以上,输了 26 场 20 分以上,输了一场 58 分的球队。除了输球,很难说这支球队在其他方面“超水平发挥”。这到底是怎么回事?为什么我们的模型产生了如此大的拟合,却导致了如此不合理的结果?

事实证明,这是一个很好的例子,说明为什么简单的线性回归永远不应该用来模拟比例。理论上,当比例被限制在 0 和 1 之间时,线性模型可以输出任何实数。如果 1993 年的小牛队公布了一个稍差的 MOV,我们的模型就会预测到一个负胜率!我们创建了一个模型,倾向于挑选非常差的团队作为优等生,非常好的团队作为劣等生。

逻辑回归

解决方法是使用逻辑回归而不是线性回归。不幸的是,sklearn 中方便的逻辑回归模块只适合分类数据,而不是实际比例。这意味着我们需要做一些额外的工作来将线性回归转换成逻辑回归。

逻辑回归的核心是对比例、概率或分类的对数优势进行线性回归。因此,第一步是定义函数,将我们的目标变量“win_rate”转换为 log-odds,然后再转换回来。这些函数通常被称为 logit 和 sigmoid 函数,可以在我们的 python 笔记本中轻松定义如下:

def logit(p):
    return np.log(p/(1-p))def sigmoid(x):
    return 1 / (1 + np.exp(-x))

然后,我们将重复我们用来产生线性回归的过程,只有一些微小的变化。

  1. 我们的目标变量“win_rate”使用 logit 函数转换为对数赔率。
  2. 使用具有单一特征“MOV”的常规线性回归来拟合目标,这与以前没有什么不同。
  3. 使用 sigmoid 函数,我们的线性回归预测(以对数赔率的形式)被转换为更熟悉的“胜率”。
# create inputs
X = pd.DataFrame(data['MOV'])
X['intercept'] = [1 for x in range(data.shape[0])]
y = data['win_rate'].apply(logit)# create and fit linear regression model
model = sm.OLS(y, X)
fit = model.fit()
fit.summary()# generate predictions
preds = [sigmoid(x) for x in fit.predict(X)]

正如预期的那样,这种逻辑回归模型对我们的数据产生了稍好的拟合,R 为 0.944,平均绝对误差仅为 2.3 场。虽然这只是比我们之前的模型稍微好一点,但是绘制结果显示更适合具有更极端的正或负 MOV 值的团队。这些图可以使用与以前几乎完全相同的代码生成。

NBA 最伟大的成功者是…

现在,我们实际上可以确定 NBA 最伟大的超水平球队。为了获得更有说服力的结果,让我们过滤输出,只包括至少赢得 4 场季后赛的球队。

overachievers = results[results['playoff_wins'] >= 4].sort_values(by = 'error', ascending = False)overachievers.head()

现在你知道了,NBA 最伟大的球员是 1987 年的金州勇士队。在乔·巴里·卡罗尔、斯里皮·弗洛伊德和克里斯·穆林的带领下,1986-87 赛季勇士队的 MOV 得分很低,只有 2.3。虽然这通常会导致一个令人失望的赛季,但 1986-87 年的勇士队获得了 42 场胜利,远远超过了他们预测的 34 场胜利,在西部联盟中排名第五。球队在两场控球比赛中取得了 63%的胜率,同时也在 30 场比赛中输掉了 10 分或更多。在季后赛中,勇士队在 5 场比赛中(3-2)击败了 4 号种子犹他爵士队,然后在 5 场比赛中(1-4)输给了被广泛认为是有史以来最好的球队之一的湖人队。

感谢你的阅读,我希望下周你能回来。

链接到 Github

用遗传算法打破俄罗斯方块世界纪录

原文:https://towardsdatascience.com/beating-the-world-record-in-tetris-gb-with-genetics-algorithm-6c0b2f5ace9b?source=collection_archive---------16-----------------------

使用 PyBoy 和 Python

你好,我是尼克🎞 on Unsplash

几周前,我发现了这个用 Python 写的支持人工智能/机器人的很棒的游戏模拟器。我非常兴奋,因为现在我可以使用我的机器学习知识来创建困扰我童年的游戏代理。

在本文中,我将展示我们如何使用遗传学算法和神经网络的简单实现来创建一个代理,它可以在 Game Boy 上非常好地玩原版俄罗斯方块,并能够打破根据twin galaxy创下的 999999 和 523 行的世界纪录。

俄罗斯方块是最畅销的视频游戏系列之一,是一款益智游戏,主要目标是通过清除俄罗斯方块(是的,这些方块就是这么叫的)的线条来获得尽可能高的分数。游戏的规则非常简单,然而,它实际上是一个 NP 完全问题[1]。这意味着编码一个基于规则的代理可能不是最明智的方法,启发式算法,如遗传算法,将是一个更好的选择。

遗传算法(GA)是一组受达尔文进化论启发的算法。这些算法用于解决优化问题。这意味着我们可以使用遗传算法来优化神经网络的权重(他们也可以做得很好)。在这篇文章中,我不会深入讨论什么是神经网络,因为已经有很多关于它的资源,比如这里的。

总的想法是,我们将创建一个神经网络(NN ),它将为代理所做的每个动作生成一个分数。对于每个新的 tetromino,代理将尝试所有可能的动作,并选择得分最高的动作。使用遗传算法,我们希望通过进化优化网络,使其收敛到最佳状态。

评估可能行动的网络

在 GA 中,我们有一些关键的概念:适应度精英主义交叉变异

  • 适应度是我们如何衡量网络的能力,以将其输出与移动的好坏相关联。
  • 精英主义是指一定比例的高性能网络被带到新一代。
  • 交叉是使用另外两个网络的基因(权重)创建新网络的过程。
  • 变异包括随机修改网络的权重。

步骤如下:

  1. 生成具有随机初始权重的神经网络群体。
  2. 对于每个网络,一直玩到游戏结束。
  3. 计算每个网络的适应度得分。
  4. 把表现最好的网络带给下一批人(精英主义)。
  5. 从当前群体中随机选择 2 个网络(父代)并执行交叉以产生一个新的网络(子代)。
  6. 以 x%的概率突变新的网络权重。
  7. 继续,直到我们达到所需的世代数。

像许多其他机器学习问题一样,我们需要做的第一步是收集数据,或者在这种情况下,从环境中收集状态数据。这里有一个快速的例子展示了如何快速初始化环境。

这个脚本本身是不言自明的。开发者通过tetris.game_area()很容易获得游戏的状态。然后,我们可以创建一个稀疏矩阵,其中 0 是空白瓦片,1 是碎片:

area = np.asarray(tetris.game_area())area = (area != 47).astype(np.int16)

棋盘的矩阵表示

使用上面的矩阵,我们可以定义许多特性,如[2]所示:

合计高度 计算所有列高度的总和。在上面的例子中,总和是 16。

孔数
棋盘上的孔数。下面的板上有 6 个孔:

至少有一个孔
的列数,在上例中为 5。

凹凸度 各列之间的绝对高度差之和。在下面的棋盘中,它是:1 + 0 + 2 + 2 + 0 + 0 + 1 + 0 + 0 = 7

行转换 每一行中从被占用到未被占用的瓦片的转换数量相加。下图中的每个红点算作一个过渡:

列转换
与上面类似,但按列进行。

凹坑数量
凹坑被定义为没有任何块的列。下面的板上有 3 个坑:

最深的井 一口井可以通过下面的图片得到最好的解释。在这种情况下,最深的井的高度为 2。

清除的行数 移动时清除的行数。

让我们使用矩阵表示来实现这些功能:

现在,让我们实现算法:

首先,我们为网络创建一个类

我们的模型是一个简单的网络,输入层大小为 9,输出层大小为 1。这个简单的网络将使我们能够轻松地解释权重,并且可以表示如下:

我使用 PyTorch 来创建网络,但是您可以随意使用任何其他库或实现您自己的库。利用这一点,我们可以创建一个实现了交叉和变异的种群类:

对于每一代新人,我们将带来前 20%的网络。

对于交叉,我们用从群体适应度产生的概率分布对父母进行采样(网络适应度越高,它被选择的可能性就越大)。每个体重都是随机选择的,父母双方各有 50%的机会。

交叉

随后,权重有 20%的机会随着乘以因子 0.5 的随机高斯噪声的增加而变异。

下一步是编写一些逻辑来玩这个游戏。首先,让我们定义一些助手函数来移动块:

对于每一个新的作品,我们会尝试所有可能的动作。我们需要检查的转身和横向移动的次数取决于积木的类型。我们可以使用这三个函数来确定它们:

现在我们有了开始模拟网络所需的一切。对于每一个新的棋子,我们将棋盘信息传递给get_score()以获得每个可能动作的网络输出。我们选择输出最高的动作。一旦游戏结束,我们返回网络的适应度也就是游戏的分数。

由于游戏的随机性,网络不会为每次运行产生相同的结果。我们可以通过run_per_child评估每个网络的多次运行,以更好地估计网络的适应性。

随着代理在游戏中变得更好,培训时间会变得更长。为了加快训练速度,我们在代理达到最高分数(999999)时停止游戏,并使用多重处理。生成多个进程来并行评估网络非常简单,如下所示:

现在你知道了,我们已经实现了一个遗传算法来创建一个可以玩俄罗斯方块的简单代理。这里有一个例子,在人口规模为 50 的情况下,仅经过 10 代就获得了最佳模型:

Scores: [999999.0, 999999.0, 729892.0, 372490.0, 999999.0, 296117.0, 299328.0, 533870.0, 282609.0, 525193.0]
Average: 603949.6Lines: [1031, 1002, 825, 415, 935, 393, 364, 622, 389, 582]
Average: 655.8

然而,由于代理的简单性,它肯定有一些限制。由于代理人只考虑当前的奖励,而忽略未来的奖励,这很可能会出现这样的情况:放置一个方块可以清除线,但会恶化棋盘的位置。此外,由于棋盘尺寸较小(18x10),如果代理连续获得多个坏块,则很有可能会输。这导致运行之间的标准偏差非常高,如上例所示,在最佳运行中,代理清除了 1031 行,在最差运行中清除了 364 行。

就这样,我希望你在阅读我对这个项目的方法时感到有趣。请随意查看完整的源代码,并根据您的意愿进行任何改进:https://github.com/uiucanh/tetris

参考资料:

[1]埃里克·德梅因、苏珊·霍恩伯格、戴维·李奔-诺埃尔。 俄罗斯方块比较硬,甚至可以近似

[2]雷南·萨缪尔·达席尔瓦,拉斐尔·存根帕皮内利。 玩原版游戏《男孩俄罗斯方块》用的是实数编码的遗传算法

Python 中漂亮而简单的绘图——熊猫+散景

原文:https://towardsdatascience.com/beautiful-and-easy-plotting-in-python-pandas-bokeh-afa92d792167?source=collection_archive---------9-----------------------

照片由乔伊·凯伯在 Unsplash 拍摄

创建从熊猫数据帧到散景的交互式绘图的一行代码

虽然 Matplotlib 可以满足我们在 Python 中想要绘制一些东西时的所有需求,但使用它创建一个漂亮的图表有时很耗时。嗯,有时我们可能想向老板展示一些东西,这样就可以有一些漂亮的互动情节。

有很多优秀的库可以做到这一点,Bokeh 就是其中之一。然而,学习如何使用这样的库可能也需要一些时间。其实已经有人替我们解决了这个问题。这里有一个叫Pandas-Bokeh的库,直接消费熊猫,用散景渲染数据。语法非常简单,我相信您很快就可以开始使用它了!

[## PatrikHlobil/Pandas-Bokeh

Pandas-Bokeh 为 Pandas、GeoPandas 和 Pyspark 数据帧提供了一个 Bokeh 绘图后端,类似于已经…

github.com](https://github.com/PatrikHlobil/Pandas-Bokeh)

条形图示例

让我用一个例子来演示这个库。

首先,我们需要使用pip安装库。

pip install pandas_bokeh

安装后,我们需要导入numpypandas,当然还有pandas_bokeh库。

import numpy as np
import pandas as pd
import pandas_bokeh

我想生成一些随机数据用于演示目的。假设我们有一个电子商务网站的数据集。该数据集包含三个类别从 2010 年到 2019 年的销售额。让我们使用 Numpy 生成这个数据集。

df = pd.DataFrame({
    'Year': np.arange(2010, 2020),
    'Category-A': np.random.uniform(9000, 15000, 10),
    'Category-B': np.random.uniform(9000, 15000, 10),
    'Category-C': np.random.uniform(9000, 15000, 10)
})

现在,我们的熊猫数据库里有了数据。在我们开始使用pandas_bokeh绘制数据之前,我们需要设置笔记本的输出,这将适用于 Jupyter/iPython 笔记本。稍后我会解释为什么我们需要这样做,因为pandas_bokeh支持其他输出位置。

pandas_bokeh.output_notebook()

好的。我们现在可以绘制数据帧。

df.plot_bokeh(
    kind='bar',
    x='Year',
    y=['Category-A', 'Category-B', 'Category-C'],
    xlabel='Category',
    ylabel='Annual Sales',
    title='Annual Sales by Category'
)

是不是比默认的matplotlib好看多了?让我们快速看一下参数:

  • 您想要绘制哪种类型的图表?目前,pandas_bokeh支持以下图表类型:折线图、点图、阶跃图、散点图、条形图、直方图、面积图、饼图和地图。
  • xy简单地传入熊猫数据帧的列名
  • xlabelylabelx 轴和 y 轴相对的标签
  • title图表的标题

所以,你已经看到了创造这样一个美丽的情节是多么容易。更重要的是,它是互动的。下面是 GitHub 官方回购的 GIF。

图片提供:https://github . com/PatrikHlobil/Pandas-Bokeh/raw/master/docs/Images/start image . gif

一些高级参数

当然,该库也支持许多高级参数,允许我们在必要时定制情节。

这是另一个使用相同数据集的示例,但使用折线图绘制数据。

df.plot_bokeh.line(
    x='Year', 
    y=['Category-A', 'Category-B', 'Category-C'],
    figsize=(900, 500),
    ylim=(5000, 20000),
    zooming=False,
    panning=False
)

请注意,这里我使用的df.plot_bokeh.line(...)相当于df.plot_bokeh(kind='line', ...)

  • figsize定义元组中绘图的大小(宽度,高度)
  • xlimylim分别定义 x 轴和 y 轴的默认范围。这里我只为 y 轴设置。
  • zooming启用/禁用缩放手势
  • panning启用/禁用平移手势

输出到 HTML

你记得我们已经把输出设置到笔记本了吗?

pandas_bokeh.output_file('chart.html')

除了 Jupyter 笔记本,我们还可以将输出设置为 HTML 文件。因此,图表将被保存并输出到一个可以持久化和分发的 HTML 文件中。

摘要

由 Kelly Sikkema 在 Unsplash 上拍摄的照片

在本文中,我演示了如何使用pandas_bokeh库,用极其简单的代码绘制出您的 Pandas 数据帧,但它是一个具有交互特性的漂亮演示。

事实证明,当您有许多特殊的渲染要求时,该库可能无法满足您的所有需求,但当您只想为数据集构建一个典型的图表时,它是一个优秀的库。

[## 通过我的推荐链接加入 Medium 克里斯托弗·陶

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

medium.com](https://medium.com/@qiuyujx/membership)

如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)

带有统计显著性注释的漂亮箱线图

原文:https://towardsdatascience.com/beautiful-boxplots-with-statistical-significance-annotation-e1b314927fc5?source=collection_archive---------10-----------------------

Python 中带重要性注记的箱线图超短教程

图由作者制作。

简介和动机

我总是记得自己阅读了一些很好的科学出版物,在这些出版物中,作者会创建一些带有统计注释的很好的箱线图。在大多数情况下,使用统计检验来确定不同组之间某一具体特征的平均值是否有统计学上的显著差异。

我现在已经成功地创建了一些定制的 python 代码来做这件事:生成集成了统计注释的漂亮的箱线图。在这篇短文中,我将展示如何用 Python 创建如此漂亮的方框图。

数据集

我们将使用 Iris 数据集,正如我们在我以前的所有帖子中所做的那样。数据集包含鸢尾属三个品种(鸢尾属 setosa 、鸢尾属 virginica 和鸢尾属 versicolor )的 50 个样本的四个特征(萼片和花瓣的长度和宽度)。数据集通常用于数据挖掘、分类和聚类示例以及测试算法。

作为参考,这里有三种花的照片:

图由作者制作。

对于这个简短的教程,我们将只使用 3 个类中的 2 ,即 setosaversicolor 类。这样做只是为了简单。

如果你想在交互式路线图和活跃的学习社区的支持下自学数据科学,看看这个资源:https://aigents.co/learn

Python 中的工作示例

步骤 1 :让加载数据并子选择所需的 2 个花类😗***

**from sklearn.datasets import load_iris
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np# Load the Iris dataset
X = load_iris().data
y = load_iris().target
feature_names = load_iris().feature_names
classes_names = load_iris().target_names# Use only 2 classes for this example
mask = y!=2
X,y  = X[mask,:], y[mask]# Get the remained class names
classes_names[[0,1]]
# array(['setosa', 'versicolor'], dtype='<U10')**

第二步 : 我们现在已经选择了 2 类的所有样品:setosa&versicolorflower class我们将把数据放入一个panda数据框架中,让我们的生活变得更轻松:****

**df = pd.DataFrame(X,columns=feature_names)
df['Group'] = [i for i in y]
df_long = pd.melt(df, 'Group', var_name='Feature', value_name='Value') # this is needed for the boxplots later ondf.head()**

第三步:让我们检查数据帧:

如我们所见,我们有 4 个特征,最后一列表示相应样本的组成员。

统计测试

第四步 : 现在是做统计测试的时候了。我们将使用一个双样本 t 检验(因为我们组是独立的)来检验 如果这四个特征(即萼片长度、萼片宽度、花瓣长度、花瓣宽度)中的任何一个的**平均值在统计上不同** 花****的两个(********

#* Statistical tests for differences in the features across groups
from scipy import stats
all_t = list()
all_p = list()
for case in range(len(feature_names)):
    sub_df = df_long[df_long.Feature == feature_names[case]]
    g1 = sub_df[sub_df['Group'] == 0]['Value'].values
    g2 = sub_df[sub_df['Group'] == 1]['Value'].values
    t, p = stats.ttest_ind(g1, g2)
    all_t.append(t)
    all_p.append(p)

为了进行我们刚刚使用的统计测试:

t, p = stats.ttest_ind(g1, g2)

这里,我们将 g1(第 1 组:setosa)的平均值与 g2(第 2 组:versicolor)的平均值进行比较,我们对所有 4 个特征进行比较(使用 for 循环)。

但是我们如何知道 g1(第 1 组:setosa)的平均值明显大于或小于 g2(第 2 组:versicolor)的平均值呢?

为此,我们需要查看一下 t 值。

print(all_t)
[-10.52098626754911, 9.454975848128596, -39.492719391538095, -34.08034154357719]print(feature_names)
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

释义:

  • 如果 t 值为 ( > 0),则 g1(第 1 组:setosa)的平均值明显大于 g2(第 2 组:versicolor)的平均值。
  • 如果 t 值为 ( < 0),则 g1(第 1 组:setosa)的平均值明显小于 g2(第 2 组:versicolor)的平均值

提醒 : feature_names = ['萼片长(cm)','萼片宽(cm)','花瓣长(cm)','花瓣宽(cm)']。

  • 我们可以得出结论:只有 g1(杂色)的萼片宽度的平均值在统计学上大于 g2(杂色)的萼片宽度的平均值。

第五步 : 检查 t 检验结果

print(np.count_nonzero(np.array(feature_names)[np.array(all_p) < 0.05]))
# 4

解释:我们可以看到在 setosaversicolor 类之间所有 4 个特征在统计上有显著差异。

第六步:魔术来了。让我们创建一些漂亮的 箱线图并用估计统计 显著性对它们进行注释。

# renaming so that class 0 will appear as setosa and class 1 as versicolor
df_long.loc[df_long.Group==0, 'Group'] = classes_names[0]
df_long.loc[df_long.Group==1, 'Group'] = classes_names[1]# Boxplots
fig, axes = plt.subplots(2,2, figsize=(14,10), dpi=100)
axes = axes.flatten()for idx, feature in enumerate(feature_names):
    ax = sns.boxplot(x=”Feature”, hue=”Group”, y=”Value”, data = df_long[df_long.Feature == feature], linewidth=2, showmeans=True, meanprops={“marker”:”*”,”markerfacecolor”:”white”, “markeredgecolor”:”black”}, ax=axes[idx])
    #* tick params
    axes[idx].set_xticklabels([str(feature)], rotation=0)
    axes[idx].set(xlabel=None)
    axes[idx].set(ylabel=None)
    axes[idx].grid(alpha=0.5)
    axes[idx].legend(loc=”lower right”, prop={‘size’: 11})

    #*set edge color = black
    for b in range(len(ax.artists)):
        ax.artists[b].set_edgecolor(‘black’)
        ax.artists[b].set_alpha(0.8)

    #* statistical tests
    x1, x2 = -0.20, 0.20
    y, h, col = df_long[df_long.Feature == feature][“Value”].max()+1, 2, ‘k’
    axes[idx].plot([x1, x1, x2, x2], [y, y+h, y+h, y], lw=1.5, c=col)
    axes[idx].text((x1+x2)*.5, y+h, “statistically significant”, ha=’center’, va=’bottom’, color=col)fig.suptitle("Significant feature differences between setosa and versicolor classes/groups", size=14, y=0.93)
plt.show()

图由作者制作。

结论

从统计测试中我们可以看出,我们可以得出结论:只有第 1 组(setosa)的萼片宽度的平均值在统计上大于第 2 组(versicolor)的萼片宽度的平均值。

另一方面,组*的萼片长度、花瓣长度和花瓣宽度** 的平均值比杂色组的平均值***

这些观察结果也可以通过观察箱线图来验证。

那都是乡亲们!希望你喜欢这篇文章!

敬请关注并支持这一努力

如果你喜欢这篇文章,并且觉得它有用,那么关注我就可以看到我所有的新帖子。**

有问题吗?把它们作为评论贴出来,我会尽快回复。

最新帖子

*** [## 时间序列预测:用脸书的先知模型预测股票价格

使用可从《先知脸书》公开获得的预测模型预测股票价格

towardsdatascience.com](/time-series-forecasting-predicting-stock-prices-using-facebooks-prophet-model-9ee1657132b5) [## 用新冠肺炎假设的例子解释 ROC 曲线:二分类和多分类…

在这篇文章中,我清楚地解释了什么是 ROC 曲线以及如何阅读它。我用一个新冠肺炎的例子来说明我的观点,我…

towardsdatascience.com](/roc-curve-explained-using-a-covid-19-hypothetical-example-binary-multi-class-classification-bab188ea869c) [## 支持向量机(SVM)解释清楚:分类问题的 python 教程…

在这篇文章中,我解释了支持向量机的核心,为什么以及如何使用它们。此外,我还展示了如何绘制支持…

towardsdatascience.com](/support-vector-machines-svm-clearly-explained-a-python-tutorial-for-classification-problems-29c539f3ad8) [## PCA 清楚地解释了——如何、何时、为什么使用它以及特性的重要性:Python 指南

在这篇文章中,我解释了什么是 PCA,何时以及为什么使用它,以及如何使用 scikit-learn 在 Python 中实现它。还有…

towardsdatascience.com](/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e) [## 关于 Python 中的最小-最大规范化,您需要知道的一切

在这篇文章中,我将解释什么是最小-最大缩放,什么时候使用它,以及如何使用 scikit 在 Python 中实现它

towardsdatascience.com](/everything-you-need-to-know-about-min-max-normalization-in-python-b79592732b79) [## Scikit-Learn 的标准定标器如何工作

在这篇文章中,我将解释为什么以及如何使用 scikit-learn 应用标准化

towardsdatascience.com](/how-and-why-to-standardize-your-data-996926c2c832)

和我联系

  • 领英:https://www.linkedin.com/in/serafeim-loukas/
  • 研究之门:https://www.researchgate.net/profile/Serafeim_Loukas
  • ****EPFL 简介:【https://people.epfl.ch/serafeim.loukas】T4
  • 堆栈 溢出:https://stackoverflow.com/users/5025009/seralouk***

美丽的代码

原文:https://towardsdatascience.com/beautiful-code-ad8a0c6b19?source=collection_archive---------16-----------------------

像电脑程序一样枯燥的东西能叫艺术吗?绝对的!

美有很多来源。谈到软件开发,美是由架构连贯性 e 赋予的,它们与应用于解决问题的 【功能精确性】 以及 创造力 携手并进。同样地, 编码风格 是代码优雅的一个组成部分,并且在改进开发团队的交流时不应该被低估。

让我们更详细地探索代码之美的概念,以及到底是什么让编程成为🅐🅡🅣!

在简单中寻找美

我最近读了《美丽的代码选集,《我从未写过的最美的代码,作者是乔恩·本特利,它基于一个首要原则,即“少即是多”,即一些明星开发人员一次又一次地进行重构,以精炼他们的代码并消除冗余,因此它尽可能简洁、易懂和简洁。从书中挑选出来的一些表达这种技能的格言如下:**

***📌 **A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.**
— Saint-Exupéry📌 **The cheapest, fastest, and most reliable components of a computer system are those that aren’t there.**
— Bell📌 **If I had more time, I would have written you a shorter letter.**
— Pascal📌 **Simplicity does not precede complexity, but follows it.**
— Perlis***

换句话说,这是对简单的呼唤。

每一行代码都是必须调试、阅读和理解的代码,以后还需要支持。这是一种固有的成本!所以在保留功能的同时减少代码是一种高尚的努力。如果一个方法有 10 条语句,但是我们把它减到 5 条,问题的可能性减半,因为它出错、过于复杂或有问题的地方减少了。 源代码是负债,不是资产 !下次您使用 LOC(代码行数)作为生产力度量时,请考虑这一点!

三个相关的哲学是 YAGNI,干燥和亲吻。 你不需要它 暗示代码需要一个存在的理由,否则它必须被重构或删除。 不要重复自己 提出每一段代码在系统内必须有一个单一的、明确的目的和表示。最后, 保持简单愚蠢 ,很有描述性:保持事情简单!

讽刺的是,简单是一个复杂的主题!

在软件中,最漂亮的代码、最漂亮的功能和最漂亮的程序有时根本不存在。

质量设计是一个项目的灵魂

光是听“bug”这个词就让每个开发人员畏缩不前。人们普遍认为,好的程序员是那些写出无错误代码的人。尽管一个没有错误的程序是必须的,但是没有错误的代码编写不是必须的。我这么说的意思是,一些开发人员甚至在程序编译或执行之前就努力写出无错误的代码,更多地关注功能而不是设计。

在开发过程中忽视可维护性,为了功能性而忽视模式/标准,是一个灾难的处方(也是一个昂贵的处方)。另一个问题是程序员会在错误的地方和错误的时间花太多的时间担心效率;过早优化相当于打开了工程上的潘多拉魔盒。

好的设计就是让其他设计师觉得自己是白痴,因为这个想法不是他们的。

每个专业的软件开发人员都会写出有用的代码,但是在有用的代码和经得起时间考验的代码之间还是有一线希望的。一个可靠的设计保证了修复 bug 将是一件轻而易举的事情,因为 bug 将会出现在它们应该出现的地方!换句话说,当架构没有受到损害时,解决 bug 的成本更低,并且不会对技术债务产生太大影响。

所有的艺术都从一张空白的画布开始

开发人员将他们的想法转化为有形的东西的能力,就是创造性的定义。屏幕是一块空白的画布,等待着被代码填充并产生一个独特的解决方案——如果工作不是独特的,它将只是简单的“复制和粘贴”!没有两个程序员会写出完全相同的代码,即使他们的最终软件从表面上看是一样的。作为程序员,每个人都有自己声音的表达方式。这本身就很了不起!以我的经验来看,理解另一个开发者的代码,就像进入他们的思维,从他们的角度看世界。****

能够编码的兴奋是很难解释的。不仅仅是一行行的代码…我们可以想象我们慢慢构建的系统,当数据在其中流动时,它就变得真实了。这在智力上和情感上都是有益的,因为看到一件事情从构思到完成是一种成就。不管多小多大!

作为结束语,在我进入下一节之前,这里有一段摘自《计算机编程的艺术》系列的作者 Donald Knuth (对于非程序员来说,它就像是计算机科学的圣经)的摘录,当他被要求证明在书名中选择单词 art 的合理性时:

计算机编程是一门艺术,因为它将积累的知识应用于世界,因为它需要技巧和独创性,尤其是因为它产生美的物体。

算法的辉煌是终极的复杂

算法是使有效编程成为可能的配方。它们是编程的支柱,因为它们以系统的方式描述了解决问题的所有步骤。虽然逻辑和分析技能是左脑活动,但解决问题是使用我们右脑‘精神肌肉’的创造性过程。有效解决问题的秘诀是掌握复杂性,正如我们前面讨论的,复杂性会对我们的程序产生负面影响。

我设计、回顾或研究过的所有最好的算法都有一个共同点:它们依靠美好的想法来更有效地处理计算任务,同时避免不必要的细节和复杂性。举几个例子来说,对令人敬畏的代码库做出贡献的最基本的算法内部工作是:简化的布尔代数、创造性的组合学技术、数据结构的明智选择、正则表达式的简洁使用、良好的资源利用和对坚实原则的遵从。

这里有一个有趣的悖论,这使得算法的创建成为一项复杂的任务:

创造力没有算法——安迪·哈格里夫斯

编码风格很重要

到目前为止,我们研究了好的代码需要简单和良好的设计。我现在将转向编程的美学方面:代码布局。格式良好的代码的视觉外观与其质量密切相关,许多以自己的工作为荣的程序员从改进工作中获得极大的满足感,因为他们意识到程序员是因为他们的风格和纪律而被记住的,而很少是因为代码本身。

编写代码不仅是为了让机器执行,也是为了让其他程序员在试图检查、扩展、纠正、重构或调试代码之前阅读和破译。因此,代码的逻辑结构的准确和一致的表示是必不可少的。

缩进和空白空间的使用是这里的关键。类似地,最好的布局方案在代码修改下也能保持良好:修改一行代码不应该需要修改其他几行。也就是说,程序员交流的圣杯是自我记录代码,这意味着:足够的注释,有意义的命名约定,使用小的、容易测试的、纯粹的函数等等。

好的代码是它自己最好的文档

所以,漂亮的代码是清晰的,易于阅读和理解。它有一个平衡。它的结构、形状和建筑揭示了它的意图。每个部分都相对较小,且用途单一。这就像一个马赛克:所有的小代码片段完美地组合在一起,但同时当一个元素需要改变时,它们很容易分开!

资源

  • 里奇·希基的必看之作:简单变得容易。
  • 唐纳德·克努特的经典之作:作为艺术的计算机编程。
  • 来自实用主义程序员:计算机编程的艺术。

收场白

每次我们写代码,都是在走一条通向未知解的非确定性的道路;一个从未被创造过的东西!这是一次自我发现的旅程,也是我们智慧的表达。这就是到底什么是艺术!**

我们不是那种创造视觉愉悦供他人欣赏的艺术家。但是当我们爱一样东西时,我们会把美融入其中!

感谢阅读!

*我经常在媒体上写关于领导力、技术&的数据——如果你想阅读我未来的帖子,请*‘关注’我

R 中美丽的相关图——一种新方法

原文:https://towardsdatascience.com/beautiful-correlation-plots-in-r-a-new-approach-d3b93d9c77be?source=collection_archive---------9-----------------------

使用 plotly 以直观、互动的方式理解相关矩阵。

克林特·王茂林在 Unsplash 上拍摄的照片

每个从事数据工作的人都知道,美观和解释性的可视化是关键。毕竟,用图表讲故事比用普通的表格要容易得多。这在您创建报告和仪表板时尤其重要,这些报告和仪表板的目的是让您的用户和客户快速浏览有时非常复杂和庞大的数据集。

一种以解释性方式可视化的数据类型是相关矩阵。在这篇文章中,我们将看看如何使用 R 和 plotly 库把一个相关矩阵转换成一个漂亮的、交互式的和非常描述性的图表。

更新(2020-10-04):我不得不用静态图像替换一些链接图表,因为它们在手机上显示不正确。

1.介绍

数据

在我们的示例中,我们将使用 mtcars 数据集来计算 6 个变量之间的相关性。

data <- mtcars[, c(1, 3:7)]
corrdata <- cor(data)

这给了我们将要使用的相关矩阵。

mtcars 相关矩阵(图片由作者提供)

现在,虽然所有的信息都在那里,但一次消化所有的信息并不是特别容易。输入图表,特别是热图。

基本图表

作为起点,base R 为我们提供了 heatmap()函数,让我们至少可以更好地可视化数据。

base R 热图(图片由作者提供)

虽然这是朝着正确方向迈出的第一步,但是这个图表仍然不是非常具有描述性,最重要的是,它不是交互式的!理想情况下,我们希望将我们的最终产品包含在一个漂亮闪亮的仪表板中,并使我们的用户和客户能够与之交互。

Plotly 热图

Plotly.js 是一个 JavaScript 图形库,构建在 d3.js 和 stack.gl 之上,允许用户轻松创建交互式图表。它是免费和开源的,幸运的是,我们有一个 R 实现!

plotly 热图(图片由作者提供)

这又是一个进步。我们的相关性矩阵现在显示为一个交互式图表,并且我们有一个颜色条来指示相关性的强度。

然而,当你快速浏览图表时,会有什么发现呢?你能立即识别最强和最弱的相关性吗?大概不会!并且还显示了许多不必要的数据。根据定义,相关矩阵是对称的,因此每个相关矩阵包含两次。此外,变量与其自身的相关性始终为 1,因此我们的图表中没有必要出现这种情况。

改进的 plotly 热图

现在看看下面的图表,试着回答同样的问题。

改进的 plotly 热图(图片由作者提供)

好多了!图表是干净的,我们可以立即发现最强和最弱的相关性,所有不必要的数据都被删除,它仍然是交互式的,并准备好作为一个美丽的仪表板的一部分显示!

为了实现这一点,我们使用了散点图,并使方块的大小取决于相关性的绝对值。

你如何自己创建这样一个图表(用一点努力)?我们来看看吧!

2.履行

我们需要做的第一件事是转换我们的数据。为了创建适合我们需要的散点图,我们只需要一个网格。对于相关矩阵,x 和 y 值将对应于变量名,但我们真正需要的是等间距的数值来创建网格。我们的转换将相关性矩阵转换成一个包含 3 列的数据框:网格的 x 和 y 坐标以及相关的相关性。

#Store our variable names for later use
x_labels <- colnames(corrdata)
y_labels <- rownames(corrdata)#Change the variable names to numeric for the grid
colnames(corrdata) <- 1:ncol(corrdata)
rownames(corrdata) <- nrow(corrdata):1#Melt the data into the desired format
plotdata <- melt(corrdata)

您可能想知道为什么行名的数值在上面的代码中是颠倒的。这是为了确保生成的图具有从左上角到右下角的相关图的主对角线(不像上面的 base R 和 base plotly 示例)。

结果,我们得到一个类似这样的数据帧:

转换后的相关矩阵(图片由作者提供)

我们可以用下面的代码绘制它:

fig <- plot_ly(data = plotdata, width = 500, height = 500)
fig <- fig %>% add_trace(x = ~Var2, y = ~Var1, type = “scatter”,   mode = “markers”, color = ~value, symbol = I(“square”))

相关矩阵的初始散点图(图片由作者提供)

这是一个好的开始,我们已经正确地设置了网格,我们的标记也根据数据的相关性进行了着色。不可否认,我们真的不能正确地看到它们,它们都有相同的大小。我们接下来会解决这个问题。

#Adding the size variable & scaling it
plotdata$size <-(abs(plotdata$value))
scaling <- 500 / ncol(corrdata) / 2
plotdata$size <- plotdata$size * scaling

首先,我们定义一个大小变量作为相关性的绝对值。为了正确地确定方块的大小,我们需要将它们放大,否则我们只会得到小点,并不能告诉我们太多。之后,我们可以将尺寸添加到标记中。

fig <- plot_ly(data = plotdata, width = 500, height = 500)
fig <- fig %>% add_trace(x = ~Var2, y = ~Var1, type = "scatter", mode = "markers", color = ~value, marker = list(size = ~size, opacity = 1), symbol = I("square"))

散点图,带有按绝对相关性缩放的缩放标记(图片由作者提供)

再靠近一步!基本功能现在已经存在,我们的正方形与相关性一起正确缩放,并且与着色一起使我们能够一眼识别高/低相关性对。

接下来我们将执行一些清理工作。我们将正确命名我们的变量,删除所有网格线,并删除轴标题。为此,我们将设置自定义轴列表。我们也将中心色条。

xAx1 <- list(showgrid = FALSE,
 showline = FALSE,
 zeroline = FALSE,
 tickvals = colnames(corrdata),
 ticktext = x_labels,
 title = FALSE)yAx1 <- list(autoaxis = FALSE,
 showgrid = FALSE,
 showline = FALSE,
 zeroline = FALSE,
 tickvals = rownames(corrdata),
 ticktext = y_labels,
 title = FALSE)fig <- plot_ly(data = plotdata, width = 500, height = 500)
fig <- fig %>% add_trace(x = ~Var2, y = ~Var1, type = “scatter”, mode = “markers”, color = ~value, marker = list(size = ~size, opacity = 1), symbol = I(“square”))fig <- fig %>% layout(xaxis = xAx1, yaxis = yAx1)
fig <- fig %>% colorbar(title = “”, limits = c(-1,1), x = 1.1, y = 0.75)

初始清理后的绘图(图片由作者提供)

我们之前已经提到过,由于相关矩阵是对称的,所以在相关矩阵中显示了大量重复和不必要的数据。因此,我们可以在绘图中删除主对角线以上并包括主对角线的所有条目(因为主对角线中的所有条目根据定义都是 1)。最简单的方法是在应用变换之前,将原始相关矩阵中的这些值设置为 NA。因为这将导致图表的第一行和最后一列为空,所以我们也可以删除它们。

#do this before the transformation!
corrdata[upper.tri(corrdata, diag = TRUE)] <- NA
corrdata <- corrdata[-1, -ncol(corrdata)]

再次绘制我们的图表会产生以下结果:

移除值后的绘图(图片由作者提供)

快到了!最后一步是添加网格线,给我们的图一个漂亮的背景,并修正当鼠标悬停在方格上时显示的信息。

为了添加网格,我们将在绘图中添加第二条轨迹,这样我们就能够有第二组 x 轴和 y 轴。我们将使这条轨迹不可见,这样就不会有任何东西干扰我们的相关平方。由于我们使用单位值来放置初始网格,我们需要将它们移动 0.5 来创建网格线。我们还需要确保我们的轴绘制在相同的范围内,否则一切都会变得混乱。这听起来很复杂,但确实很简单。

因为我们已经走了这么远,下面是产生最终情节的完整代码。

最终相关图(图片由作者提供)

3.结论

在对如何创建显示相关性的更漂亮的图表进行了冗长的描述之后,我们终于得到了我们想要的结果。希望这篇文章能让你创造出令人惊奇的、互动的情节,快速洞察相互关系。

请务必让我知道,如果你有任何反馈或建议,以改善我在这篇文章中所描述的!

奖金

对于那些感兴趣的人来说,我已经把包括更多特性的完整代码作为一个 R 包提供,叫做

新增功能包括:

  • 根据地块大小自动调整比例
  • 颜色选项包括十六进制颜色、蓝色和绿色
  • 自动格式化背景、字体和网格,以适应不同的闪亮主题
  • 相关性随时间变化的动画(开发中)

此外,一定要看看我的帖子关于 3 个简单的技巧来改善你的图表,以进一步增强我们在这里所涵盖的内容!

用 Matplotlib 定制漂亮的彩色地图

原文:https://towardsdatascience.com/beautiful-custom-colormaps-with-matplotlib-5bab3d1f0e72?source=collection_archive---------11-----------------------

使用自定义的色彩映射表升级您的图表游戏,以匹配您的主题。

如果你的 Matplotlib 图表需要一个色彩映射表,而你没有使用一个内置的映射表,你可能会有一段不好的时间。我曾经害怕用 Python 编辑色彩映射表。我查看的每个帮助线程都显示了不同的方法,没有一个完全符合我的情况。这总是令人失望,因为色彩映射表可以极大地改变你用数据可视化发送的信息,甚至可以使你的图表无法使用。

不相信我?看看这个。

每个可视化显示相同的数据(澳大利亚地方政府区域的估计人口),但具有不同的色彩映射表。数据是连续的和积极的,这是通过仔细检查每个图例显示的。然而,彩色地图讲述了一个不同的故事,有点像金发姑娘的故事:

  1. 第一个图表使用顺序色彩映射表,其中亮度值始终单调变化(增加或减少)。如果观想中的细节很重要,那么顺序可能不是你的最佳选择,因为很难比较具有相似值的区域。
  2. 第二个图表使用了发散的颜色图。颜色越多,就越容易分辨出相似值之间的差异,但这也向观察者暗示了数据是以正常基线为中心的,比如零。如果我们对平均值的数据进行归一化,那么这个尺度是合适的,但是因为我们只是显示了一系列正值,所以它在这里不适用。
  3. 第三张图表恰到好处。这类似于顺序贴图,因为颜色在整个过程中逐渐变化,一端清楚地指示较高的值,另一端指示较低的值。然而,这张地图包括更多的颜色,这使得观众更容易比较小的差异。

这些只是一些你可以使用的色彩映射表的例子,更多细节和选项,请查看 Matplotlib 的指南。

如果你试图让一个颜色图适合一个主题,那么设计和创建这个颜色图会变得更加困难。例如,嵌入在仪表板或网站中的可视化,带有现有的配色方案。为一个完全专业的最终产品付出额外的努力是值得的,本指南将帮助你实现这一目标。

使用 Matplotlib 内置的色彩映射表

让我们创建一个测试图像,并关闭轴记号,使它看起来更好一些。

默认 matplotlib 色彩映射表。

现在让我们编辑图像,并测试 4 种不同的内置 Matplotlib 颜色映射。

四个内置 matplotlib 彩色地图。

创建您自己的色彩映射表

如果 Matplotlib 默认色彩映射表不符合您的需要,您可以随时创建自己的。在本教程中,我假设你有一些想在色彩映射表中使用的颜色。如果没有,向下滚动到底部的一些资源,以帮助选择你的颜色。

在不同的颜色格式之间转换

如果你有一套基于品牌或网站主题的特定颜色,它们很可能是十六进制格式的。首先,让我们定义一些函数,将十六进制转换为 RGB,将 RGB 转换为十进制(每个 RBG 通道的值在 0 到 1 之间)。

下面显示了我的十六进制颜色,以及它们的 RGB 等价物(我用来生成这个图像的代码是这里是)。

创建连续的色彩映射表

让我们创建一个包含以上所有颜色的连续色图。我们将使用名为 LinearSegmentedColormap 的 matplotlib.colors 函数。这个函数接受一个包含红色、绿色和蓝色条目的字典。每个条目应该是一个由 xy0y1 元组组成的列表,形成一个表中的行。所以,如果你想让红色在下半部分从 0 增加到 1,绿色在中间部分增加到 1,蓝色在上半部分增加到 1。然后,您可以使用:

cdict = {'red':   [(0.0,  0.0, 0.0),
                   (0.5,  1.0, 1.0),
                   (1.0,  1.0, 1.0)],

         'green': [(0.0,  0.0, 0.0),
                   (0.25, 0.0, 0.0),
                   (0.75, 1.0, 1.0),
                   (1.0,  1.0, 1.0)],

         'blue':  [(0.0,  0.0, 0.0),
                   (0.5,  0.0, 0.0),
                   (1.0,  1.0, 1.0)]}

迷茫?我也是。所以我写了一些代码(如下)来包装这个函数,让它更容易管理。下面的代码可以用来在列表中任意数量的十六进制颜色之间进行映射,它使用我们之前定义的函数将十六进制转换为十进制。

通过提供一个从 0 到 1 的浮动列表,我们还可以将颜色映射到颜色条上的特定位置,以便扩展地图某些部分的表示。

创建发散的色彩映射表

我们也可以使用这个代码来创建一个发散的颜色图,如果我们的数据要显示在某个中点附近,比如零,这是很有用的。如果数据不是以中点为中心,例如范围从-2 到 5,我们需要将色图的中心移动到数据的中点。下面的代码显示了如何通过使用 TwoSlopeNorm 创建一个范数来实现这一点,然后在 imshow 中使用该范数在映射到颜色之前将数据缩放到[0,1]范围。

为色彩图选择正确的颜色

请记住,虽然我不会在这篇文章中详细介绍,但你对颜色的选择不仅仅是美学上的,还有一整个领域致力于理解不同颜色和组合对人类理解的影响。还有一个要考虑的问题是色盲的人会如何看待你的色彩映射表。选择颜色时,你应该考虑这两个因素。

如果你在选择颜色时需要一些灵感,这里有一些我觉得有用的来源。

  • 酷派
    酷派是一款拥有如此多功能的神奇应用。出于创建连续色阶的目的,我更喜欢他们的颜色渐变生成服务,它有大量漂亮的调色板,可以很好地过渡到连续色阶,并可以调整以满足您的需求。
  • Gregor Aisch 的 Chroma
    Chroma 对优化你的调色板很有用。它可能有一点点问题,但它有助于您获得两种或更多种颜色,并生成中间值的完整范围。它还能告诉您您的电子秤是否色盲安全。
  • W3schools 调色板这有一些不错的调色板示例。W3 还提供了其他免费的服务来选择基于颜色理论的调色板,在不同的颜色格式(如 Hex,RGB 等)之间转换,以及许多其他有用的工具。
  • Hayk An 的色标生成器
    我在上一个项目中偶然发现了这个色标生成器。这是一个很好的资源,您可以在其中生成随机的、视觉上令人愉悦的色阶,然后调整它们的属性,包括添加更大范围的颜色以及调整饱和度和亮度等。

查看我的 GitHub 获取本教程的代码。

Beautiful-Head:追踪名降的演变及其在博客中的关系

原文:https://towardsdatascience.com/beautiful-head-tracing-the-evolution-and-associations-of-name-drops-in-blogs-c6764b3504ee?source=collection_archive---------36-----------------------

一种自然语言处理和网络科学的方法来可视化信息流中的命名人的动态(演示@beautiful-head.appspot.com

查看所有演示@【beautiful-head.appspot.com

介绍

指名道姓——利用他人的名字来维护自己的表达的丑陋、可悲的行为——已经成为一种指责,一种文化机制,立即将他人的表达贬低为仅仅是一种令人讨厌的借口。面对不断被点名的人,我们甚至可以假装不知道,做一个游戏。我们意识到,名字可能会被滥用。我们在正常的谈话中,在社交媒体上,在各种各样的作品中体验到这一点——无数的名字,从巨著到对作者来说有着神圣地位的默默无闻的人物。尽管韦氏词典将其定义为“经研究但看似随意提及的 杰出的 人物,以此来给其他人留下深刻印象”,我们可以想象,贬低名字可以延伸到任何名字,甚至是不那么杰出的名字,这对于我们的表达有某种实用功能,无论是增加我们的可信度、可联系性还是减少可能的批评途径。

然而,这个项目从这种可耻的对留名的指责转向了一个更宽容的角度,即留名可以被用来告诉我们一个作者随着时间的演变。在开始我如何操作这种方法之前,我先讨论激发这种分析的两个理论概念。即,

  1. 在动态文本流(即随时间变化的文本,如博客帖子、推文等)中(专有名词、命名实体,即人)的命名。)是一种独特的“向观众传达信息的手势”。(下面我会具体讨论我这么说的意思。)
  2. 所有的思想都是通过他人来思考的,因此名字可以被抽象为控制一个人知识领域的媒介。(这来自概念理论,即技术上没有真正的“原创”这种东西,而是一切都是混搭。)

这两个理论概念,再加上在公共环境中学习,可以被用来追踪一个作者的作品,基于作品中演变和形成关系的人名地址。虽然它可以扩展和测试各种各样的应用,这个项目试图展示我们如何去创造和说明这样一个进化和关联的过程。

然后我将展示 3 个视图——一个定制的动态网络动画,一个总结动态网络的交互式可视化,以及一个静态显示域名滴之间关联的矩阵。我将以一些评论来结束本文,这些评论是关于可视化如何为作者的作品提供一个(宏大的)“信息姿态”来提前告知,从而支持读者的解释以及增强作者的自我展示能力。最后,我展示了可视化信息流的额外演示——尽管它们偏离了这个项目的细节。

目录:

1 —动机(概述这种方法背后的理论的非正式文章——不感兴趣的读者可以跳过这一部分,可视化仍然有意义,尽管它们缺乏紧迫性。)

2 —操作化(数据收集和网络结构)

3-视图 X:动态网络动画

4-查看关联的 Y: A(汇总)图

5-视图 Z:名称下拉矩阵

6 —备注

7 —附加内容和其他演示

可视化演示:

查看 X 演示:奥斯汀·克莱恩的动态网络动画

查看 Y 演示:奥斯丁·克莱恩的关联图

查看 Z 演示:奥斯汀·克莱恩的姓名下拉矩阵

*用作数据的信息流来自奥斯汀·克莱恩的博客——我在动机部分解释了为什么我在这个项目中使用他的帖子。

定义

  • 信息流: 随着时间的推移不断到达的一系列(相关)文档(文本)(新闻、博客、twitter 等。)
  • 指名-降将: 指称一个被指名的人
  • 动态网络: 随时间变化的网络(即由节点和边组成的图)

1 —动机

名称删除作为唯一的信息

Thorn-R. Kray 在他的论文中提到了一个“临界点”,即“对权威名字的合法引用……变成了令人讨厌的 冒名顶替 ”的现象。(在他的语境中,他关注的是学术话语中的权威名称,但我们可以把讨论延伸到公共话语中,损失不大。)这意味着,域名删除(引用)机制在某个阈值处变得合适。Kray 进一步承认,很难将留名简单地归结为对权威的虚假诉求——这种行为有一些更特殊的地方,需要我们将其视为一种社会实践,而不是一种修辞逻辑手段。

他提到了高夫曼的经典研究日常生活中自我的呈现:

“当一个人出现在其他人面前时,他们通常会试图获取关于他的信息或利用已经拥有的关于他的信息。[……]关于个人的信息有助于确定情况,使他人能够预先知道他对他们的期望和他们可能对他的期望”(Goffman 1956)

在这种社会理论下,留名基本上仍然是“向观众表达的一种姿态”,但不一定(仅仅)包含“留下深刻印象”的险恶动机。抛名是一种礼貌的社交策略——一种提前向观众提供信息、设定期望的方式,是论文前的摘要。

(然而,这也是一场赌博——正如高夫曼所说的互动中的大多数其他台词——可以在对方心中产生各种各样的印象[“他很聪明!”,“哇,他自命不凡”,“但他读过德勒兹吗?”],导致的后果包括信任感、与人交往的能力,或者因输掉赌注而感到彻底的尴尬和羞愧。)

将指名道姓视为对观众的手势,意在提前告知(而不仅仅是为了留下印象或娱乐)给了我们最初的动机:如果在我们的分析中,我们赋予指名道姓一种独特的信息现象的功能,与其他文本现象相比,我们会对作者有什么样的看法?

名字滴作为一种媒介,随着时间的推移而构建

Kray 引入了一种信任/怀疑的紧张关系。一方面,无论是否为了给人留下深刻印象,指名道姓都是期望建立信誉,然而矛盾的是,有一种潜在的怀疑,认为一个人指名道姓只是为了建立信誉。奇怪的是,如果有人认为这种对可信度的呼吁是为了掩盖不可信的东西,那么可信度的条件就会引起怀疑……这种矛盾的禁令来自科学话语本身的结构:

“……年轻的科学家必须学会什么时候接受共识的权威,什么时候抵制它。”(奥灵顿,1977 年)

“这样的要求在本质上是自相矛盾的。新手必须学会遵循传统,同时对它保持足够的怀疑。每一次未能达到与之相关的期望都会立即被注意到。假笑和奇怪的微笑会引起一种不充分的感觉,这是对学徒错误的惩罚。然而,这种残忍似乎是一种不可避免的邪恶。要求学生“独立思考”,同时又要求熟悉一种高度排他性的话语,这种话语本应指导学生“如何思考”,这是一种迂回的双重约束
—克雷

我们可以再一次将科学的形象延伸到更广泛的公众中。从学术界到推特回复中出现的游击战,我们被“独立思考”的社会指令轰炸,‘批判性思考!’同时期望展示我们的凭证(通常以通过说出我们在想谁的形式出现)。尽管这可能有些自相矛盾,但这同时也承认了为什么我们无法克制自己不去取名字:

"..放弃名字是一种无法避免的做法,因为它将我们与我们学科历史的知识遗产联系起来。就像任何好的仪式一样,把过去的想法转化为现在的想法,这就是抛名字的作用。”
— Kray

艾伦·雅各布斯在他为普通读者写的书《如何思考》中更进一步,声称“独立思考是不可能的”。虽然克雷最终框定了一种不可避免地存在且必须通过经验来导航的信任-怀疑主义紧张关系,但雅各布斯将这一概念引向了其逻辑结论——命令“为自己着想”通常意味着“与我想通的人一起思考,而不是与你想通的人一起思考”。对于雅各布斯来说,认为有一种“思想”会不受智力联想的影响而来到我们身边是愚蠢的。为了更进一步,雅各布斯还大胆地声称,为自己思考不是不可能的,而是不可取的。

脱离他人独立思考是不可能的,即使可能,也是不可取的。思考是必然的、彻底的、奇妙的社会性。你所想的一切都是对别人所想所说的回应。当人们称赞某人“独立思考”时,他们通常意味着“不再听起来像我不喜欢的人,而开始听起来更像我喜欢的人。”
—艾伦·雅各布斯

思考是一种社会行为,不管是对死去的人还是对坐在我们身边的人——没有人能保证(而且不断有证据表明这一事实),我们甚至能在一个与联想网络脱节的想法中找到乐趣。当然,这并没有直接转化为姓名丢弃的现象,但它确实开辟了将姓名视为定向媒介的可能性——也就是说,这些媒介构建和塑造其内容,而不仅仅是使其可见。

作为媒介,名字可以成为动态网络的“锚”——随着时间的推移,稳定我们知识领域中的各种概念和主题,以及构建我们如何感知和呈现它们。本质上,这给了我们第二个动机。大多数网络分析都试图不偏爱一种文本现象或引入层次结构(让数据说话而不受理论干扰的更大概念的一部分),但如果名称确实有特权(作为管理所有其他概念的媒介),则网络分析技术很大程度上依赖于计数、聚合、求和等。可能不会暴露他们的特殊身份。

因此,将名字滴概念化为锚定概念的媒介,加上高夫曼将名字暗示为独特的信息社交策略,为这个项目提供了潜在的驱动力——这是尝试将动态信息网络可视化,将名字滴作为上述的媒介。

作为偷窃的好方式的抛名(像一个艺术家)

虽然我们有自己的动机,但我想用这一部分来提醒大家,虽然这是一种“赞美降名”的项目,但我并没有排除错误或粗俗的使用给我们带来烦恼的可能性。我确实同意 Klay 的评估,当我们给一些东西贴上抛头露面的标签而不仅仅是引用的时候,就有一个“引爆点”。然而,我对我们在这一点上的决定提出质疑——具体而言,指控某人诽谤似乎与诽谤的实际行为具有同等的险恶用心。

看起来,区分令人讨厌的留名现象和不那么令人讨厌的事情的真正原因是我们对留名者阴暗而深刻的意图的判断——他们是在用这个名字来打动我们,还是更像是向他们正在思考的思想家致敬?事实上,除去任何庸俗的渴望来打动自己非凡的外表,但保持或多或少相同的机制(即暗指别人,为你的表达提供某种功能),降名的行为被减少到比平庸的“表达样板”多一点——我们可以称之为“给予信任”、“引用”或“引用来源”。然而,它是我们乐于在社会中容忍的样板,因为它提供了安全,避免了更深不可测的剽窃。

因此,我感觉到了一种同样矛盾的紧张关系,即在社交中,放弃名字是一种耻辱..一方面,我们被要求提交参考文献以保护自己免受剽窃的犯罪,另一方面,有一种“提交我们自己的想法”的溢出压力,以及“抛头露面与智力不安全感相关联”的恐惧。事实上,如果艾伦·雅各布斯是对的,为自己着想是不可能的,也是不可取的——我倾向于认为他是对的——这个问题可以从根本上转变为‘为什么我们不把的名字写得更像’(在一定的抄袭和知识产权概念下)。

勒撒姆在他辉煌的散文 影响力的狂喜中,大胆地承认了这种紧张,并主张采取激进的拥抱,认为否认抄袭活动的必然性是一种“来源伪善”。我直接引用他的断言,担心我不能公正地间接讲述它:

任何文本都是完全由引用、参考、回声、文化语言编织而成的,它们在一个巨大的立体声系统中贯穿始终。构成文本的引用是匿名的,不可追踪的,然而已经阅读了;它们是没有引号的引用。核心,灵魂——让我们进一步说,所有人类话语的实质、主体、实际和有价值的材料——是剽窃。因为基本上所有的想法都是二手的,有意识或无意识地从一百万个外部资源中汲取,并且每天被收集者骄傲和满足地使用,这种骄傲和满足来自于他发明了这些想法的迷信;然而,除了从他的精神和道德素质以及他的气质中得到的一点点变色之外,他们在任何地方都没有一点独创性,这一点在措辞的特点中表现出来。新旧构成了每一刻的经纬。没有一根线不是由这两股线拧成的。出于需要、癖好和高兴,我们都引用。神经学研究最近表明,记忆、想象和意识本身是缝合、缝合和模仿的。如果我们剪贴自己,难道我们不能原谅自己的作品吗?

这种想法,奥斯汀·克莱恩通过他的项目像艺术家一样偷窃(在我的阅读中,它超越了他的书,扩展到他的虚拟身份)为这种创造性和构思的“剪切-粘贴”方法提供了实用的指导方针。他在一个好盗窃/坏盗窃的比较中简洁地概述了这一点:

从这个意义上来说,指名道姓几乎是一种礼貌——这不仅是一种相当有信用的方式,也是向你的“英雄”致敬的一种方式。(注意,在这个项目的名字掉落的概念化中,他们不一定是“英雄”——作为灵媒,他们可能是反英雄,习惯性的批评对象,等等。).到目前为止,你会注意到我提到了一种留名的形式,有些人可能倾向于将其视为简单的引用,但引用更接近于正式引用的概念,而不是像留名这样非正式、随意、善意的提及。正如 Kleon 强调的那样:“如果你觉得它廉价或错误,它很可能就是。我提倡对自己的作品进行一次“电梯内脏检查”:如果你在一部停着的电梯里遇到了你要偷的艺术家,他们会和你握手或打你的脸吗?把这个建议运用到抛名本身的张力上,并不太难。

因此,通过勒撒姆的文章和克里昂的作品(在艺术家、作家等中非常流行)中概述的观念。),我们还可以观察到个人的理论框架——支配着某人的作品和其他产出——刺激着名字的删除。这增加了将域名抢注作为分析对象的支持,也为我们提供了一个这样的分析可以蓬勃发展的环境:一个在公共场合学习的环境。公共学习是一个松散的术语,我用它来描述博客和微博(社交媒体)记录一个人的学习(以及他们学习的媒介)的增长趋势。Kleon 引用 C.S. Lewis 的话,将这一过程归因于他的在线成果:

“我为不学无术的人写一些我自己都不知道的东西……经常发生这样的事,两个学生能比老师更好地为彼此解决工作中的困难……我以业余爱好者的身份给另一个学生写信,谈论我遇到的困难或我获得的光明……
——c . s . Lewis

“这是我一直试图在舞台上写作、教学或演讲的方式:不是作为一名专家,而是作为一名同学。T5 我在努力学开。我让别人看着我,而我在想办法。”
—克莱恩

“在开放中学习”的驱动力,加上我们对善盗和影响力的讨论,提供了一个很好的背景,在这个背景下,对姓名删除的分析既可以是可访问的作者受到激励,在他们的帖子中删除姓名并列出他们的媒介有意义的对这些媒介的分析反过来将有助于理解作者作品和思想的演变

这也让我选择使用奥斯汀·克莱恩的博客作为可视化的数据集。

连接到信息流的一般研究

Kleinberg 的 在线信息流的时间动力学 是一篇优秀的调查论文,研究了我们在处理信息流时遇到的各种问题(通过信息网络的视角)。正如 Kleinberg 所展示的,随着时间的推移,跟踪主题的演变,识别流中的“事件”,以及信息可视化都是该领域的重要方面——本项目略微触及了所有这些方面。如前所述,从根本上说,这项工作更接近于提供一种可能的信息可视化形式——一种在信息网络中赋予姓名特权的形式。虽然肯定不接近正式研究的形式——我并不真正“测试”任何东西——但这是一种非正式的探索,探讨如果我们通过社会理论而不是完全面向数据的方法来可视化,一种方法可能会是什么样子——及其结果的有趣性。

“处理信息流的时间动态的正确技术是什么?在新闻和电子邮件的典型例子中,可以看到这些信息流中固有的一些复杂性。每一个都为读者提供了一系列文件,展示了一个编织的和情节性的特征:编织,在某种意义上,许多平行的,主题连贯的流被合并和交织成读者看到的单一流;从某种意义上来说,主题通常在一段时间内变得越来越强烈,然后又逐渐消失。然而,尽管有这两个复杂性来源,这些原始形式的信息流缺乏任何明确的组织结构,超出了单个文章或消息的粒度。因此,处理此类信息流的第一步是定义适当的结构,抽象出它们相互交织的主题、它们的多次突发事件以及它们的长期趋势。
—Kleinberg, 在线信息流的时间动态

2 —操作化

生成该分析涉及许多步骤,每个步骤都需要复杂的技术参数调整才能获得有意义的结果。因为我在这里并没有开发任何新的东西——只是简单地剪切和粘贴各种数据挖掘、信息可视化和网络科学技术——所以我将只讨论高层次的技术步骤。

这个项目的数据以时间戳文档流的格式出现。具体来说,我抓取了 Austin Kleon 的博客站点以获取每篇博客文章(我们称之为文档)及其发表时间。

***Data Time Range:** 2006-06-14 - 2020-01-08
*I filter out a few of his earlier posts as noisy***Total Posts:** ~2000, before filtering*

提取域名和内容 为了获得我们的分析单位,我将每个文档通过一个解析器、带标签的位置和一个页面排名算法,得到如下结果:

  • 所有被命名的实体都是人(我们将称之为人名地址栏)
  • 所有其他名词和专有名词(我们称之为内容)
  • 权重以上每个人在帖子中的作用有多重要——为了获得合理的结果,这涉及多个步骤,包括 td-idf 平衡以及检查每个单词的信息内容

生成初始网络 对于同一个文档中出现的每个名字拖放,我用两个术语的重要程度的相对权重来表示它们之间的联系。对每一对域名进行这样的操作会生成一个节点和边的网络。由于我对服务于最像媒体的角色的名字删除感兴趣,我测量了每个节点的信息中心性——相对于边权重计算——并提取了前 5%。据推测,这为我们提供了随着时间的推移发挥了最重要作用的姓名地址。

请注意,除了提取的 5%之外的名字删除将被视为内容。从本质上讲,这些其他的名字滴,虽然本身就是媒介,但还不足以为了这些视觉化而从内容中分离出来。

跟随媒介理论家马歇尔·麦克卢汉,我们也可以概念化为“任何媒介的‘内容’总是另一种媒介”。因此,我们实际上只是试图提取最相关的媒介——人名、名词、专有名词,在某种意义上都是媒介——并将其余的标记为“内容”。**

类似地,对于每一个时间步,我们根据名字和内容是否同时出现在博客文章中来建立它们之间的联系。这给了我们动态的网络。

3-视图 X:动态网络动画

演示:奥斯汀·克莱恩的动态网络动画

动态网络随时间变化的动画

我提出的第一个观点是半信息性的——它提出了一个故事,但不是无缝的,尽管我仍然包括它——也是半艺术性的。这里的想法是创建一个动画,强调随着时间的推移,姓名地址和内容网络的特定属性。

如何解读此观点:

  • 布局:有一个通过链接连接的分割视图——为了消除混乱,我只让最相关的链接可见。上面的半部分包含名称拖放节点,下面是内容节点。左上角包含播放动画和左右移动时间步长的按钮。你也可以用左右箭头键和空格键来控制动画的播放/暂停。**
  • A——节点:彩色节点代表名称下降,非彩色节点代表内容。颜色并不重要,但基本上是通过对节点进行聚类的方法,基于名字点的时间外观模式来分配的。可以点击任何节点来高亮显示它们,使它们在整个动画中更容易被跟踪。**
  • B —状态栏:可视化上方的栏表示每个时间步节点的总权重和平均熵。
  • C——节点高度:节点的高度表示它们的累积权重,因此更高的名称-drop 使用得更多,类似地,更高的内容节点使用得更频繁。
  • D — 内容特异性:这是内容的熵度量。基本上,内容节点越靠右,就越被各种各样的名称下拉链接。例如,上图中的“艺术”此时链接到多个名称拖放,因此出现在屏幕的右侧。如果一个内容节点,在历史上,已经连接到几个名字点,它将出现在左边,表明一个高特异性的媒体管理它。
  • E — 中等特异性:name-drop 节点基于它们当时连接的内容节点左右移动。因此,如果在给定时间,名称删除节点 X 连接到历史上与多个其他名称删除节点链接的内容节点,节点 X 将出现在右侧。这表示名称拖放相对于其所连接的内容的唯一性,具有高媒体特异性的名称拖放出现在左侧,因为它们连接到未通过其他名称拖放引用的内容。

总的想法是当名滴出现时,根据它们的垂直位置和大小来可视化它们在作者文本中的权重,根据它们的水平位置来可视化它们与连接的内容* 的特异性。这就产生了一个动画,展示了以域名为媒介的故事,在作者的知识领域和信息流中导航它们的位置,这取决于通过它们思考和呈现的内容。***

4-查看关联的 Y: A(汇总)图

演示:奥斯汀·克莱恩的关联图

名称拖放和内容之间关联的总结图—可以将鼠标悬停在每个节点上,以交互方式查看详细信息

如果我们从前面的视图中移除动画因素并总结关联权重,我们可以可视化一个总结图,该图可视化了名字点(作者的媒介)以及内容之间的影响和关联。

如何阅读此视图:

  • 布局:节点基于它们第一次与作者文本中的重要概念之一有联系而从左到右定位。本质上,左边的节点,不管它们是内容节点还是名称拖放,都是最先出现在作者的输出中的,而右边的节点出现在它们最近的历史中。
  • A-Name-drops:位于视图底部的节点是 Name-drops。可以将鼠标悬停在这些图标上,查看它们的汇总关联。节点的大小代表了名字点在整个历史中的总权重。即较大的节点比其他节点被更有效地使用。与上一个视图一样,颜色是根据名称拖放的时间模式分配的。
  • B —内容:非彩色节点是一群内容节点。这些节点也是按照它们第一次出现的顺序排列的,它们的大小代表了它们在作者作品中的全部意义。我们可以有把握地假设,位于任何给定的名称拖放上方的内容节点在作者的历史中大约同时出现。如果这些节点直接连接到悬停在上面的名称拖放节点,它们就会亮起。

这个视图是交互式的,想法是将鼠标悬停在一个名字拖放节点上,以查看它过去或将来对其他名字拖放的影响**

交互性,以了解域名删除如何影响网络中的其他节点或受其他节点的影响

互动后如何阅读此视图:

  • 布局:当鼠标悬停在一个名字拖放节点上时,视图会改变以显示其关联和影响。右上角的面板控制过去或未来的影响是否可视化,以及是否显示或隐藏链接。总的想法是,越不透明的节点与所选择的名称下拉具有越强的连接(关联/影响)。
  • A —选择的名称:用户悬停并选择的节点。
  • B —名字点之间的直接链接:从所选名字到其他名字点的弧线表示直接连接。这意味着这两个名字一起出现在一篇文章中,因此在某种程度上,是相似内容的媒介。
  • C——高亮显示的内容节点:当鼠标悬停在一个名称下拉菜单上时,任何内容节点都是彩色的,这意味着该内容和所选名称之间有直接的联系。内容节点的不透明性指示所选名称和内容之间的关联性的强度,不透明的内容节点指示与名称的高关联性。
  • D-其他名称-下拉:根据所选选项,这些节点的不透明度表示它们对所选名称的影响强度。这种影响是基于它们与连接到所选名称的内容的关联性的重要性来计算的。本质上,如果这些节点是不透明的,这意味着它们已经显著影响了所选节点或受其影响——这取决于您是否在右上方的控件中选择了过去的或未来的影响
  • E——名称点和内容之间的非直接链接:名称点和内容节点之间的直线连接线表示其他名称点如何影响所选名称或被所选名称影响。即,当选择节点 Z 时,在名称-拖放 X 和内容 Y 之间的连接,而过去影响被选择,表明 X 在过去与 Y 相关联,因此影响 Z 和 Y 之间的连接——因此 X 通过 Y 影响 Z。**

一般来说,将鼠标悬停在一个名字删除节点 Z 上可以突出显示图中所有其他节点,这些节点在影响(未来)已经被节点 Z 影响(过去)。这种影响是通过与内容节点的连接计算的加权度量,考虑了作者作品中内容节点和名字删除的重要性。从理论上讲,这个视觉展示了媒体之间随着时间的推移而产生的影响——强调了塑造作者作品的影响的进程——以及被广泛讨论的大概念。****

5-视图 Z:名称下拉矩阵

演示:奥斯汀·克莱恩的名字-下降矩阵

奥斯汀·克莱恩博客的名降矩阵——每个单元代表名降之间的影响

最后,如果我们进一步总结总结图,我们可以从视图中删除内容节点,并简单地显示名称点之间的关联。这是最简单、可读性最强的视觉效果,它试图表达一个作者名字掉落的最快历史。矩阵,即使没有详细阅读,指出了作者如何通过他们的媒介工作的“直觉”。

如何阅读此视图:

  • 布局:这是一个通用的邻接矩阵表,横轴和纵轴代表域名。然而,请注意,根据作者信息流中的名字滴的总权重,的名字滴具有不同的代表区域。可以将鼠标悬停在矩阵中的任何单元格上,以确定它指向哪个姓名地址。**
  • 单元格颜色和不透明度:每个单元格的不透明度代表横轴名称拖放对纵轴名称拖放的整体影响强度。**
  • 轴顺序:水平轴和垂直轴(分别为从左到右/从上到下)上的所有名称-拖放按其第一次出现的时间排序。

一般来说,将鼠标悬停在某个单元格上可以突出显示该单元格所代表的关联的相关名称。实际上,查看横轴上给定域名称 X 的一列单元格,可以理解为“域名称 X 的过去连接对其他域名称未来连接的影响有多大”。相反,在纵轴上查看给定的名字滴 Y 的一行单元格读作“名字滴 Y 的连接受其他名字滴的过去连接的影响有多强”。(连接是指名称拖放和内容节点之间的链接,影响的衡量方式与之前的视图相同,即通过对共享内容节点的连接进行加权衡量)。从理论上来说,这种视觉效果既强调了主要的名字投放,也强调了名字投放在什么时候会产生影响。此外,由于矩阵是不对称的——域名称删除 X 对域名称删除 Y 的影响不等于 Y 对 X 的影响——该图描述了域名称删除和任何重大不平衡之间的相互影响。**

6 —备注

在这一节中,我想写下一些关于这种方法的局限性和这些可视化可以提供的见解的一般想法。

限制

  • 我通过令人眼花缭乱的分布“直观地”挑选了多个参数——选择多少个名字点,可视化“内容”的百分比,当帖子中的一个词被认为“重要”时,权重和计数的阈值,等等..这些可以通过更复杂、更系统的方法进行更严格的研究来确定。
  • 命名实体提取(确定什么是名称删除)本身并不完美,我做了大量的数据清理来连接各种专有名词,以确定它们实际上是相同的名称删除还是根本就是名称删除。尽管进行了清理,但有时还是会出现重复项,它们不会被识别为同一个实体——因为引用它们的方式略有不同。其他时候,某些实体根本无法识别,或者错误的名词被识别为人,这是非英语单词的一个长期问题。
  • 确定什么是真正最相关的“内容”需要更多的工作——对词汇、事件等的全面分析。正如克莱恩伯格在他的论文中提到的那样,这将是有益的,而不是简单地查看最相关的名词。与命名实体类似,我也做了一个非常简单的概念计数,如 1-gram,2-gram 名词,但还可以做更多的工作来将某些概念连接为一个相同的概念。
  • 我所表述的联系——名字和概念出现在同一篇文章中——对中等长度的文章很有效,但对较长的文章就不适用了。较长的帖子需要进行更深入的搜索,以找到单个帖子中的链接。(同样,对于像 Twitter 这样的小篇幅帖子或微博,要么需要大量数据,要么需要更复杂的方法来建立联系。)
  • 这种信息网络的结构赋予了点名的特权,但如果我们分析的帖子出于其他原因引用了许多名字,就会很快被打乱——例如政治新闻,它会引用多个政治候选人,而这些候选人可能不一定属于理论上的“点名”作为“信息手势”的概念。在这个项目中,通过特别关注在公共信息流中学习来缓解这个限制,在公共信息流中,名字丢弃通常属于我们的定义。
  • 请注意,这种分析不一定直接反映作者的“真实”影响和思想。虽然可能存在相关性,但我们可以严格地关注作者在这个项目范围内的作品——假设作者通过他们的作品展示了一个自我形象,不管这个形象有多“真实”。

可视化作为一种(宏大的)“信息姿态”

也许视觉呈现的直接效果直接源于动机——它们作为一种(宏大的)“信息姿态”,快速传播作者希望向读者描绘的自我形象。通过消除多余的连接,并缩小到可以安全可视化的范围,这个项目试图呈现信息流(在这种情况下,一个作者的博客)中的显著习惯性移动。通过以这种方式可视化习惯,读者可以使用这些可视化来快速衡量信息流的多个属性,包括:

  • 作者最不喜欢/最不喜欢哪个名字?琳达·巴里显然是克莱恩的代表)
  • 媒体是如何随着时间的推移而演变的——它们的使用何时开始或达到顶峰,它们何时被放弃,另一种媒体是否“接管”了现有媒体的领地?媒体使用的时间模式等。(例如。有趣的是,我们看到一些早期的名人开始影响克莱恩的未来作品,并受到其影响,直到梭罗,我们才看到另一个大“英雄”出现。这也表明克里昂不断地将他的讨论追溯到这些早期的英雄身上。)**
  • 作者影响力的多样性和扩散性——或者说缺乏——仅仅是看到不同博客的不同名字列表就可以帮助读者认识到他们可以期待的模式和阅读体验。
  • 一个名字掉落占据哪些概念的时空模式。
  • 广泛讨论的概念的可见性,以及它们如何与特定的名称下拉联系起来(特别是对于视图 Y)。
  • 等等等等等等。

考虑到以上这些特性和许多其他难以列举的特性,结合 Kray 和 Goffman 的理论概念——名字掉落是提前告知的信息手势,我们可以将可视化概念化为一个大信息手势。作为一种宏大的姿态,可视化通过对域名争议历史的汇总视图,告知观众他们可以提前预期的信息,并为他们做好准备。请注意,这种姿态并不一定依赖于读者对人名的了解——日常对话中很少出现人名——而是呈现了作者的“形象”(戈夫曼的自我呈现理论)。这个图像本身是一种媒介,通过它我们可以感知作者的信息流——作为一个粗糙、直观的例子,看到一个具有影响力扩散的各种有分量的名字滴的矩阵与一个影响力很小的单个高分量的名字滴的矩阵,可以立即给我们一个不同的想法,我们可以从作者的文本中期待什么。此外,这些可视化(尤其是矩阵和总结图)显示了定位作者讨论的“锚”系统的结构——在这个意义上,我们可以感知主题如何随着时间的推移在信息流中重复出现。

进一步的假设可能会出现,我们可以预期,如果我们大规模地观察多个域名删除网络,我们可以提取模式并对信息流的各种属性进行分类。我们甚至可以设想找到名降动态网络属性的比率、阈值和平台,通过观察可以将信息流聚集成不同的类型,或者可能将它们建模以预测信息流。

这些可视化——尤其是矩阵——也可以作为博客摘要。其他尝试——博客天线(Blog Antenna)——试图通过自相似性主题分析,用视觉来总结个人博客,但同样,优先命名可能是一个更合理的理论结构。

7 —附加内容和其他演示

【beautiful-head.appspot.com】其他演示可查看@T5

漂亮的头像参考

Beautiful-Head 这个名字是指贝宁格演唱的民族歌曲《Beautiful Head》:

“重新定义你自己
设计你自己
你永远不会看着我
得到你的关系图
一个策略
你在权衡你的选择
你会拿我换什么?
你最近在测量我
我可以告诉你
我可以告诉你我在减肥
你最近在测量我

你在给我穿衣服 ——国民,美丽的头第二节

不可思议,不是吗?我建议从信息网络的角度来听整首歌,以此来阐明名字掉落在戈夫曼的自我呈现社会理论中的作用。

可视化其他博客——政治和哲学

尽管这种分析对新闻和/或较小的信息流有局限性——正如我在限制一节中解释的那样——我仍然出于兴趣在一些其他作者和博客上运行它——只是为了看看。

亚历山大·加洛威——媒体研究,偶尔发表中大型文章

***Data Time Range:** 2014-10 to 2020-01
**Total Posts:** ~150, before filtering*

其他视图:盖洛威的演示可视化

沙迪·哈米德 —政治、中篇专栏、帖子和文章

***Data Time Range:** 2009-12 to 2020-01
**Total Posts:** ~250, before filtering*

其他视图:沙迪·哈米德的演示可视化

伊丽莎白·布鲁尼格 —政治/社会学、文化、中篇文章

***Data Time Range:** 2017-12 to 2019-10
**Total Posts:** ~100, before filtering* Due to the few posts - I only used her articles on Washington Post) -, I loosened my filtering criteria.*

其他视图:伊丽莎白·布鲁尼格的演示可视化

可能是因为职位数量少,但有一个非常明显的不对称性,表明除了少数关键候选人(伯尼,沃伦等。),旧域名会影响未来的域名,但很少有反向引用。这可能是文化/观点写作的结构属性,其中信息流不断地处理当前事件,因此通常在不改变过去观点的情况下前进(不像在公共博客中学习)。

可视化微博

这个项目是为博客帖子定制的,但我在一些 twitter 账户上运行它是为了好玩——我认为——在某种程度上在公共环境中使用它们的提要(混合了宗教(伊斯兰教)、哲学和政治的内容)。 注意,由于 Twitter 数据收集的限制,这不是一个用户的完整历史,而是最近约 3200 条推文/RTs +回复。

***Accounts**: [Evollaqi](https://twitter.com/Evollaqi) & [IbnMaghrebi](https://twitter.com/IbnMaghrebi)*

Evollaqi 的演示可视化

IbnMaghrebi 的演示可视化

**

我自己的推特表现…

Twitter 上公共学习的可视化

最后,我展示了我自己的 Twitter 的名字删除矩阵——与这篇文章中的其他人相比,这是一个非常尴尬的自我形象...(我当然不总是以一种公众学习的方式使用 twitter,但我最近开始更多地使用了)。

这个矩阵肯定包含了我在 Twitter 上的所有主要名字,它准确地反映了我后来的变化,即在矩阵的右下角有更强的关联,表现得更有联系,更有学习力。

感谢您的阅读。如果你有任何想讨论的问题或想法,请随时在 Twitter 上联系我。

如果你认为有另一个博客或信息流可以通过这个项目有趣地可视化,让我知道,我会看看我能做什么!

美化冠状病毒条形图

原文:https://towardsdatascience.com/beautify-coronavirus-bar-charts-ac636d314d98?source=collection_archive---------51-----------------------

超越 Matplotlib 基础的 5 个步骤

当你刚接触 matplotlib 的时候, plt.show() 的结果并不是特别令人印象深刻。当然,它对传达信息很有用,但它不是那种可以放在文件夹里或向朋友炫耀的图表。

五个关键调整可以将基本图形转换为漂亮的图形。美丽在这里并不意味着无关紧要。当谈到图形数据时,漂亮包括正确的背景、方向、大小、颜色和标签,以提供一个有吸引力的、清晰的和信息丰富的图形。

在本文中,我们加载冠状病毒数据,准备用于绘图的数据,使用 matplotlib 绘制基本条形图,并使用 5 个键调整将绘图转换为漂亮的图形。本文假设读者对熊猫有基本的了解。

加载冠状病毒数据

首先,我们需要一些数据。以下代码将约翰·霍普斯金冠状病毒 Github 数据集分配给变量 url 。该文件是一个 CSV 文件,并且在靠近末尾处提供了日期。该日期可由用户更新以获得最新的冠状病毒信息。数据集每天更新。

接下来,导入熊猫,然后使用 pd.read_csvdf.head() 读取并显示数据帧。

从最后一栏可以看出,数据是按城市和国家提供的。该数据集包括所有国家。要仅绘制来自国家/地区的数据,我们可以通过列‘国家/地区’进行分组。我们选择‘sum’聚合来获得除纬度和经度之外的所有数字列的精确计数。

最后,我们只选择提供关于冠状病毒的数字信息的列,即、【死亡】、、【恢复】、、【活动】、

现在开始制图。

准备用于打印的数据

matplotlib 很容易生成一个图。在条形图的情况下,您只需要 x 值,即您想要比较的类别,以及 y 值,即比较的列。我们将比较每个国家的恢复病例数。

创建一个包含数百个类别的条形图是不可行的。在冠状病毒数据的情况下,类别是国家,由列为我们的组之后的索引。我们将只选择前 10 个国家。

首先,使用 sort_values 方法,通过选取 10 个最高回收数量的国家来分割数据框架。结果可以存储在新的数据帧中,如下:df _ Recovered = df . sort _ values(by =‘Recovered’,ascending=False)[:10]

接下来,使用索引上的 to_series 方法将索引转换为序列。这种转换的原因是在绘图时使用列是标准的,实际上是熊猫系列。这些指数,通常是你在 T4 分组之后想要的类别,必须被转换。以下代码将索引国家转换为序列:x _ vals = df _ recovered . index . to _ series()

我们还设置了y _ vals = df _ recovered[' Recovered ']来选择“Recovered”列作为我们的 y 值。

以下是分割数据帧并设置 x 和 y 值的步骤。

使用 Matplotlib 的基本条形图

条形图是许多 matplotlib 图中的一种。导入 matplotlib,之后,您决定想要绘制的绘图类型,在我们的例子中是条形图,然后您插入 x 和 y 值,后面跟着 plt.show() ,如下所示。

这是我电脑上的图表。它捕捉到了关键信息,但是国家名称连在一起,太小了,不美观。

现在,让我们使用相同的信息和 5 个关键的调整来创建一个美丽的条形图。

调整一:进口海博

seaborn 是 matplotlib 的一个很好的补充。我一直使用 seaborn ,因为我更喜欢带有网格线的灰色背景,我发现 seaborn 中的许多图形选项,如线性回归,更容易使用,更美观,并提供更多信息。

下面的代码将 seabornmatplotlib 一起导入,并将背景设置为漂亮的深色网格。

调整 2:水平前进

我们已经有了数据集, df_recovered 。上面给出的 x 值和 y 值的信息可能保持不变,只有一个例外:将它们转换为水平条形图。

水平条形图更容易阅读,因为 x 轴上的间距不再杂乱。当订购垂直堆叠时,水平条形图也提供了很好的美感。

以下是切换 x 和 y 的代码。注意,在条形图函数中设置参数 orient='h' 也可能有效。

调整 3:改变体形大小

这是一个大的。我不确定为什么默认的 matplotlib 图这么小。增加尺寸总是一个好主意。你可以看到更多的细节,图形不那么拥挤,它们占据了更多的屏幕空间。

您可以使用 plt 上的fig的方法,然后在括号内设置 figsize 的尺寸。注意尺寸是(水平,垂直)。这里有一个大尺寸的作品。根据自己的喜好调整数字。

调整 4:使用调色板

漂亮的颜色真的让图表很突出。当使用一种颜色时,考虑将透明度包含在 alpha 参数中。对于条形图,调色板是理想的。调色板甚至可以颠倒,这样最深的颜色就在最上面,这取决于你想讲的故事。

值得尝试用你的颜色讲一个故事。由于从冠状病毒中恢复是一件好事,绿色可以用作积极的颜色,恢复最多的国家显示在顶部,作为最暗的绿色阴影。将最深的颜色放在最上面通常需要将'_ r【T3]'字符串连接到调色板的末尾来颠倒顺序。

找到所有调色板选项的一个有趣的方法是在代码中插入一个调色板错误!正确的选项会显示在 Colab 笔记本中。或者,标准调色板可以在的 Python 图库中找到。我更喜欢错误的方法,因为我可以留在我的笔记本上,它告诉我一切。

调色板可在 sns.barplot 内设置,连同 x 值和 y 值如下。

调整 5:使用有尺寸的标签

不言而喻,应该为图使用标签并确定其大小。所有的图表都应该有标题,标题的大小可以增加,直到你喜欢为止。

seaborn 的情况下,x 轴和 y 轴默认使用 index 和 columns 提供的标签,这里就不加了。

下面是给你的图加标题和调整标题大小的代码。

把所有的放在一起

剩下的就是保存剧情,展示出来。保存您的绘图总是值得的,因为在您的计算机上的输出会比在 Jupyter 或 Colab 笔记本上,甚至在使用第三方软件的 Medium 等网站上看起来好得多。一个简单的策略是将 dpi(每英寸点数)设置为一个较大的数字,比如 300。

这里是所有的代码一起创建和显示一个美丽的冠状病毒水平条形图。

如你所见,通过 5 个关键调整,新图表值得与朋友分享或放入你的作品集。这个图表很简单,但是信息丰富而且很漂亮。它在我的电脑上更清晰,在你的电脑上也会如此。

现在你已经学会了 5 个关键的调整,使你的条形图美观,享受这个数据集和其他创建和显示新的信息列的乐趣。

编码快乐!

科里·韦德(Corey Wade)是伯克利编码学院 的主任 Python 工作坊 的作者,伯克利独立研究数学系主任。2020 年夏天,他正在为青少年在线举办一个机器学习& AI 夏令营。更多信息参见berkeleycodingacademy.com

BebopNet:爵士乐即兴创作的神经模型

原文:https://towardsdatascience.com/bebopnet-neural-models-for-jazz-improvisations-4a4d723d0b60?source=collection_archive---------20-----------------------

使用人工智能生成(个性化)Bebop 即兴创作

Shunit Haviv Hakimi、Nadav Bhonker 和 Ran El-Yaniv

更新(2020 年 10 月): 我们关于 BebopNet 的论文刚刚发表在 ISMIR 2020 !
在 ISMIR 2020 中查看我们的论文、海报和视频:https://program.ismir2020.net/poster_6-08.html
我们还上传了我们的代码、一个经过训练的模型、一些样本、和补充材料:
https://shunithaviv.github.io/bebopnet/

图片来源:https://www.pexels.com/@victorfreitas

创作音乐和爵士乐即兴创作绝对不像看起来那么容易。事实上,即使对最好的音乐家来说,这也是一项艰巨的任务。我们甚至能准确地定义和理解爵士乐即兴演奏吗?不幸的是,在很大程度上,这仍然是一个难以捉摸的幻想。

每个人都同意的是,爵士乐即兴创作是一种符合固定的重复和声进行的旋律独奏的自发发明。当独奏与和声、与其他演奏者、与独奏本身对话时,一场伟大的爵士乐表演就诞生了。当然,个人发明本身不是随机的,它应该遵循一些非常难以精确确定的复杂规则。在我们看来,爵士乐独奏一代的这种固有的难以捉摸性,回避了机器学习技术的挑战,机器学习技术原则上可以从示例中学习。

作曲的计算机程序

自从电脑出现以来,人们就一直试图用电脑来创作音乐。考虑到各种类型的音乐中出现的模式和数学关系,这也许并不奇怪(例如,考虑一下巴赫的螃蟹佳能,它神奇地将同一旋律向前和向后结合)。大多数计算机音乐生成的最初尝试是基于规则的,这意味着他们试图显式地编码语法音乐规则(希勒,1957 )。随着机器学习的进步和更强大的计算机的出现,马尔可夫模型被用来生成音乐。马尔可夫模型本质上回答这样的问题:“给定音符 C、E 和 G 的序列,下一个音符的概率分布是什么?”

模型是如何产生这些概率的?最简单的形式是,马尔可夫模型“扫描”一个由许多音乐作品组成的语料库,并计算它在序列“C,E,G”之后找到的所有音符。然后,它通过出现的总次数来标准化这个计数量的向量,以获得概率分布(所有数字都是非负的,并且总和为 1)。这就是所谓的马尔可夫链的最大似然估计。基于马尔可夫链的模型,更一般地说,基于可变阶马尔可夫建模(可以考虑更长的上下文),可以产生令人惊讶的令人印象深刻的结果(例如,参见这个和这个)。
然而,使用有界阶马尔可夫模型存在一个问题,即:当增加用于预测的上下文的长度时,很快就会达到这样一个点,即在训练集中不会出现这样大小的训练序列。换句话说,对于大订单建模,模型遭受统计稀疏性,因此它不能考虑长期依赖性。

然而,这些年来,算法越来越好,计算机越来越强,总体上遵循摩尔定律和库兹韦尔定律(你知道库兹韦尔是第一个建造作曲的 T2 计算机的人吗?).这些发展为深度神经网络(机器学习的一个新旧子领域)走向舞台中央铺平了道路,推动了许多不同领域的科学和技术,包括音乐创作、图像识别、自动翻译、语音到文本、文本到语音等。

今天,利用马尔可夫模型和深度神经网络,模型和大型音乐语料库正被用来制作越来越令人愉快的音乐。一些令人印象深刻的结果由洋红色和开放式展示。

在这里,我们向您展示了我们使用机器学习所取得的成就。

我们开始尝试创作令人愉悦的爵士乐即兴作品,将独奏的产生视为一个模仿学习的问题。我们有意决定简化事情,将重点放在由单声道乐器(而不是复音乐器,如钢琴)在一个狭窄的爵士乐流派中创作的独奏上。我们选择的乐器是萨克斯管,流派是 Bebop。因此,我们想训练一个神经网络通过学习模仿著名萨克斯管 Bebop 演奏者的即兴演奏来即兴演奏爵士乐独奏。我们设计了 BebopNet 来学习预测下一个要演奏的音符,给定一些过去的音符和过去的和声级数以及即将到来的和声(下一个音符应该在其上演奏)。一旦经过训练,模型应该能够在任何期望的和弦进行上创建独奏,而不一定是出现在训练集中的那些。为了判断我们的成功,请听一段由 BebopNet 为查理·帕克的“Mooche”创作的独奏。

为“ Moose The Mooche ”即兴创作。即兴表演在 00:34 开始。

BebopNet 还可以应用于创建其他(非爵士)音乐类型(如当代流行歌曲)的和弦进行独奏。例如,听一段由生成的独奏。

利佐为“果汁”即兴创作。

模仿学习:注意到注意

对于即兴创作音乐的神经网络来说,除了理解音乐理论之外,它还需要能够捕捉主题和音乐思想。这意味着神经网络必须能够捕捉音乐数据集的长期特征。此外,任何人类爵士乐演奏者都知道,神经网络必须知道每个时刻的和声环境,即节奏部分演奏的和弦。

由于音乐和语言有许多相同的特性,我们最初将 BebopNet 基于一个可以生成语言句子的语言建模神经网络。我们训练了 BebopNet,一个长短期记忆 ( LSTM )模型,根据之前的音符预测下一个要演奏的音符。

使用递归神经网络的优势在于其捕捉重复和长期模式的能力。随着基于注意力
模型在语言建模中变得流行,我们用 transformer-xl 代替了我们的神经网络。

正如在马尔可夫模型中所做的,我们通过反复要求网络预测一系列音符和和声之后的下一个音符来训练我们的网络。我们使用的方法与 Andrej Karapathy 的著名博文中描述的方法非常相似。

下一个音符预测(GIF)

然而,与自然语言处理的神经网络不同,神经网络的输出是下一个单词的一个概率向量,我们的输出是两个概率向量:一个是下一个音符的音高持续时间

训练后,在使用模型生成独奏时,我们在每一步都有两个选择:要么贪婪地选择最可能的音符,要么将输出视为分布向量并对下一个音符进行采样。后者保证了我们的可变性,并允许我们产生不同的即兴创作。

下一个字符预测的简化网络结构。每个音符由音高和持续时间表示。输入还包括上下文和弦。

资料组

我们的数据集由从saxsolos.com购买的 XML 文件形式的爵士独奏转录组成,包括以下爵士即兴演奏:
-查理·帕克(1920–1955)
-炮弹·阿德利(1928–1975)
-桑尼·斯蒂特(1924–1982)
-菲尔·伍兹(1931–2015)
-索尼·罗林斯(1930-)
-史坦·盖兹(1985)

笔记表示法

为神经网络选择正确的输入表示方法对于其功能性至关重要,并且会极大地影响性能。从原始音频波形、MIDI 格式到活页乐谱,音乐表现方法种类繁多,因此选择一种最适合的方法极具挑战性。

BebopNet 基于符号音符表示,非常类似于音乐家用于交流音乐的标准音乐符号系统。使用这种表征可能有助于学习节拍和旋律中的模式和重复。每个对象代表一个音符及其音高、持续时间、小节内的偏移以及和声上下文。和声环境包括当前和弦的四个音符。我们使用上面的音高表示方法,并连接所有四个音高来表示一个和弦。

音乐符号中的度量及其转换为神经网络输入的示例

创造了一个模型,我们的即兴创作在艺术上还不错吗?

任何爵士乐即兴创作以及任何艺术的一个主要成功标准是创造力。如何评估爵士乐独奏的创意水平?嗯,定义创造力一直是人类长期争论的难题之一。我们不想深入讨论这个问题,所以我们决定解决创造力的一个非常适度但可量化的方面,并通过他们的“抄袭水平”来评估爵士乐独奏的原创性。

利用这种独创性的概念,我们可以观察到几个有趣的事实。例如:在 Bebop 巨人中,桑尼·斯蒂特是模仿者的“国王”(双关语)。他从史坦·盖兹和桑尼·罗林斯那里抄袭了许多短语。另一个有趣的事实:令人惊讶的是,使用几个抄袭指标,我们训练的模型看起来像任何专业爵士乐手一样原创。

剽窃

我们定义的度量是最大公共子序列中音符的数量。作为一个基线,我们在我们的数据集中寻找这个特征:爵士乐巨人在多大程度上“复制”了彼此的音乐句子?

注意,我们将这种比较定义为对音高移位不变:两个相同的序列将包含相同的音高间隔和相同的持续时间。

表中的每个元素是艺术家 A 的独奏(行名)中在艺术家 B 的任何独奏(列名)中找到的平均最大子序列。

将我们的爵士乐即兴学习模型生成的爵士乐独奏池与数据集进行比较,结果是平均最大的公共子序列 4.4 音符,这意味着我们在这个特征上与任何爵士乐巨头没有太大区别。

但是让我们看看更短的序列。为了做到这一点,我们计算一个艺术家和数据集的其余部分之间长度为 n 的共同序列的百分比。一定长度的序列 n 在语言建模中被称为 n 元语法。

长度 n 的常用短语的百分比——克长。我们的爵士款是黑色的(仿款)。

正如所料,长度为 1 的大多数序列也可以在数据集中的某个地方找到,而 n 越大,出现的百分比就越小。对于任何 n ,模仿学习模型不超过最大出现百分比。

*我们计算了曲线下的面积实现了对抄袭的归一化测量:
-炮弹 0.704
-戈登 0.746
-格茨 0.745
-帕克 0.693
-罗林斯 0.718
-斯蒂特 0.680
-伍兹 0.714
-阿蒙斯 0.718

  • 我们的模型 0.713【t24*

让我们把它私人化

所以,现在我们有了 BebopNet,但是它能创造出个性化的爵士乐独奏吗?我们所说的“个性化”是指 solo 经过优化,能够让特定用户感到满意!为此,我们试图训练一个个人偏好模型,捕捉特定用户的口味。这个个人模型应该优化从模仿模型生成的独奏,以匹配特定用户的音乐品味。在本节中,我们将演示我们是如何做到这一点的。查看 solo over the jazz standard "【芝士蛋糕】* 为本帖作者之一优化。*

为“芝士蛋糕”的个性化即兴创作。即兴表演从 01:02 开始。

个性化内容无处不在。亚马逊、网飞和 Spotify 等科技巨头将现有内容定制为客户的个性化体验。例如,Spotify 内容的个性化是基于完整歌曲的一般“低分辨率”特征。在我们的例子中,我们试图在非常高的每个音符“分辨率”上实现个性化,这意味着我们为给定的独奏创建的个性化分数不是一个数字,而是一个完整的序列。

我们的个性化过程以这样一种方式操纵生成模型,它产生匹配个人偏好的优化代。我们的个人偏好模型可以被训练以匹配任何特定用户的口味。用于训练该模型的数据集直接从用户输入组装。

个性化流程有三个步骤:

1.组装:组装一个音乐序列和相应用户评分的小数据集。

2.训练:训练一个用户评分模型,预测用户对每个音乐序列的评分。

3.生成:使用用户评分模型结合波束搜索,生成尽可能符合用户偏好的即兴创作。

步骤 1:组装用户偏好数据集

为了构建数据集,我们收集了不同背景下的爵士乐即兴演奏:

  • 来自我们一般数据集的爵士乐即兴演奏
  • 爵士乐即兴创作产生于我们一般数据集中的和弦进行
  • 爵士乐即兴创作产生于和弦进行之上,这在我们的一般数据集中是不存在的

在听爵士乐即兴演奏时,每个用户用一个节拍标记他们的偏好。该仪表基于 CRDI (连续响应数字接口)装置的理念。

受 CRDI 启发的仪表(图片来自 https://github.com/Andrew-Shay/python-gauge

我们的(虚拟)计量器被限制为五个不同的级别,标签被标准化为-1 和 1 之间。
最终的数据集被分割成音乐序列,其中每个序列在序列的末尾都标有用户的乐谱。

步骤 2:训练用户评分模型

对于用户评分模型,我们使用类似于上述音符到音符预测模式的模型,但是用户评分模型被训练来预测给定序列中每个音符的用户分数。用户评分模型还包括一个额外的注意力层,输出是一个介于-1 和 1 之间的浮点值。

步骤 3:生成用户优化的即兴创作

有了经过训练的用户评分模型,我们在音符到音符预测模型上使用 波束搜索 。波束搜索使用用户评分模型的评分标准。

波束搜索通常用于生成式语言模型,并被 Google Translate 等系统大量使用。这些模型通常包括单词到单词的预测模型。

使用波束搜索,我们可以增加搜索范围,以最大化某个期望的目标。这意味着,在每一步,搜索将考虑下一个笔记的各种选项,并做出更好的选择,使目标最大化。对于我们的个性化生成,波束搜索优化了用户在生成的即兴方法上的得分。

使用贪婪方法,搜索在每一步选择最可能的音符,目的是增加生成序列的分数。

波束搜索——贪婪方法

然而,有可能在某个步骤选择一个不太可能的音符将导致更多可能的后续音符和整个生成句子的更高分数。增加每一步生成序列的长度允许我们深化搜索

波束搜索—更长的序列

即兴创作示例

我们现在呈现由我们最终的深度学习模型生成的爵士乐标准的即兴创作。每一次即兴创作都以特定的“头”为条件——特定爵士乐标准的旋律和和弦。我们发现了一个有趣的方法,通过在一个新的头上测试来确保我们的模型学会随机应变。也就是说,我们在一个模型在训练过程中从未见过的和弦进行上测试了它。我们甚至在非爵士乐的例子中也这样做了。

以下所有样本都是使用我们的系统生成的。生成的音符用 MIDI SoundFont 播放,并与使用乐队在一个盒子里(BIAB)创建的背景音乐混合。

大多数样本包括头部的旋律,然后是生成的即兴创作。

创作了超越爵士乐标准的爵士乐即兴作品

在流行歌曲上即兴创作爵士乐

根据耶胡迪特·拉维兹创作的以色列歌曲《拉卡塔和迪雅·贝亚德查》即兴创作了爵士乐

最后的想法

一个理想的音乐创作应该满足几个条件。例如,一个人可能期望爵士乐独奏是和谐的、有创造性的、令人愉快的、有趣的和有意义的。然而,当考虑计算机化分析和 jazz 生成时,问题是这些属性中的大多数没有数学定义。
因此,基于这些概念的明确表述,创造一个能产生高质量音乐的计算机程序超出了我们的能力。

在许多情况下,如果有足够大的训练序列,用于顺序预测的 ML 技术可以绕过这些障碍。我们确实有很多音乐实例可以学习,通过使用先进的预测技术,我们可以乐观地希望我们的模型将学会忠实地模仿优秀的爵士乐独奏。然而,话虽如此,我们还有一个内在的问题:我们如何评估性能?

虽然用户研究可能有助于评估一些对音乐质量的平均感知,但评估旨在取悦特定人以满足主观偏好的个性化内容是具有挑战性的。

在我们找到有效的评估方法之前,很难在这一领域取得持续的进展,尤其是在创作主观音乐内容方面。在这篇博文中,我们描述了我们为实现这一目标而迈出的一小步。我们提出了一种方法来客观评价主观内容。一路上,我们不得不克服极度嘈杂和不一致的人类反馈。我们的技术依赖于由每个用户提供的足够大的标记样本,这对于用户来说是相当大的努力。

我们预计,引出主观用户反馈的问题将在未来以完全不同的方式得到解决,例如,通过不引人注目地监控用户满意度,例如,使用照相机、EEG,或者甚至直接的脑-机连接。

这种评价只是超越爵士乐和其他音乐流派的一个障碍。为了制作计算机生成的人类水平的爵士乐独奏,我们将不得不解决几个与创造力相关的大问题。例如,我们能够客观地判断一个计算机程序是否有创造性吗?

创造性表现的一些主要属性是创新和“开箱即用”的模式的产生;即超出观察分布的异常模式的外推。然而,目前的最大似然法主要能够处理插值任务,而不是外推。有可能了解异常值的模式吗?

在计算机程序能够像熟练的人类艺术家一样表演之前,有许多问题、障碍和巨大的差距需要弥合。但与此同时,小步骤可以带来有用的音乐生成能力,人工智能可以成为创作过程的一部分。与任何数字乐器一样,音乐家可以使用人工智能探索新的想法、主题和声音,创造出前所未有的令人兴奋的新音乐。

这篇博文总结了以色列理工学院计算机科学系 Ran El-Yaniv 的深度学习实验室进行的研究。

联系人:
舒尼特·哈维夫·哈基米—shunithaviv@gmail.com
纳达夫·蓬克—nadavbh@gmail.com
冉·埃尔-亚尼夫—拉尼@cs.technion.ac.il

通过深度学习成为更好的自行车手

原文:https://towardsdatascience.com/become-a-better-cyclist-321a209d78d8?source=collection_archive---------37-----------------------

使用 YOLOv5 识别伦敦骑自行车者的危险因素

循环包含许多社会利益。它影响着一个社区的安全、经济、环境、公平和健康。道路上骑自行车的人数很大程度上受到他们对安全的看法的影响。要确定道路安全,最基本的是要有一个共同的衡量标准,以便确定和比较风险因素。使用谷歌街景(GSV)图像是分析城市环境的一种经济有效的方法。由于提取准确结果需要大量图像,因此使用了自动检测对象和结构的模型。

该项目的目的是使用对象检测和图像分割模型从伦敦的 GSV 图像中提取骑自行车者的道路风险因素。这涉及汇编道路安全指标和风险因素;在使用 YOLOv5 和 PSPNet101 这两个最先进的工具分别探测物体和分割图像之前,分析 GSV 数据集,并进一步分析其结果;确定 YOLOv5,PSPNet101 的局限性,并提出使骑自行车者的安全评估更准确的方法。

在图像数据集中的 50 万幅图像中,识别了大约 200 万个物体,标记了 2000 亿个像素。平均而言,每个下层超级输出区域(LSOA)有 108 个图像。使用 YOLOv5,在 LSOA 水平上直接识别出以下风险因素的分布:高车辆速度、电车/火车轨道、卡车流通、停放的汽车和行人。发现汽车 x 公共汽车、汽车 x 骑自行车者和汽车 x 人(最强)之间存在统计上显著的负相关。以及人 x 公交和人 x 自行车的正相关(最强)。重型车辆数量呈长尾分布。使用 PSPNet101,建筑物(27%)、天空(22%)和道路(22%)像素是最常见的。因此,在这些区域中的任何一个中的物体都可以被同等地检测到。所有的结果和实现都可以在项目的库中获得。

未来的发展包括提高 GSV 图像的可用性和分辨率。用包含更多类别的更大数据集训练 YOLOv5 和 PSPNet101。定义安全度量以同时考虑检测到的对象和分割的结构。

介绍

骑自行车对社会有很多好处。它影响我们的安全、经济、环境、公平和健康[1]。虽然在有些国家,大部分的日常通勤是通过自行车来完成的,但在另一些国家,人们很少使用自行车。

在实际的新冠肺炎疫情环境中,政府正在推广骑自行车作为驾驶甚至拥挤的公共交通工具的替代方式。众所周知,污染较重的地区不仅会给当地居民带来额外的感染风险,而且在公共交通工具上也很难保证社会距离。出于这些原因,英国政府正在用一个 20 亿英镑的一揽子计划来推动这种可持续的交通方式。

道路上骑自行车的人的数量很大程度上受到他们对安全的看法的影响[4]。要确定道路安全,最基本的是要有一个明确的通用指标,以便确定和比较风险因素。

谷歌街景(GSV)图像是公开可用的,此外,它覆盖了大多数发达国家(图 1) [5]。因此,这是一种分析城市环境的经济有效的方法。

由于提取准确结果需要大量的图像,数据集和在其上训练的模型用于自动检测存在的对象和其他结构。为此,使用对象检测(OD) [6]和图像分割(IS) [7]工具。

该项目的目标是根据具体的安全指标,如事故、伤害和死亡率,编制一份与伦敦骑自行车者最相关的风险因素清单。使用 GSV 影像数据集,通过 OD 和 IS 模型提取大伦敦地区已识别的风险因素。在较低层的超级输出区(LSOA)层面,研究不同的安全系数如何在伦敦分布。以识别大多数检测到的对象之间的相关性。在单独分析来自所有 LSOAs 的图像后,检测两种算法最常见的错误分类,并提出减轻错误分类的方法。最后,根据本项目的经验,为 OD 和 IS 模型如何检测额外的道路安全风险因素提供新的指南。

图 1 GSV 世界报道。改编自[5]。

在下一节中,将介绍对于理解该项目的目标和结果至关重要的概念。

背景

首先介绍骑行的好处。然后,探讨道路安全指标,然后确定伦敦骑自行车者的风险因素,并定义如何使用 OD 和 IS 方法捕捉这些因素。详细介绍了 YOLOv5 (OD)和 PSPNet101 (IS)模型及其各自用于训练它们的数据集。

骑自行车的好处

本节概述了与骑自行车相关的最重要的社会效益。它们可以分为五个主要领域:安全、经济、环境、公平和健康[1]。

在美国,年轻人死亡的主要原因是交通事故。占 15 至 24 岁年龄组死亡总人数的 41%(CDC)。在欧盟,过去 10 年中,骑自行车者的死亡率保持不变,而汽车司机和乘客的死亡率下降了 24%。行人中下降了 19% [8]。英国是仅有的 3 个行人死亡率上升的欧盟国家之一,每年上升 1.3%。欧盟平均每年下降 2.6%。在英国,骑自行车者的死亡人数下降了 1.3%,年平均下降率排名第 13 位。鉴于 99%的行人被机动车撞死,1%的行人被自行车撞死,显然有必要提高骑自行车者的安全,并增加他们在街上的数量。同时,这也促进了数量上的安全:如果骑自行车的人越多,他们就越安全。驾驶员通过更频繁地与骑自行车的人接触而形成的意识是根本原因。

推广步行和骑自行车作为替代交通方式,对个人、公司和社区都有很多经济效益。根据 2015 年城市交通记分卡,2014 年美国的拥堵成本为 1600 亿美元。估计每人每年需要 960 美元。这些值考虑了时间和燃料费用。据计算,2018 年在美国拥有一辆汽车的成本是 8849 美元,而自行车是 308 美元,步行被认为是免费的。2018 年基准报告补充说,自行车旅游在全球多个地区具有积极的经济影响。受保护的自行车道意味着商业报告显示了骑自行车对商业的积极影响。研究发现,平均而言,骑车上班的人比开车上班的人花更多的时间,去公司的次数也更多。此外,在 2011 年的一项研究中,政治经济研究所(Political Economy Research Institute)发现,在自行车专用项目上投资 100 万英镑,平均创造了 11.41 个就业岗位,而在公路专用项目上投资相同金额,平均创造了 7.75 个就业岗位。

减少对不可再生资源的依赖是自行车运动的积极方面之一。据美国环境保护署估计,交通运输部门排放的温室气体最多,占 28%(在美国)。其中,乘用车和轻型卡车占整个运输行业的 60%。此外,众所周知,道路和停车场等结构会显著增加城市洪水、暴雨径流和城市热岛效应的可能性(由于城市中缺少阴影和裸露的土地,它们通常比周围环境的温度更高,这是空气湿度低的结果)。推广自行车将减少对原有基础设施的需求,并减轻一些负面影响。

在一个国家推广骑自行车可以促进公平。由于拥有汽车的高成本,当一个城市优先考虑这些车辆的道路基础设施时,它会给负担不起的低收入家庭带来更高的风险。这在低收入社区尤为重要,据一份缩小差距简报估计,低收入社区只有 50%的道路有人行道,而高收入社区有 90%的人行道。这导致行人和骑自行车的人面临更大的威胁。《新的多数:骑自行车实现平等》报告称,26%的有色人种愿意骑自行车,但出于安全考虑而不骑,相比之下,白人受访者中这一比例为 19%。

体育活动,如骑自行车和散步,对身心健康有许多好处[9]。疾病控制和预防中心报告说,如果公民更加积极,十分之一的过早死亡、八分之一的乳腺癌、八分之一的结肠直肠癌、十二分之一的糖尿病患者和十五分之一的心脏病是可以预防的。它还可以降低冠心病、中风和许多呼吸系统慢性疾病的风险,这些疾病与空气质量密切相关[9]。2018 年空气状况报告指出,超过 1.339 亿美国人生活在臭氧和/或颗粒污染水平不健康的县。这是一个受社区内交通模式影响很大的因素。因此,车辆是美国环境保护署的主要贡献者之一。由于所有这些好处,在人群中提倡较少久坐的生活方式的重要性变得显而易见。

通过促进骑自行车者的安全,整个社会受益。骑自行车的人和行人会更安全。司机将减少他们的通勤时间,并将其转化为社会收益,如降低污染水平和经济损失。

道路安全指标

道路安全指标对于决策至关重要。根据欧洲道路安全宪章,它们使我们能够评估道路的当前状况,观察干预后对事故率的影响,监控其随时间的进展,并预测进一步的发展。

要发挥作用,道路安全指标应符合几个标准:

1.与道路安全的某些方面有关,如道路事故的原因或后果;

2.以可靠的方式衡量;

3.随着时间的推移可以监测;

4.允许道路安全工程师或公共卫生专家设定目标;

5.有助于建立不同安全性能的比较和基准。

所有指标共有六个方面:地理范围、时间跨度、数字格式、表示/可视化、可靠性、准确性、代表性和道路安全的具体“水平”。第一个包括测量发生的地方:组织、城市、地区、国家、欧洲或全球。第二个与分析的时间框架有关:日、周、月、季度、年、十年或更长时间。测量单位由第三个特征表示。它们可以是一个比例、一个百分比或一些其他明确定义的比率。表示描述了数据呈现的方式,例如,以地图、图形或表格的形式。可靠性、准确性和代表性与测量系统的设计和实施相关联。最后,该指标的“级别”因是否考虑以下因素之一而有所不同:碰撞的影响、碰撞后反应、碰撞结果、碰撞原因和预测因素、道路安全政策和措施或安全文化和安全系统。

碰撞结果,包括死亡率、重伤/轻伤率和事故率等指标,是选择下一节介绍的风险因素时考虑的因素。

引入了道路安全指标,以便对最相关的骑自行车者的风险因素进行明确排序

危险因素

为了列出和排列伦敦骑自行车者最相关的风险因素,考虑了事故、伤害和死亡率。在伦敦,骑自行车者的死亡率相对较低(图 2),因此,优先考虑另外两种更具歧视性的骑自行车者。在设计图 3 图表时,事故率和受伤率用于对所有风险因素进行排序。注意,一旦没有找到所有风险因素的通用安全指标,这些排名也有很强的定性和基于经验的成分。

图 22010 年至 2017 年大伦敦地区骑自行车者死亡人数。数据来自[10]。

影响骑自行车者安全的前三个最相关的因素是自行车道的存在、道路速度限制和道路车道宽度。接下来,提供支持图 3 中定义的排名的统计数据。请注意,只有少量涉及骑自行车者的事故被报道[11],因此,以下段落中的统计数据可能无法完全反映真实情况。

自行车道和停放的汽车

自行车道可以分开,也可以位于道路上。

当一辆汽车试图超过一名骑自行车的人时,或者在摔倒的情况下,被撞上时,物理上分离的车道减少了撞车的可能性。骑车人受伤的一个主要原因是糟糕的路面质量导致的摔倒[12] [13] [14]。由于周围没有汽车停放,这些车道将骑车人受伤的风险降低了一半。[15]出于所有这些原因,没有考虑与高速公路限制、狭窄的自行车道宽度、路面质量和停放的汽车相关的风险。

与无车道相比,在道路自行车道的情况下,车辆速度往往较低,且与骑车人之间的相互作用较少[16]。

这使得第一种情况最安全,其次是公路和无自行车道。

自行车道的存在被认为是最具决定性的因素,因为它可以预防许多以前发现的风险。它被认为是风险因素排名中的第一位。

车速

研究发现,在大约 10%的事故和 30%的致命事故中,速度是主要因素之一。车祸中车辆的速度是决定受伤严重程度的唯一最重要的因素。[17]

考虑速度时有两个明显的因素。众所周知,不仅更高的速度会导致事故率、伤亡率的增加,而且速度差异也很大。高速变化的道路更不可预测,一旦它们有利于相遇的次数和超车操作次数的增加。因此,降低速度限制有时可能只会导致车辆平均速度的降低,而不是其变化。[18]

车辆高速行驶所带来的危险的核心是制动距离的增加以及从车辆传递给骑车人的动能。一旦两者都随着速度的平方增加,避免或幸存下来的可能性就会平方减少。[18]

从生物学角度来看,众所周知,在碰撞中,人体只能抵抗有限的动能转移。[19]这一数额因身体部位、年龄组和性别而异。考虑到设计最好的汽车,如果车辆超过 30 km/h,就可以超过这个极限。[20]研究还表明,如果汽车以低于 30 公里/小时的速度行驶,行人在撞车事故中幸存的可能性高于 90%。当以 45 公里/小时的速度被汽车撞上时,生还的几率降低到 50%。[21]或者,当一辆汽车的速度从 30 公里/小时上升到 50 公里/小时时,在撞车事故中幸存的可能性降低了 8 倍。[22]

这被认为是第二个最相关的因素。在靠近低速限制道路的道路自行车道的情况下,与平行交通相关的风险因素被认为是可以忽略的,无论车道的宽度如何。

车道宽度

在英国,推荐的自行车道宽度为 2 米。最低要求是 1.5 米。所有低于 1.5 米的值都被认为太窄,几乎没有余地绕过障碍物,如:碎片、坑洞和排水器。人们经常说,没有自行车道比太窄的自行车道更安全,因为驾车者往往会直接开到车道线上,而骑自行车的人则太靠近路缘。

在道路限速之后,自行车道宽度被认为是以下最重要的因素。每当它被认为是广泛的,交通风险因素没有被考虑。不管道路自行车道的宽度如何,低速限制足以排除所有与交通相关的风险因素。

路灯

排在前 3 位之后,路灯被认为是决定道路安全的最相关的标准。众所周知,它会影响驾驶员和骑车人的反应时间,并使骑车人不容易被注意到,尤其是在不使用任何反光或发光装置的情况下。此外,从骑车人的角度来看,他们不太了解与路面质量相关的其他道路风险。预计它不会在伦敦遇到很多照明不足的道路,因此,它被排在第四位。

路面质量、电车/火车轨道和排水器

正如文献中经常提到的,路面质量是评估安全性时要考虑的一个关键因素。[12] [13] [14]路面质量是指没有自行车道时的道路质量,或自行车道存在时的道路质量。除了排水器和小径的存在,这些是以下最重要的风险因素。这是放置在路灯下一次,有足够的亮度和循环速度适中,它应该不会构成重大威胁。

路口数量和路口可见度

大多数自行车和汽车事故发生在十字路口。在[23]中,报告的百分比是总碰撞数的 60%。此外,作为同一项研究的一部分,街道不以直角相交的十字路口给骑自行车的人带来了额外的危险。在这些地区发生的撞车事故对骑车人造成严重伤害的可能性增加了 31%。主要原因是路口能见度降低。

货车和其他大型车辆

近年来,随着经济发展和消费者需求的增加,城市中的卡车数量也在增加。[24] [25]虽然骑自行车也有同样的趋势,但它们之间的相遇次数却大大增加了。例如,在纽约市,15%的自行车网络与 11%的卡车网络重叠。[26]遭遇次数的增加导致卡车事故和死亡率的增加。卡车-自行车事故通常比其他类型的事故后果更严重。[27] [28] [29] [30]在一些欧盟国家,30%的骑自行车死亡事故与卡车有关。[31]过去 20 年的研究表明,在伦敦,卡车是导致骑自行车者死亡的最常见的交通工具。[28] [32] [33]

提前停止线

比利时、丹麦和英国等几个欧洲国家都有这种线路,当交通信号从红色变为绿色时,允许某些类型的车辆(即自行车)先行。这有几个好处。首先,线后的驾驶员可以清楚地意识到他们周围有骑自行车的人,并采取正确的预防措施来避免危险的操作。第二,对于一个骑自行车的人来说,向左转弯以避免与后面的车相撞变得更加安全。在事故、伤害或死亡率的统计数据方面,没有发现任何问题。

弯道能见度

几个来源确定弯曲是一个风险因素。弯道和十字路口通常被认为对骑自行车的人构成类似的危险。在骑自行车的人看来,低能见度会造成通常不会出现的危险情况——突然出现行人或侵入的植物。从驾驶员的角度来看,这可能会使骑自行车的人不被注意到,从而成为易受攻击的因素。[12]没有明确的统计数据显示弯道如何影响骑自行车者的事故、伤害或死亡率。

行人

在所有年龄组中,与 15 至 64 岁或 65 岁以上的成年人相比,行人死亡事故最常发生在 14 岁以下的儿童身上。从性别来说,男性比女性的风险更大。[34]由于这些原因,符合这些标准的人口高度集中的地点(例如学校地区)面临额外的风险。然而,在无车区,行人和骑自行车的人之间的事故极其罕见,而且几乎从不严重。[35]这被认为是最不重要的风险因素。

考虑图 3,从图的左到右,风险因素的数量减少。最不安全的情况是没有自行车道。第二,在公路场景中窄车道的高速度限制。第三,高速限制,但车道更宽。第四,无论道路上的车道是宽还是窄,都要限速。最后,物理隔离车道被认为是最安全的场景。

在接下来的两节中,我们将介绍用于从影像中捕捉对象和结构的工具。

图 3 确定了伦敦道路上 5 种情况下骑自行车者的风险因素。

目标检测

OD 是一种与图像处理和计算机视觉领域密切相关的计算机技术。它用于图像注释、活动识别、人脸检测、人脸识别、视频对象共同分割和对象跟踪等任务[36]。

每个对象都有一组特殊的特征,有助于将其分类为属于特定的类。例如,当寻找圆形或矩形时,在角上弯曲或垂直的物体被搜索[36]。

用于 OD 的方法属于这两类中的一类:基于机器学习或深度学习的方法。在第一种情况下,最相关的特征列表被先验地定义。支持向量机是一个可能的例子。相反,在深度学习方法中,可以在不指定相关特征的情况下执行端到端 OD(yolov 5)。卷积神经网络是典型的例子[36]。

YOLOv5

YOLOv5 是 YOLO 的最新版本,最初由 Joseph Redmon 开发。第一个版本运行在一个名为 Darknet 的框架中,这个框架是为了执行 YOLO [37]而特意构建的。

版本 5 是第二个不是由原作者开发的模型(在版本 4 之后),也是第一个在最先进的机器学习框架中运行的模型——py torch[6]。

YOLOv5 GitHub 储存库包含 MS Coco 数据集中的预训练模型。此外,在相同数据集上进行基准测试(图 4 ),以及关于如何使用不同数据执行或重新训练的详细文档。

图 4 最新的 YOLO 车型是版本 5(2020 年 7 月)。发布时有 4 组不同的砝码,精确度和存储要求各不相同。 EfficientDet (最精确的 OD 模型)的出现凸显了 YOLOv5 的检测速度,同时保持了同样的高精度[6]。

在表 1 中,对每套 YOLOv5 砝码的精度、速度和存储要求进行了比较。

表 1yolov 5 发布的所有砝码组的规格。通常,随着平均精度的提高,需要 GPU 执行更多的处理能力。改编自[6]。

YOLOv5 的架构由三个重要部分组成,就像任何单级物体探测器一样:模型主干、颈部和头部。第一种用于提取给定输入图像的主要特征。在版本 5 中,使用跨级局部网络。这些研究表明,使用更深的网络,处理时间有了显著的改善。模型颈部面板用于获得特征金字塔,并有助于在对象缩放上概化模型。最终的检测部分由模型的头部执行(与 YOLOv3 和 YOLOv4 中相同)。它在要素上应用锚框,并生成输出向量,包括类别概率和边界框。

每个潜在的检测都有一个相关的置信度得分。这表明模型对边界框内对象的存在有多确定,同时,该框是否正确地捕捉了它。

由于 YOLOv5x 的高精度和高速度,选择该模型来处理 GSV 数据集。

图象分割法

在计算机视觉和图像处理中,是指将数字图像分割成多个像素段或像素组的过程。目标是将图像表示简化到可以轻松检索多个结构的程度。更准确地说,这是给图像中的每个像素分配一个标签的过程,并且具有相同标签的像素共享一些特征。因此,这种方法提供了关于某些结构的存在、它们在图像中的形状和位置的信息[38]。

PSPNet101

金字塔场景解析网络(PSPNet)是最精确的信息系统模型之一。它赢得了 ImageNet 场景解析挑战赛 2016、PASCAL VOC 2012 基准测试和 Cityscapes 基准测试。它在 PASCAL VOC 2012 上达到了 85.4%的 mIoU 准确率,在 Cityscapes 上达到了 80.2%的 mIoU 准确率[7]。从那时起,细分模型的准确性在过去的两年里达到了一个稳定的水平(图 5)。

图 5 信息系统模型随时间的演变。自 2017 年以来,平均 IoU 的增幅非常小[39]。

在接收到输入图像后,PSPNet 执行卷积神经网络(CNN)以从最后的卷积层提取特征图。然后,金字塔解析模块用于获取不同的子区域表示,接着是上采样和级联层,以创建最终的特征表示。这携带了本地和全局上下文信息。在最后一步中,该表示被送入卷积层,并获得最终的每像素预测。

由于 IS 模型的执行时间很长,所以它被选为速度最快、精度最高和文档最好的模型。

训练数据集

有多个带有标记对象和分割图像的可用数据集。对于 OD 模型训练和基准测试,两个最常用且包含最多道路类别的是 MS Coco [40]和 Open Images V6 [41]。同样,对于 IS 来说,Cityscapes [42]和 ADE20K [43]是当前最先进的数据集。在表 2 中,所有 4 个项目被放在一起,并根据其相关类别进行比较,以评估骑自行车者的道路安全性。

表 24 个最大 OD 和 IS 数据集之间的比较,以及评估道路安全的相关数据。

一些道路安全对象可以直接提取,其他的可以间接提取。这同样适用于分段结构。表 2 中不带星号的特性代表其动态行为。因此,在同一地点,它们的数量会随着时间的推移而变化。

在 OD 类别中,确定了以下骑自行车者风险因素:汽车和停车计时器用于计算停放的汽车。行人专用区。卡车和公共汽车为卡车流通。数字自行车运动员的自行车。交通灯和停车标志的车速,一旦他们是交通平静的因素。最后,列车T3 因为有轨电车/火车的存在而产生了紧密的关联。对于 IS,道路、人行道和街灯分别用于检索道路和人行道宽度以及街灯。**

可可女士

Microsoft Coco 是用于 OD、分段和字幕的最大和最受欢迎的数据集之一。它包含 330K 个图像,其中 200K 被标记。存在 150 万个标记对象,分布在 80 个类别中。图 6 包含一些标记对象的例子。该数据集包含几类日常物品,从家用电器到道路上最常见的物品[40]。

图 6 (上)MS Coco 数据集中带注释的图像示例。(底部)每个图像中存在的对象[40]。

城市景观

Cityscapes 数据集侧重于对城市街道场景的语义理解。它包含了来自德国、法国和瑞士 5 0 个城市的 20 000 幅粗略的注释图像和 5 000 幅精细的注释。这些照片是在几个月(夏季、春季和秋季)、良好/中等天气条件下和白天拍摄的。共有 30 类结构(图 7) [42]。

图 7 城市景观中可用的三个分割图像示例【42】。

Coco 女士和 Cityscapes 数据集最具互补性,相关对象和道路结构的数量最多。在这两个数据集中预先训练的 YOLOv5 和 PSPNet101 模型分别用于检测对象和分割图像。

方法学

本节将详细介绍如何使用 YOLOv5 和 PSPNet101 模型存储和处理 GSV 影像数据集。各个参数的选择。另外,用来执行它们的软件和硬件。

GSV 影像数据集

没有考虑伦敦的道路安全分析,而是选择在 LSOA 层面进行。大伦敦可以分为多个更小的区域:输出区、中间层超级输出区和 LSOA。伦敦的每一个分区在地理尺度上都有所不同。从伦敦数据存储库获得了包含这些部门的多个 shapefiles 的 zip 文件夹。

Emily Muller 在这个项目开始之前使用 Google API 获得了 GSV 影像数据集。将每个图像标识与给定的伦敦 LSOA 相关联的单独文件也是可用的。

由于高内存需求,本项目中使用的所有图像都存储在帝国服务器中。使用 Globus 平台访问研究数据存储中的图像。

YOLOv5

为了执行 YOLOv5,使用了 Imperial 的高性能计算集群。它是使用 VPN 连接工具— Tunnelblick 远程访问的。

由于 YOLOv5 的执行速度,它使用了一个单独的 P1000 GPU。选择了最精确的砝码组— YOLOv5x。

定义每次检测的最小置信度为 0.5。高于标准值 0.4。仅保存包含检测到的对象和各自位置的文本文件。每一行包括每个对象的数字名称,用空格分隔的是检测框中心的坐标,以及矩形的宽度和高度的两个值。

使用 MatplotlibSeaborn Python 可视化框架,绘制了前 15 个最常检测到的对象的相关性矩阵。使用 SciPy pearsonr 函数获得 Pearson 相关因子和 p 值。

Pandas DataFrame 用于绘制前 15 个最常检测到的物体的相对和绝对分布直方图。

错误分类、局限性和未来方向分析侧重于以前确定的与道路安全相关的物体。此外,所有观察结果均来自对伦敦所有 LSA 的一幅图像的单独评估,以及整体项目经验。

PSPNet101

尽管 Esra Suel 已经提供了执行 PSPNet101 的初步版本,但仍进行了修改以克服与 TensorFlow 新版本的不兼容性。

通常,IS 方法比 OD 慢。最初它是用 Python 多处理工具来加速执行的。最后,原始 GSV 数据集被分成 13 批,在 13 个 P100 图形处理器上并行执行。通过这种方式,向 HPC 提交了 13 份工作。与其他可用的 GPU 相比,P100 因其对数值分析的高处理能力而被选中(表 3)。

表 3 帝国高性能计算集群上可用的 GPU 类型。在这个项目中使用了 P100。

GSV 数据集中的所有图像都被分割。之后,实现了两个 Python 函数。它生成一个字典,将每种 RGB 颜色链接到一个给定的对象类。另一个是接收分割图像的完整数据集作为输入,并输出每个类别的标记像素的总数。使用Pandas**data framePython 库分析并表示所有标签的相对和绝对分布。

错误分类、局限性和未来方向分析侧重于之前确定的与道路安全相关的结构。此外,所有观察结果均来自对伦敦所有 LSOAs 的一幅图像的单独评估,以及整体项目经验。

结果和讨论

在这一节中,结果与讨论一起呈现。首先,提供了伦敦所有 LSOAs 的 GSV 影像数据集的概述。然后,分析 OD 和 IS 输出。

GSV 数据集

GSV 数据集包含分布在大伦敦地区的 518 350 幅图像。有 512 812 张照片被认定为伦敦 LSOA。其中,478,724 个是独特的(表 4)。

表 4 并非 GSV 数据集中的所有图像都是 LSOA 识别的。因此,在分析中使用了一个较小的集合— 478 724。

对于每个数据点,有 4 个图像可用,范围从 0 到 360 度。有 119 681 个独特的 LSOA 识别点,每个点有四个 90 度图像(图 8)。

图 8 对于图 9 中的每个数据点,有 4 个相关的图像。每个捕捉周围环境的 90 度角。

伦敦市中心附近有更多可用的图像,向外围递减。在图 9 中,显示了一个 LSOA 地图集,以及所有图像各自的地理分布。

图 9 (左)也根据可用图像的数量进行着色。(右)同一组图像的地理分布(纬度和经度)。

数据点数量最多的 LSOA,211 个,位于伦敦市中心。平均而言,每个 LSOA 有 27 个数据点可用。数据集中有一个只有 1 的 LSOA(表 5)。图像数量的广泛分布损害了较少表示的 LSOAs 中对象和分割结构数量的估计精度。

表 5 伦敦所有 lso 数据集中 GSV 点的可用性。

物体检测| YOLOv5

图 10 提供了运行 YOLOv5 后的图像示例。图像中的所有汽车、卡车和人都以高置信度值被准确地检测出来。

图 10 执行 YOLOv5 后的 GSV 图像示例。

接下来,所有对象的相对和绝对分布在数据集级别呈现。

数据集对象分布

图 11 显示了前 15 个最常检测到的物体类别的相对分布。

图 11 在所有 LSOAs 中检测到的前 15 个对象的相对分布。

一旦数据集只包含街景图像,就有望检测到很大一部分汽车。伦敦是一个人口密度很高的城市,公共交通很普遍。这可以解释为什么有这么多的行人和公共汽车。盆栽植物检测与伦敦公园和绿地的数量密切相关。

表 6 包含在 GSV 数据集中检测到的前 15 个最常见物体的绝对数量。用绿色突出显示的是那些被认为对骑自行车者的道路安全有积极贡献的道路。红色的是负面因素。

除了表 6 中的彩色风险因素对象,还考虑了火车(657)和停车计时器(968)来提取图 3 中的风险因素。

表 6 前 15 个最常检测到的物体的绝对计数。用于提取骑自行车者道路安全系数的物体是有颜色的。

LSOA 物体分布

图 12 显示了与捕捉骑自行车者风险因素相关的物体的 LSOA 分布。

图 12 检测到伦敦所有 LSOAs 上的对象分布。另外,在每个图谱的底部有各自的分布直方图。

大多数自行车是在伦敦市中心被发现的。一旦这是一种短距离的交通工具,他们基本上是在这个地区被发现的。公共汽车在伦敦市中心比在外围地区稍微集中一些。远离市中心的卡车数量较多。对于市中心的许多道路,根据伦敦卡车控制计划,它们的流通是被禁止的。

公共汽车和卡车分布都是长尾分布,增加了意外发生的几率,使骑自行车的人面临更高的风险。

伦敦市中心以外的汽车分布密度要大得多。远离中心的道路有更多的车道,这可能意味着检测到这些物体的机会更高。市中心的停车计时器越少,这个地区的汽车数量就越多。在中心检测到的人数要多得多。尤其是在它所在的城市伦敦,它是历史中心和中央商业区。停止标志和交通灯基本上是在伦敦市中心之外发现的。两者具有非常相似的直方图分布。虽然,检测到的红绿灯数量几乎多了五倍。

相关矩阵

在道路安全方面,最强的正相关性是:人 x 自行车(0.52)、人 x 公共汽车(0.48)、公共汽车 x 自行车(0.25)和公共汽车 x 卡车(0.20)。负相关性最强的是:人 x 车(-0.23)和自行车 x 车(-0.20)(图 13)。

图 13 前 15 位检测到的对象关联矩阵。每个像元包含皮尔逊相关系数(顶部)和相关的 p 值(底部)。

就正相关而言,人 x 自行车高值表明行人和骑自行车的人在同一空间感到安全。

一旦公共汽车成为公共交通工具,预计周围会有很多人。因此,人员 x 公共汽车的皮尔逊系数相对较高。自行车 x 公交车和自行车 x 卡车的相关值有显著差异。

这可能表明骑自行车的人在公共汽车旁边比在卡车旁边感觉更安全。

一旦公共汽车司机在靠近易受伤害的行人时更有经验,这就不足为奇了。公共汽车和卡车之间相对较高的相关性,以及结构相似的事实表明,有时一个可能会被错误地归类为另一个。

对于负相关,人 x 汽车和自行车 x 汽车的具有统计显著性的皮尔逊系数表明,汽车高度集中的区域不利于骑自行车和步行。

一个不可忽视的因素是,较大的物体遮挡较小的物体可能导致较小的物体不易被探测到。因此,导致负相关。由于 GSV 图像是在离地面很高的地方拍摄的,这不太可能是经常发生的现象。

整体自行车安全指标

没有发现一种精确的度量来基于在伦敦道路上检测到的物体来估计骑车人的道路安全。虽然,根据图 12 中的对象分布,制定了一个正的和另一个负的组合安全措施。

影响骑车人安全的特征之一是周围其他骑车人的数量。发生这种情况是因为司机在大量出现时会更加意识到他们的存在。此外,绝大多数严重伤害是由车辆和骑自行车的人相撞造成的。人们发现,在汽车和人的存在之间存在着统计上显著的负相关关系。这样,行人越多,汽车越少。因此,骑车人受伤的风险更小。

**自行车在对每张图像中这些物体的平均数量求和后,合二为一,作为一种积极的安全组合措施。

如果汽车是伤害率的主要来源,那么在分析某个地区的死亡率时,重型车辆就显得尤为重要。

创建第二个 LSOA 地图,加入以下对象的每个图像的平均数量:公共汽车汽车卡车,作为安全性的负组合测量

需要强调的是,我们无法从这两个生成的 LSOAs 中提取整体的安全性指标(图 14)。一个简单的例子是,骑自行车的人与交通隔离的道路不一定对骑自行车不安全。

图 14 (左)自行车人* LSOA 分布被组合成一个组合指标,反映了骑自行车者安全性的积极得分。(右)公交车小汽车卡车分布组合成最终的地图集,展示伦敦的交通。这与骑车人的安全成反比。*

限制和错误分类

所有检测到的道路安全物体都有很高的可信度(图 12)。YOLOv5 可以检测各种大小的物体,即使在部分遮挡的情况下也是如此(图 15)。此外,对象和背景之间的低对比度似乎没有导致大量的未检测。这方面的一个例子是,该算法检测到伦敦道路上的一辆汽车反射在窗户上(图 10)。然而,这被认为是一种分类错误——各种分类错误。

它汇编了一组 10 个随机物体检测图像,以便读者可以自己验证 YOLOv5 的准确性(图 15)。

图 15 来自不同 LSOAs 的十个随机选择的对象检测图像显示了在 MS Coco 类别中的高检测准确度。

图像分割| PSPNet101

图 16 提供了一个分割图像的例子。用检测到的结构的各自标签来识别它。

图 16 使用 PSPNet101 分割后的 GSV 图像。包括了像素标签。

下一节将详细介绍 GSV 数据集中的绝对和相对标注分布。

数据集像素标签分布

建筑物(27%)、天空(22%)、道路(22%)、植被(18%)和汽车(6%)覆盖了所有图像总面积的 95%(图 17)。在前四种结构的情况下,这是由它们的内在尺寸来解释的。一旦这个数据集只包含从伦敦的道路上获得的图像,它就会比任何其他对象找到更多的汽车。这个像素频率数不仅与它们的大小有关,还与它们在图像中的频率有关。这样看来,OD 和 is 似乎是一致的。

图 17GSV 数据集中执行 PSPNet101 后标记像素的相对分布。

跨不同类别的分割像素的相对分布还表明,不仅可以检测道路上存在的对象,而且可以检测周围环境中的对象,包括建筑物和天空中的对象。

虽然没有发现以下一些物体与道路安全有明显的相关性,但它们显示了使用 GSV 图像在广泛的位置检测结构的能力。嵌入建筑景观中的 2 750 个钟被错误地归类为碟形卫星天线。在同一地区,发现了 37 917 株盆栽植物。天空中发现了 234 架飞机。检测到大量标记为人行道的像素后,表明可能会捕捉到经常出现的对象(发现了 107 266 人,以及 5 013 条长凳和 1 168 个消防栓)。

表 7 中是由 19 个分段类别分布的所有像素标签的绝对计数。

表 7 在所有影像数据集中检测到的标记像素的绝对数量。

同样,从 IS 的角度来看,由于检测到的像素数量相对较高且形状一致,GSV 数据集似乎有助于估计道路和人行道的面积。这同样适用于路灯。尽管只有 3.03 亿像素被识别出来,但这个物体的尺寸表明,其中相当大一部分应该已经被探测到了。

在对完整数据集的每个 LSOA 的一个分割图像进行单独分析后,似乎可以准确地检索道路和人行道的面积和形状。

正如在简介中所指出的,最后这些属性与道路安全相关,因为它们允许计算道路和人行道宽度。街灯或电线杆的存在,正如他们在城市景观中所称的,是评估道路能见度的一个代理。

在图 18 中,这些概念连同侧面的说明性图像一起被举例说明。

图 18 信息图展示了提取道路和人行道宽度以及街灯的潜力。

限制和错误分类

由于某些结构的尺寸,PSPNet101 无法准确捕捉它们的形状。一个例子是极细,因此它们的检测受数据集中图像分辨率的影响很大。一旦对这些结构最重要的是它们的检测而不是捕捉它们的形状,这就不是特别大的问题。

就道路和人行道而言,有时堵塞似乎是一个问题。然而,通过考虑通常出现在这些区域中的对象,同时考虑它们的重叠区域似乎是一种有效的变通方法。具体来说,这是在路上的汽车和人行道上的人身上观察到的。通过这种方式,仍然可以提取这些结构的形状和大小的信息。

提取伦敦道路上这些建筑的绝对尺寸可能是一项艰巨的任务。根据拍摄图像的角度,标准可以有很大的不同。克服这个问题的一个方法是关注对象之间的相对维度(图 19)。

图 19 来自不同 LSOAs 的随机分割图像的小样本显示了在捕捉尺寸和形状时考虑结构遮挡的重要性。

未来方向

对于 OD 而言,在评估骑自行车者的道路安全方面向前迈出的一步是找到一个共同的道路安全指标,允许我们比较,例如,在事故或伤害率方面,物体如何不同地影响安全。在更大的数据集中训练 YOLOv5,并且比 Coco 女士有更多的对象类别。这将涉及注释额外的图像。关于如何训练 YOLOv5 的文档非常详细且易于掌握。静态图像不能捕捉几个特征。使用包括行人、骑自行车者和车辆运动在内的视频记录将允许捕捉受图像获取时间高度影响的变量。

就信息系统而言,这些模型可以专门用于检测新的物体。

自行车道的存在是决定骑自行车者道路安全的一个因素。没有找到任何包含这些内容的数据集。创建一个包括这一类别的对评估它们的安全性是非常重要的。

虽然我们没有发现人行道是否与骑自行车者的安全相关的证据,但在未来,证明存在关联,在城市景观中预先训练的 PSPNet101 将能够捕捉到它。

图 18 总结了可使用 PSPNet101 在 GSV 数据集中提取的所有道路安全信息(在本项目中确定)。

结论

该项目的目标是使用 OD,从大伦敦的 GSV 影像数据集中提取骑自行车者的道路风险因素。这包括对所有 LSOAs 的图像分布的研究。确定相关的道路安全指标,以确定骑自行车者的风险因素并对其进行分级。使用 YOLOv5 和 PSPNet101 检测物体和分割图像。分析不同类别之间的对象分布和相关性。最后,找出两种方法的常见错误分类和局限性,并提出推进道路安全评价的新方法。

在数据集中可用的 50 万幅图像中,识别了大约 200 万个对象,标记了 2000 亿个像素。平均每个 LSOA 有 108 张图片。使用 YOLOv5,在 LSOA 水平上直接确定了以下风险因素的分布:高车辆速度、电车/火车轨道、卡车流通、停放的汽车和行人。汽车(占所有物体的 84.5%)、人(6.01%)、卡车(3.92%)、公共汽车(0.60%)、交通信号灯(0.4%)、停车标志(0.07%)、停车计时器(0.05%)和火车(0.04%)计数用于识别先前的风险因素。伦敦市中心以外的道路交通流量较高。相比之下,该区域内骑自行车者和行人的比例更高。前者被定义为一个消极的组合安全措施,第二,积极的。研究发现,汽车与公共汽车、汽车与骑自行车的人以及汽车与人之间存在显著的负相关。人 x 自行车和人 x 公交车的正相关。重型车辆(公共汽车和卡车)数量呈长尾分布。使用 PSPNet101,建筑物(27%)、天空(22%)和道路(22%)像素是最常见的。因此,在这些区域中的任何一个中的物体都可以被同等地检测到。所有的结果和实现都可以在项目的库中获得。

未来的方向包括提高 GSV 图像的可用性和分辨率。使用包含更多道路安全相关类别的数据集训练 YOLOv5 和 PSPNet101。定义一个安全度量来加权和组合(在道路级别)检测到的对象或分段结构。最后,实时处理街景图像或视频将允许更好地捕捉道路安全的动态(视频)。

YOLOv5x 实时执行。

文章 | GitHub 资源库

参考

[1]“pedbikeinfo”,行人和自行车信息中心,[在线]。可用:http://www.pedbikeinfo.org/.【Acedido em 2020 年 4 月 19 日】。

[2] C. Allan,“骑行英国的骑行统计”,2019 年 11 月。【在线】。可用:【https://www.cyclinguk.org/statistics. 【Acedido em 2020 年 8 月 19 日】。

[3]“20 亿英镑创造自行车和步行新时代”,英国政府,2020 年 5 月 9 日。【在线】。可用:https://www . gov . uk/government/news/20 亿包创造骑行新时代。【Acedido em 2020 年 8 月 19 日】。

[4] S. M. Balogh,“骑自行车者的感知安全性——道路属性的作用”,瑞典斯德哥尔摩 KTH 皇家理工学院,2017 年。

[5]“谷歌街景报道”,维基百科,2020 年 8 月 14 日。【在线】。可用:https://en . Wikipedia . org/wiki/Coverage _ of _ Google _ Street _ View。[2020 年 8 月 19 日]

[6] G. Jocher,“YOLOv5”,Ultralytics,2020 年 7 月 23 日。【在线】。可用:https://github.com/ultralytics/yolov5.【Acedido em 2020 年 7 月 23 日】。

[7] J. S. X. Q. X. W. J .赵恒爽,《金字塔场景解析网络》,em 计算机视觉与模式识别,2017。

[8] E. R. S .观察站,“2018 年交通安全基本事实”,欧洲委员会,2018 年。

[9]美国疾病预防控制中心营养部,“身体活动”,2019 年 2 月 4 日。【在线】。可用:https://www . CDC . gov/physical activity/about-physical-activity/pdf/healthy-strong-America-2019 02 _ 508 . pdf【Acedido em 19 April 2020】。

[10] T. f .伦敦,“伦敦之旅,报告 11”,2018 年。

[11]安全网,“行人和骑自行车者”,2009 年。【在线】。可用:https://EC . Europa . eu/transport/road _ safety/sites/road safety/files/specialist/knowledge/pdf/行人. pdf【Acedido em 13 May 2020】。

[12]“自行车设施”,iRAP,[在线]。可用:http://toolkit.irap.org/default.asp?page=treatment&id = 1。[2020 年 4 月 8 日]

[13]“道路安全委员会”,西澳大利亚政府,[在线]。可用:https://www . RSC . wa . gov . au/RSC/media/Documents/Resources/cyclers-INFO-sheet . pdf .【Acedido em 2020 年 4 月 8 日】。

[14]《自行车安全》,美国国家公路交通安全管理局,[在线]。可用:【https://www.nhtsa.gov/road-safety/bicycle-safety. 【Acedido em 2020 年 4 月 8 日】。

[15] K. T. e. al,“路线基础设施和骑自行车者受伤的风险:病例交叉研究”,《美国公共卫生杂志》,,第 102 卷,第 12 期,第 2336-2343 页,2012 年。

[16] L. Chen,C. Chen,R. Srinivasan,C. E. McKnight,R. Ewing e M. Roe,“评估纽约市自行车道的安全效果”,《美国公共卫生杂志》,第 102 卷,第 6 期,第 1120-1127 页,2012 年。

[17]“骑自行车——防止受伤”,维多利亚州政府,2013 年 11 月。【在线】。可用:https://www . better health . vic . gov . au/health/health yling/cycling-preventing-injury。【Acedido em 2020 年 5 月 7 日】。

[18]“速度和事故风险”,欧洲委员会,2020 年 5 月 8 日。【在线】。可用:https://EC . Europa . eu/transport/road _ safety/specialist/knowledge/speed/speed _ is _ a _ central _ issue _ in _ road _ safety/speed _ and _ accident _ risk _ en。[2020 年 5 月 8 日]

[19]“人体可以容忍哪些力量?,“欧盟委员会,流动性和运输,2020 年 5 月 9 日。【在线】。可用:https://EC . Europa . eu/transport/road _ safety/specialist/knowledge/vehicle/key _ issues _ for _ vehicle _ safety _ design/what _ forces _ can _ be _ tolerated _ the _ human _ body _ en。【2020 年 5 月 9 日 Acedido em】。

[20] C. a. H. N. Tingvall,“零视野——安全和机动性的道德方法”,em 第六届 ITE 国际道路安全会议&交通执法:2000 年以后,墨尔本,1999 年。

[21] E. Pasanen,“驾驶速度和行人安全”,1991 年。

[22] S. M. G. Ashton,“从车辆外部设计变化中获益”,em 汽车工程师学会会议录,密歇根州底特律市,1983 年。

[23] V. S. M. R. e. a. Asgarzadeh M,“交叉口和街道设计对自行车-机动车碰撞严重程度的作用”,伤害预防,第 23 卷,第 179–185 页,2017 年。

[24] L. Dablanc,“欧洲大城市的货物运输:难以组织,难以现代化”,运输研究 A 部分:政策与实践,第 41 卷,第 3 期,第 280-285 页,2007 年。

[25] M. Jaller,j . hol guín-Veras e . s . Hodge,“城市中的停车:货运交通的挑战”,交通研究记录:交通研究委员会杂志,第 2379 卷,第 46–56 页,2013 年。

[26] A. Conway,N. Tavernier,V. Leal-Tavares,N. Gharamani,L. Chauvet,M. Chiu e X. Bing Yeap,“自行车友好城市中的货运”,运输研究记录:运输研究委员会杂志,第 2547 卷,第 91–101 页,2016 年。

[27] J.-K. Kim,S. Kim,g . f . Ulfarsson e . l . porre llo,“自行车-机动车事故中骑车人受伤的严重程度”,事故分析&预防,第 39 卷,第 2 期,第 238-251 页,2007 年。

[28] J. Manson、S. Cooper、A. West、E. Foster、e . Cole e . n . r . m . Tai,“重大创伤和城市骑自行车者:生理状况和伤害概况”,《急救医学杂志》,第 30 卷,第 1 期,第 32–37 页,2012 年。

[29] S. Kaplan,k . Vavatsoulas e . c . g . Prato,“与丹麦骑车人伤害严重程度相关的加重和减轻因素”,《安全研究杂志》,第 50 卷,第 75–82 页,2014 年。

[30]p . Chen e . qi . Shen,“在涉及汽车的自行车碰撞中,建筑环境对骑车人伤害严重程度的影响”,事故分析&预防,第 86 卷,第 239-246 页,2016 年。

31 p . e . al,“交通研究程序”,第 25 卷,第 999-1007 页,2017 年。

[32]m . McCarthy e . k . Gilbert,“1985-1992 年伦敦骑车人道路死亡:驾驶员、车辆、操纵和伤害”,事故分析&预防,第 28 卷,第 2 期,第 275-279 页,1996 年。

[33] A. S. Morgan,H. B. Dale,w . e . Lee e . p . j . Edwards,“伦敦骑自行车者的死亡:1992 年至 2006 年的趋势”, BMC 公共卫生,第 10 卷,n . 669,第 1-5 页,2010 年。

[34] P. Tuckela,w . Milczarskib e . r . mais elc,“纽约州和加利福尼亚州与自行车碰撞造成的行人伤害”,《安全研究杂志》,第 51 卷,第 7-13 页,2014 年。

[35] D .杜福尔,“欧洲委员会——智能能源欧洲”,2010 年 2 月。【在线】。可用:https://EC . Europa . eu/energy/intelligent/projects/sites/iee-projects/files/projects/documents/presto _ fact _ sheet _ cyclers _ and _ 行人 _ en . pdf .【Acedido em 2020 年 5 月 11 日】。

[36]“对象检测”,维基百科,2020 年 7 月 24 日。【在线】。可用:https://en.wikipedia.org/wiki/Object_detection.【Acedido em 2020 年 8 月 19 日】。

[37] J. Redmon,S. Divvala,r . gir shick e . a .法尔哈迪,“你只看一次:统一的实时物体检测”,em 计算机视觉与模式识别,2016 年。

[38]“图像分割”,维基百科,2020 年 7 月 6 日。【在线】。可用:【https://en.wikipedia.org/wiki/Image_segmentation. 【Acedido em 2020 年 8 月 19 日】。

[39]“城市景观测试中的语义分割”,带代码的论文,[在线]。可用:https://papers with code . com/sota/semantic-segmentation-on-city scapes。[2020 年 8 月 18 日]

[40]m . m . s . b . l . b . r . g . j . p . p . d . r . c . l . z . p . d .宗-林逸,“微软可可:上下文中的公共对象”,em 计算机视觉和模式识别,2014 年。

[41]h . r . n . a . j . u . I . k . p .-t . s . k . s . p . m . a . k . t . d . v . f . a . kuznet sova,“开放图像数据集 V4:统一图像分类、对象检测和大规模视觉关系检测”,Resultados da procura Resultado da Web com liga es entre sites 国际计算机视觉杂志,* 2020 年。*

[42]m . o . s . r . t . r . m . e . r . b . u . f . s . r . b . s . m . Cordts,“语义城市场景理解的城市景观数据集”,em Proc .2016 年 IEEE 计算机视觉和模式识别会议

[43]海珠西航局,周,“通过 ADE20K 数据集进行场景解析”,em 计算机视觉与模式识别,2017。

[44]“概况介绍:骑自行车者的安全”,欧洲委员会,[在线]。可用:https://EC . Europa . eu/transport/sites/transport/files/themes/urban/doc/cycler _ safety _ one pager . pdf【Acedido em 2020 年 4 月 8 日】。

[45]“自行车骑手安全”,维多利亚州交通资源,[在线]。可用:https://www . vic roads . vic . gov . au/safety-and-road-rules/cycler-safety/bike-rider-safety。[2020 年 4 月 8 日]

[46]“驾驶和自行车安全”,伦敦交通局,[在线]。可用:https://tfl . gov . uk/travel-information/safety/road-safety-advice/driving-and-cycling-safety。[2020 年 4 月 8 日]

附录

YOLOv5 |检测到的对象

该项目的主要目标之一是展示街景图像的潜力。给定一个大型数据集,可以提取大量信息。

在分析所有处理过的 LSOAs 图谱时,发现了两个说明这种技术潜力的类别:飞机盆栽(图 20)。

在第一种情况下,在希思罗机场和伦敦金融城机场附近的区域,每幅图像中检测到更高密度的飞机。此外,所有检测到的平面都在这些结构的右侧。这种现象可以用风向西->东来解释,这使得飞机更倾向于从东->西着陆,而事实上着陆比起飞花费的时间要长得多。因此,只有右边拍摄的图像包含它们。最后,每个机场旁边的检测数量差异也很明显。由于希思罗机场的空中交通增加,大部分都在它的附近。

盆栽植物也经常被发现。这些主要出现在伦敦最大的公园附近的图像中。这一类别包括插在任何类型花盆中的所有植物。在执行 PSPNet101 后,植被是整个 GSV 数据集中第二大被标记的像素类型,因此捕获的盆栽植物(第四大被检测对象)的高水平就不足为奇了。

图 20 (左)在最近的伦敦机场附近拍摄的图像中,飞机密度与预期相符。(右图)同样,在最大的公园附近观察到盆栽植物的最大密度。

YOLOv5 |限制和错误分类

对于我们定义为与骑车人道路安全相关的对象,错误分类的数量非常少。这是因为定义了 0.5 的高阈值来计数为检测,并且在 MS Coco 训练数据集中,最常见的对象是我们感兴趣的对象。

尽管如此,还是有一些物品一直被错误分类。最常见的是被检测为时钟的碟形卫星天线。根据角度的不同,臂状碟形天线很容易像一个时钟指针。在完整的 GSV 影像数据集中检测到 2750 个时钟(图 21)。其他较少表现的物体也被错误地识别。有时是因为它们的形状,另一些是因为它们的质地。前者的一个例子是探测船只而不是建筑集装箱,后者是探测长凳而不是栅栏。

图 21 执行 YOLOv5 后发现的最常见的错误分类是检测到了时钟,而不是碟形卫星天线。

项目路线图

图 22 详细描述了这个为期 5 个月的项目中采取的所有步骤。

图 22 项目路线图从 3 月份开始,到 8 月份提交。

监督人

马吉德·埃扎提 | 里基·纳特瓦尼

成为 BigQuery 超级用户

原文:https://towardsdatascience.com/become-a-bigquery-power-user-94089b8cdef2?source=collection_archive---------29-----------------------

帮助你让这种野兽工作的 5 个技巧

BigQuery 是 Google 的分析数据库,它查询大型数据集的速度快得惊人,并且可以让你免费使用。在编写本报告时,处理的前 1TB 数据是空闲的,存储的前 10GB 数据是空闲的。在这篇文章中,我将向你展示一些技巧,告诉你如何充分利用这个神奇的系统。

李坦在 Unsplash 上的照片

BigQuery 是一个分布式系统,它将分布式存储与一个计算集群结合在一起,该集群(通常)会向您的查询并行抛出 2000 个或更多的插槽(vCPUs)。使用这些提示来很好地利用这种力量。

提示#1:使用 Unnest 动态生成测试数据

你会在文档中经常看到这种情况,但可能会让新读者感到困惑。

UNNEST函数让您可以像查询一个表一样查询一个数组字段。数组的每个元素都成为表中的一行。如果数组包含基元类型,结果表将有一列。在下面的示例中,每个数组元素都是一个 STRUCT 字段,它转换为表中的列。

作者图片

提示 2:一次使用 CTE 和多个语句

不要打开多个 BigQuery 控制台窗口,每个窗口都有自己的查询,而是在同一个控制台窗口中编写多个语句,并用分号分隔。您可以通过选择一个或多个查询并点击RUN来单独执行,或者不选择任何内容,然后一次性运行。

作者图片

公共表表达式(cte)对于充分利用 BigQuery 强大的多级聚合分析能力也非常有用。这涉及到 SQL WITH关键字来定义层内存中的临时表,这些表可以随意连接和选择。

提示 3:使用变量

变量可以帮助您将文字分布在多个语句中,并使查询更容易重用。这对于在多个查询或公共表表达式(cte)之间保持日期范围过滤器非常有用。

提示#4:用户定义的函数

除了已经嵌入 BigQuery 的许多函数之外,您还可以定义自己的临时或持久函数。函数可以用 SQL 或 Javascript 编写。后者对于从解析 JSON 到解码 URL 的任何事情都非常方便。让这些计算节点与您的自定义函数一起工作!

请记住,您不能导入模块,但可以引用存储在您的 Google 云存储桶中的库文件。

下面是两个 JS UDF 的例子,一个是利用存储在 GCS 中的库的持久函数,另一个是对数组进行集合操作的临时函数。

JS UDF 示例

提示 5:存储过程

存储过程为您提供了脚本功能,允许您使用 if 和 while 语句控制执行流。

结果如下。很明显,这种能力对于数据转换和重构非常有用。

作者图片

结论

BigQuery 是一个非常强大的数据仓库和分析工具。

  • 使用 BigQuery 来利用 SQL 强大的数组和结构类型
  • 使用 UNNEST 将数组和结构转换成表
  • 将 CTE 用于多级聚合,或者代替高度嵌套的查询,并将多条语句组合在一起执行
  • 使用变量来参数化查询或在连续查询之间传递数据
  • 使用用户定义函数(UDF)使您的查询片段可重用,或者在查询中利用 JavaScript 的强大功能
  • 存储过程可以使常见任务易于重复,并避免代码重复。

它会变得越来越好,所以请关注这个空间,获取更多有用的提示。

2020 年成为数据科学家

原文:https://towardsdatascience.com/become-a-data-scientist-in-2020-d4d806bd934f?source=collection_archive---------37-----------------------

改变职业的一步一步指南。

2020 年是学习数据科学并以此为职业的大好时机。无论你的背景如何,这篇文章都是关于成为一名数据科学家需要做的一些实际的事情。开始吧!

2020 年成为数据科学家

这需要一些时间,但你会成功的。

当我刚开始时,我读了所有关于这个主题的书,但我很快意识到其中许多都过时了。

我现在更喜欢接触真实的数据。

如果你想开始数据科学家的职业生涯,是时候开始收集数据了。

现在有比以往更多的信息和工具可以帮助你收集数据——首先是 Kaggle 的公共数据库,GitHub 的开源代码,Reddit 的许多链接和文章,你可以抓取和重复使用。

获得数据科学的实习机会

当然你不一定要创业才能成为数据科学家。另一个自然的方法是找实习。有很多方法可以获得实习机会,但第一种方法是直接联系招聘公司——在 LinkedIn 上搜索你所在地区的招聘人员,然后给他们写信。他们通常愿意帮助你。

第二种方法是寻找那些想雇佣实习生的公司,并与他们接触,看看你是否能得到实习机会。如果你能展示你的作品,电话推销真的有用(再次 GitHub!).查看公司网站,看看他们是否在寻找数据科学家,或者问问已经在数据科学团队工作的人。

你越主动越好。开始在 LinkedIn 上写你的数据科学项目,并在 Medium 上发布帖子,以获得更多的关注。最理想的情况是当招聘人员找上你,而你是他们要选择的人。唯一的方法是将工作投入到你的开源数据科学项目中,并推广你正在做的事情。

如果这不适合你——因为你对如此公开感到不舒服,这很好——那就开始在许多求职网站和团体上寻找实习机会。这是一个员工市场,如果你能展示出你的参与度和热情,你应该能够得到潜在雇主的初次电话或会面。

GitHub 项目组合

首先,你应该在 GitHub 上建立一个开源项目组合。我建议创建三个项目:

  • 这是一个分类项目,你可以使用图像/文本的公共数据库(你可以从 Kaggle 下载一个——在下一段中有更多的介绍)对它们进行分类,并通过监督/非监督学习(从 PCA 到神经网络,通过 DBScan,KNN 等)磨练你的技能。).
  • 一个 NLP 项目,将分析来自特定主题的推文的情绪,并相应地将它们分类为积极/中性/消极。这是一个经典的问题——选择一个你感兴趣的话题,这样你就有一个好故事来讲述它。
  • 一个搜集项目,你从不同的来源搜集信息——如果你是体育迷,可以搜集体育新闻;如果你对金融或数据科学感兴趣,可以搜集金融波动。最终目标可能是创建一个自动化的网站,提供抓取和提取的内容。很容易在面试中表现出来。

如果你更高级,那么你肯定应该尝试最新的机器学习算法。例如,您可以尝试:

  • GANs(生成敌对网络)并生成了一些脸或猫。
  • 用更简单的游戏强化学习。
  • GPT 新协议和文本生成。

你在这里有无限的机会。你一定要展示你精通神经网络和它们的基本原理,比如 Keras,PyTorch,TensorFlow。

一个很棒的资源是 代码为 的论文,它链接了机器学习论文和 Github 代码。这是在机器学习中找到最新发现的非常有效的方法。

知道自己知道什么,不知道什么

即使这听起来显而易见,你也应该能够回答关于你的知识,特别是技术细节或问题的问题。

实际上,你会被问到的最重要的问题是在一个给定的项目中什么是最难的。如果你遇到了一个特殊的技术问题,为什么和它是什么。你是怎么克服的?这些是你应该准备回答的基本问题。

准备好更详细地谈论算法,你过去用过的不同方法。开诚布公地分享你遇到的问题。这只能在求职面试时有所帮助。

润色你的 LinkedIn 个人资料

数据科学家经常忽略的最后一件事是建立一个连贯的 LinkedIn 个人资料,解释你过去做了什么以及你现在在哪里。如果你在职业生涯中有任何空白,确保你会被问到——在巴厘岛冲浪 6 个月没什么错,你应该诚实地说出当时的动机和你想要实现的目标。我认为一个好的理由是你想离开屏幕休息一下,想重新开始,想成为一名数字流浪者——有很多理由可以解释为什么这个选择对你的职业生涯也是最好的。

你还应该向你以前的雇主征求推荐信。他们可以直接在 LinkedIn 上写——只要几句话就够了。如果你的上一次离职不是真的计划好的,你对此感到痛苦,试着解释为什么,以及你对下一任雇主有什么期望。

你应该能够准确地说出你为什么想换工作。是因为你在寻找新的挑战吗?如果有,为什么你现在的工作不能拥有它们?清晰地讲述你以前的工作经历是一笔巨大的财富。

闪耀!

总结起来,要真正掌握数据科学家职位的面试,你应该做 3 件事:

  • 构建 GitHub 项目组合;
  • 知道每个项目中最难的部分是什么,以及你是如何克服的;
  • 润色你的 LinkedIn 个人资料。

我非常喜欢构建自己的开源 GitHub 项目组合,作为一名数据科学家成长的一种方式。在下一章中,我将讨论一系列项目,如果你对实用数据科学感兴趣,你可以自己尝试。

这些肯定会让你被录用!

数据科学工作

这篇文章摘自我的书数据科学工作:如何成为一名数据科学家,它将从头到尾指导你成为一名数据科学家,无论你的背景如何。

*免责声明:以上链接是我的书的附属链接。

成为抒情天才

原文:https://towardsdatascience.com/become-a-lyrical-genius-4362e7710e43?source=collection_archive---------17-----------------------

使用 Spotify 和 Genius APIs 抓取您的 Spotify 播放列表歌词。

照片来源:马尔特·温根(https://unsplash.com/photos/PDX_a_82obo

不幸的是,我不会说唱或写歌,因此我不能教你如何成为那种抒情天才。我擅长的是向你展示如何使用 Spotify 和 Genius APIs 从你最喜欢的 Spotify 播放列表中获取歌词,并从一些网络抓取中获得一点帮助。除了我在这里概述的方法之外,还有很多其他的方法,但是这是我发现的为数不多的免费且可靠的方法之一。代码的一些部分受到了 Will Soares 在 DEV Community 上写的一篇文章的启发,所以如果你觉得这很有用,请点击这里的并表示赞赏。

下面是我创建的 Python 类,GetLyrics,已经准备好了,可以让你自己试用。只需插入 Spotify 和 Genius APIs 的个人凭据,以及 Spotify 用户和播放列表 id(本文下一节将介绍如何获取所有这些信息),就可以开始了。

从上面的代码片段中可以看到,我们可以在一个列表中得到整个播放列表的歌词,song_lyrics,只需要两行代码。很好。

获取我们的类参数

我们需要做的第一件事是收集我们所有的输入(GetLyrics类参数)。为了初始化这个类,我们需要 5 样东西:

  1. Spotify 客户端 ID
  2. Spotify 客户端机密
  3. Spotify 用户 ID
  4. Spotify 播放列表 ID
  5. Genius 授权密钥

Spotify 客户端凭据

如果你还没有注册,那么你需要在 Spotify 上注册一个开发者账户。假设你有一个个人 Spotify 账户,你所需要做的就是导航到 Spotify 开发者仪表盘并使用你的 Spotify 账户详细信息登录。

登录仪表板后,您需要创建一个应用程序。即使你没有真正地创建一个应用程序,为了获得你的 API 证书,这也是必需的。给应用程序一个令人兴奋的名字和描述,并勾选所有适用于“你在构建什么?”问题。

应用程序现在应该在您的仪表板上,所以让我们导航到它的页面,并注意客户端 ID 和客户端密码。这些是我们发出请求时需要的 API 凭证。

Spotify 用户和播放列表 id

我们还需要一些与 Spotify 相关的东西。为了告诉 Spotify API 我们对哪个播放列表感兴趣,我们需要为创建播放列表的用户获取一个 Spotify URI,为播放列表本身获取一个。这是通过导航到用户主页到播放列表,点击三个点,然后点击“分享”——从那里你可以将 Spotify URI 复制到你的剪贴板。

Genius 授权密钥

我们还需要在 Genius API 文档页面点击“授权 Genius ”,创建一个 Genius 帐户。登录后,页面右侧应该会有一个授权代码。

分解类

现在我们已经得到了所有的输入,希望您已经能够自己尝试使用GetLyrics类,我将提供该类中每个方法的分解,这样您就可以放心地使用这段代码,并修改/改进它以适合您的特定用例。

初始化类属性

和 Python 中的大多数类一样,我们从一个构造函数方法开始初始化我们的类属性,这样它们就可以在下面的方法中使用。

获取播放列表信息

上面的方法使用 Spotipy 库连接到 Spotify API,并返回一个 JSON 对象,该对象包含我们感兴趣的 Spotify 播放列表的大量信息。

获取曲目名称和艺术家

在这两个方法中,我们遍历 JSON 对象来查找播放列表中每首歌曲的名称和艺术家。然后将它们存储并返回到两个列表中,供后面的方法使用。

连接到 Genius API

这个方法使用Requests库通过我们的授权密钥连接 Genius API。然后,它检查 API 中是否有与给定曲目名称和艺术家相匹配的内容。它返回一个包含与这些匹配相关的所有信息的响应对象。

筛选匹配项并获得歌曲的网址

在这里,我们对前面方法中返回的 JSON 对象进行解码,然后检查哪个“hit”与艺术家姓名完全匹配。如果找到匹配,则意味着该歌曲存在于 Genius API 中,并且该曲目的信息现在存储在remote_song_info对象中。Genius API 不包含每首歌曲的歌词,但是它包含一个 URL,该 URL 会路由到包含歌词的网页。在下面的代码片段中,我们解析remote_song_info对象来查找每首歌曲的 URL。

网络抓取歌词

最后,我们现在可以得到一些歌词了!这个方法再次使用Requests库来请求在前面的方法中获得的歌曲 URL。然后我们使用BeautifulSoup来解析 HTML。我们两次调用.find()函数的原因是因为我发现 Genius 网页的结构有时会有不同的格式。大多数情况下,歌词包含在带有class="lyrics”div元素中,但有时会变成class="Lyrics__Container..."。我加入了一个最终的elif条件,如果两个歌词对象都是NoneTypes,那么lyrics对象将被设置为None。这种情况很少发生,但这是由于在请求一首歌曲的 URL 时出现 404 错误,可能是因为该 URL 不再存在,但尚未从 API 中删除。

将所有东西包装在一起

最后,这个方法通过依次执行每个方法将所有内容联系在一起,这意味着我们只需两行代码就可以得到我们的歌词。它还有一系列的打印语句来使方法变得冗长,这样您就可以在它执行时跟踪它的进度。

我希望这篇文章对你有用。请在您自己的工作中随意使用这些代码,如果您有任何改进的建议,我很乐意在下面听到它们。感谢您的阅读!

成为一名机器学习工程师(从你的 Jupyter 笔记本里面)

原文:https://towardsdatascience.com/become-a-machine-learning-engineer-from-inside-of-your-jupyter-notebook-76a42b65c8f4?source=collection_archive---------37-----------------------

实践教程

管理基础架构,培训您的模型并部署它们。

照片由卡勒姆·威尔在 Unsplash 上拍摄

如果这听起来像是你的梦想,让我告诉你,这听起来也像是产品开发人员的梦想。结果:Azure ML SDK。

今天,我们将探讨如何处理云中的基础架构、环境和部署。我们将深入挖掘概念以及掌握这些技能所需的基础结构。

我知道概念本身可能感觉像空中楼阁。不过不用担心,会有足够多的代码让你觉得城堡其实就在地面上。

请给我上下文

如果我们谈论云提供商,有三个主要的参与者:AWS、GCP 和 Azure。谈到云计算,不难发现他们的主要客户之一是数据科学家。也许不是直接的他们,但是,惊喜!公司仍然是由人组成的。

照片由附身摄影在 Unsplash 上拍摄

所以,他们的策略很简单:让数据科学家的生活更轻松。
他们对此都有自己的方法,但今天我们将讨论 Azure。他们开发了 Azure Machine Learning,用它自己的话说就是,“一个基于云的环境,你可以用来训练、部署、自动化、管理和跟踪 ML 模型。

成为一名机器学习工程师

自动化、配置、管理和部署机器学习模型可能是数据科学家的噩梦。正因为如此,对能够填补这一缺口的人的需求增加了。

如果除了模型训练技能之外,你还能处理基础设施,你就离成为机器学习工程师更近了一步。如果你有兴趣跳到这个新角色,与 Azure 机器学习合作可以促进你的转变。

你与所有云基础设施的交互都可以通过 Python SDK 来完成,在你的 Jupyter 笔记本中编写代码会给你第一次做探索性数据分析时的感觉。

妮可·沃尔夫在 Unsplash 上的照片

Azure ML 概述

这听起来很棒,但是它是如何工作的呢?大致来说,有三种方式可以让你与 Azure 机器学习互动:使用浏览器、Azure CLI 和 Python SDK。正如你可能已经预料到的那样,我们将使用后者。

Azureml 包的功能被分成不同的模块。如果您想要执行一个动作,您只需要调用正确的模块并添加您的输入(这将非常直观)。一次非常美妙的经历。

注意:如果你想在你的 Azure Machine Learning 工作空间中设置一个实例并打开一个 Jupyter 笔记本,请访问下面的帖子。

[## Azure 机器学习服务中的数据版本控制

读完这篇文章后,你会明白 Azure ML 是如何处理数据的,MLOps 是如何关联的,并学习如何通过…

towardsdatascience.com](/data-versioning-in-azure-machine-learning-service-acca44a3b3a1)

资源是 Azure 内部结构的一部分。例如,如果您要创建一个工作空间,您只需要使用 Workspace.create() 函数导入工作空间模块,并设置参数。

注意:我知道脚本不在。ipynb 格式。但是我认为。py 格式看起来更干净。我希望这个细节不会让您远离真实的体验:您应该在您的 Jupyter 笔记本中编写代码。

实验意味着封装你的 ML 任务。这是一个很好的方法来分离你不同的假设并测试它们。那么,需要创建一个实验吗?同样,如果你试着猜怎么调用这个模块,我相信你会猜对的。

照片由路易斯·里德在 Unsplash 上拍摄

这两个例子只是让你看看用 Azure 对话有多简单。但是今天,我们将谈论基础设施。在第一部分,我们将创建我们的基础。理解评估者是什么以及他们如何与脚本、环境和计算集群交互,将为我们到达山顶做好准备:部署。

为了探索这个主题,我们将首先访问最常见的部署类型。获得这些知识将教会我们如何为我们的需求选择正确的 Azure 服务。最后,您会惊讶地发现部署您的模型是如此简单。

评估者

评估者是计算目标的抽象。您有许多选项来管理评估者内部的环境。要使用它们,您必须设置不同的参数,但最重要的参数如下:

  1. 脚本:可以直接指向存放所有模型训练代码的文件。
  2. 计算目标:这些人将处理您为工作负载定义的工作。
  3. 环境配置:您可以用不同的方式定义环境参数。因此,所有不同方法的共同点是,您需要选择哪种框架是处理您的工作负载所必需的。

图片作者。Flaticon 引用: 1 、 2 、 3 & 4 。

这三个人为我们提供了多种选择。如果你学会如何将它们结合起来,你将成为一名全能的机器学习专家。

这在现实生活中是如何实现的?

假设您领导一个预测客户流失的项目。该团队使用随机森林分类器基于 scikit-learn 构建了一个完整的项目。由于您的模型不是深度学习模型,因此您选择了 CPU 计算目标。
您的计算目标配置应该如下所示:

这一次,我们选择了一台针对数据库工作负载进行优化的虚拟机。如果您的项目需要其他规格,在这里您可以找到可用的选项。

Azure 计算集群的一个很酷的特性是,默认情况下,它们会根据提交的作业数量进行伸缩。这将导致不可思议的成本优化!。

对我们的随机森林来说足够好了,你不觉得吗?但是不要忘了我们的估算师!

注意:您必须确保数据和脚本在给定的目录中。

SKLearn 是一个预定义的估计器,配备了您最可能需要的标准软件包(pandas、numpy 和 scikit-learn 等)。正如您所看到的,您的模型将在特定的条件下进行训练,您可以在任何您认为合适的时候重新训练它,而不用担心再现性条件。

让自己适应变化

如你所知,生活就是改变。机器学习也是关于改变的。有时您的模型会过时,您将没有其他选择,只能调整您的基础设施以适应这些新的需求。

如果你的团队决定使用 Tensorflow 尝试一种新的深度学习模型会怎样?如果这变得更加真实会怎样:经过一些测试,他们已经意识到,事实上,新的模型比你的旧随机森林更好。不要惊慌失措。如你所见,你的工作可以简化为改变一些参数。

托尼克在 Unsplash 上拍摄的照片

您需要一个新的环境,您必须指向一个不同的脚本,并且您必须为一个 GPU 计算目标更改 CPU。不要生气。你需要对你的剧本做些小改动。

您只需更改虚拟机大小,就可以调配更好地满足您需求的新集群。很棒吧?别担心,我不会忘记评估部分。

如您所见,我们可以使用 TensorFlow 估计器来训练该模型,它也可用于快速设置。此外,我们可以指定框架版本,这对于避免兼容性版本错误非常有用。

此外,我们引用新的 GPU 计算目标,并将引用更改为新的脚本。太棒了。你完了!我甚至不愿去想这样的改变在过去意味着多少工作量。但是现在,它只是几行代码。

最后一个评估示例

在上一节中,我们通过指定 Azure 为我们提供的预配置选项来更改框架。但是,如果我需要的软件包在这些预配置的环境中不可用,会发生什么情况呢?

轻松点。您可以使用 Conda 或 PiPy 规范创建和注册环境。如果你想更深入地了解环境,请点击这里:

[## Azure 机器学习的可复制环境

甚至不知道如何创建 docker 文件

towardsdatascience.com](/reproducible-environments-by-azure-machine-learning-34a74772c38b)

在下面的代码中,您可以看到一个更加定制化的环境是如何工作的。在这个场景中,我们还需要两个包,Boruta 和一个新版本的 scikit-learn。剩下的代码片段对您来说应该很熟悉。

难以置信!现在,您知道了如何创建自己的定制环境,以及如何自动扩展计算目标。但是,我们不会就此止步。投产是我们的下一站。

部署

在这一部分,我们将达到我们一直期待的戏剧性的高潮:模型部署。如你所知,如果一个东西不能发射,它也不能使用。学习这些概念会为你打开新的视野。管理您认为是 Linux 或 Kubernetes 专家专有的服务,现在对您来说已经变得更加容易了。

蒂姆·莫斯霍尔德在 Unsplash 上的照片

异步实时与同步批量评分

如果您正在考虑项目的需求,第一个区别是至关重要的。实时 web 服务是这样一种类型,它期望相对较小的批量有较快的响应时间。另一方面,批量评分期望较大的批量和较慢的响应时间。

第一个例子可能是 Uber Eats 为您的递送进行的到达时间估计。他们不知道你何时何地会向他们要食物,所以他们无法做好准备。他们一收到订单就必须处理你的信息。

对于后者,可以考虑邮寄定向优惠。他们不需要期待某个特定事件的发生来决定是否给你折扣。他们可以处理大量的信息,并随时向你发送报价。

为什么这种区别如此重要?

因为,根据微软文档,根据用例,你应该选择一个或另一个 Azure 服务进行部署。Azure 机器学习可以用四种不同的方式处理部署:

  1. 本地 web 服务:如果您正在调试或者对您的模型进行一些基本的测试,您可以选择在一个计算实例中部署您的模型。
  2. Azure Container Instance(ACI):当您只想测试您的模型是否持续地抛出合理的值时,这个服务非常适合。它适用于需要不到 48gb RAM 的基于 CPU 的低规模工作负载。如果您的概念验证场景得到了足够的控制,那么这是测试服务是否响应良好的一个好选择。
  3. Azure Kubernetes 服务(AKS) :如果你正在为一个实时服务构建一个应用,你应该明确地使用这个服务。Kubernetes 的名声不是免费的:GPU 支持、灵活性和可伸缩性是他们的一些主要优势。但是你知道,灵活性总是要付出代价的。AKS 比其他服务需要更多的维护。
  4. Azure Machine Learning Compute(AML):如果您要进行批量部署,解决方案是使用您用于模型训练的相同计算资源。

图片作者。微软& Flaitcon 参考资料: 1 、 2 、 3 、 4 、 5 & 6 。

够概念!我想现在就部署我的模型!

好吧,如果你现在这么兴奋,你应该得到一个好的结局。

训练完模型后,注册它是非常重要的。注册模型是一个很好的实践的原因有很多:旧模型的可再现性,跟踪您过去的模型度量,或者简单地通过它的版本调用模型。

但我现在提出这个问题是有原因的。我们将用来部署模型的方法使用注册的模型作为输入。我将向您展示“无代码部署”选项,它支持特定的框架。对我们来说,好消息是 scikit-learn 模型得到了支持。

是啊!就这么简单。

使用带有几个参数的 Model.deploy() 是配置部署的最简单方法。在这种情况下,模型将在 Azure 容器注册中心注册。您可以使用 service.run(),调用您的服务,如果您更喜欢分类器的整数输出,那么会提供一个参数。否则, predict_proba 输出将是默认选项。

正如我之前向您解释的那样,还有其他方式来部署您的服务,使用这些方式(AKS、AML 计算)将需要提供一些额外的配置。

但我很确定最后一个要点让你大吃一惊,所以我们今天不会讨论其他选项,以便给你时间恢复(如果你支持,我们可以这样做)。

最棒的是,你可以在 Jupyter 笔记本上做任何事情!。

回头见!

今天够了。如果你到了这一步,我希望这能帮助你在你的云游戏中前进。如果你想处理端到端的机器学习项目,这样做是必不可少的。希望很快见到你!

参考

[1]由于这项技术是由 Azure 开发的,我将代码片段基于它们的文档,你可以在这里找到。

[2]这本书掌握 Azure 机器学习对一些细节的结构化澄清很有启发。我真的依赖那本书来创造这些内容。我要感谢 Christoph krner 授权我发表这篇博客,并为此付出了时间。如果你想更好地理解 Azure 机器学习,我真的鼓励你去读那本书。

[## 掌握 Azure 机器学习

如今数据量的增长需要分布式系统、强大的算法和可扩展的云…

www.packtpub.com](https://www.packtpub.com/product/mastering-azure-machine-learning/9781789807554)

我也在 Linkedin 和 Twitter 上。我很乐意与你交谈!如果你想多读一点,看看我最近的一些帖子:

[## 想成为 Azure 数据科学家助理(DP-100)吗?让我们

读完本文后,您将对云认证和 DP-100 有更深刻的理解

towardsdatascience.com](/thinking-about-becoming-an-azure-data-scientist-associate-dp-100-lets-32f8766df21e) [## 具有两个以上特征的聚类?尝试用这个来解释你的发现

使用 Plotly 的 line_polar 将向我们展示一种令人兴奋的聚类解释方法。此外,我们将看到…

towardsdatascience.com](/clustering-with-more-than-two-features-try-this-to-explain-your-findings-b053007d680a)

为熊猫超级用户显示自定义

原文:https://towardsdatascience.com/become-a-pandas-power-user-with-these-display-customizations-6d3a5a5885c1?source=collection_archive---------16-----------------------

熊猫展示定制是熊猫经常被忽视的一部分。许多用户不知道他们可以自定义与显示相关的选项。

pandas 有一个选项系统,可以让你定制它行为的某些方面,与显示相关的选项是用户最有可能调整的。

熊猫展示定制是熊猫经常被忽视的一部分。对于大多数用户来说,缺省值已经足够好了,但是许多用户不知道显示定制,他们会找到一些替代的麻烦方法来克服它们。要成为熊猫专家,你至少应该知道显示器定制选项。

这里有几个你可能会感兴趣的链接:

- [Labeling and Data Engineering for Conversational AI and Analytics](https://www.humanfirst.ai/)- [Data Science for Business Leaders](https://imp.i115008.net/c/2402645/880006/11298) [Course]- [Intro to Machine Learning with PyTorch](https://imp.i115008.net/c/2402645/788201/11298) [Course]- [Become a Growth Product Manager](https://imp.i115008.net/c/2402645/803127/11298) [Course]- [Deep Learning (Adaptive Computation and ML series)](https://amzn.to/3ncTG7D) [Ebook]- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)

上面的一些链接是附属链接,如果你通过它们进行购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。

要升级你的熊猫游戏,请阅读:

[## 熊猫数据分析系列

从提示和技巧,如何不指南到与大数据分析相关的提示,熊猫文章的精选列表。

medium.com](https://medium.com/@romanorac/pandas-data-analysis-series-b8cec5b38b22)

设置

import os
import platform
from platform import python_versionimport jupyterlab
import pandas **as** pd
import random**print**("System")
**print**("os name: %s" **%** os**.**name)
**print**("system: %s" **%** platform**.**system())
**print**("release: %s" **%** platform**.**release())
**print**()
**print**("Python")
**print**("version: %s" **%** python_version())
**print**()
**print**("Python Packages")
**print**("jupterlab==%s" **%** jupyterlab**.**__version__)
**print**("pandas==%s" **%** pd**.**__version__)seed **=** 42
random**.**seed(seed)
pd**.**np**.**random**.**seed(seed)

让我们定义数据集。它有 100 行和 2 列:

  • col1 具有 0 和 1 之间的随机数,
  • col2 有由 200 个字符组成的随机句子。
**def** **generate_sentence**(n_chars**=**200):
    **return** ''**.**join(random**.**choice('abcdefg ') **for** _ **in** range(n_chars))n **=** 100
df **=** pd**.**DataFrame(
    {
        "col1": pd**.**np**.**random**.**random_sample(n),
        "text": [generate_sentence() **for** _ **in** range(n)]
    }
)
df**.**shape(100, 2)

压制科学符号

默认情况下,pandas 用科学(指数)记数法显示小数字和大数字。如果科学记数法不是您的首选格式,您可以用一个命令禁用它。

让我们用一个小数字替换 col1 中的第一个值。熊猫被迫用科学记数法显示 col1,因为数字很小。

df**.**iloc[0, 0] **=** 1e-10df**.**head()

使用 float_format,我们可以设置想要显示的小数位数(在下面的例子中是 10)。

pd**.**options**.**display**.**float_format **=** '{:,.10f}'**.**formatdf**.**head()

使用 reset_option 命令,我们将其重置回科学记数法。

pd**.**reset_option('display.float_format')

要显示的最大列数/行数

当处理更大的数据集时,我们注意到 pandas 并不显示所有的列或行。显然,这是出于性能原因。虽然我不介意隐藏行,但是看不到所有的列(默认限制是 20 列)会令人沮丧。

让我们将行转换为列,以便直观地了解问题。

df**.**T

现在,让我们将最大列数设置为 100。

pd**.**set_option("display.max_columns", 100)df**.**T

要重置最大列数显示,我们可以将其设置回 20。

pd**.**set_option("display.max_columns", 20)

Pandas 还有一个 get 选项可以查看,这个值是当前设置的。

pd**.**get_option('display.max_columns')20

对于行,我们可以用 display.max_rows 做同样的事情。

扩展列宽

通常,在处理文本数据时,由于字符串的长度,字符串只能部分可见。Pandas 使我们能够用 max_colwidth 选项增加列宽。

pd**.**set_option('max_colwidth', 500)

数据帧信息

我相信您熟悉 describe 函数,它输出数据帧中每一列的汇总统计数据。info 选项类似于 meta describe 函数,因为它输出数据帧的元数据,如数据类型、非空对象和内存使用情况。

这在处理大型数据集时非常有用。

pd**.**set_option('large_repr', 'info')df

pd**.**reset_option('large_repr') # reset it

结论

这些是最常用的熊猫显示定制。如果你想了解更多关于显示定制的信息,请阅读 pandas 文档的选项和设置部分。

在你走之前

在推特上关注我,在那里我定期发关于数据科学和机器学习的推特。

照片由Courtney hedge在 Unsplash 上拍摄

通过机器学习成为神奇宝贝大师

原文:https://towardsdatascience.com/become-a-pokémon-master-with-machine-learning-f61686542ef1?source=collection_archive---------25-----------------------

能否借助机器学习预测口袋妖怪之战的赢家?

口袋妖怪公司保留所有权利

如果你是 90 年代的孩子,你一定看过口袋妖怪。你喜欢强大的口袋妖怪战斗吗?好吧,我做到了。
作为一名人工智能开发者和口袋妖怪粉丝,我想到了建立一个可以预测口袋妖怪战斗获胜者的机器学习模型。

来源:男高音

这个故事也将引导你:
1。构建机器学习模型
2。构建 ML 模型时需要的基本步骤。

参考消息:神奇宝贝是日本原版口袋妖怪的简称

下面是我找到并用来建立机器学习模型的口袋妖怪数据集。
https://www.kaggle.com/terminus7/pokemon-challenge

采取以下步骤来建立机器学习模型。

  1. 数据探索
  2. 数据预处理
  3. 模型选择和培训
  4. 预言;预测;预告

我已经添加了所有代码和各自的输出截图。也可以参考下面的 jupyter 笔记本。

https://github . com/kartikeya-Rana/pokemon _ battle/blob/master/pokemon . ipynb

# Import Librariesimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction import FeatureHasher
from sklearn.metrics import classification_report# Load the datasetspokemon = pd.read_csv("pokemon.csv")  # Pokemon Dataset
combats = pd.read_csv("combats.csv")  # Combats Dataset

数据探索

先来看看口袋妖怪和格斗数据集的前五个词条。

print(pokemon.head())

print(combats.head())

口袋妖怪数据集是由不同的口袋妖怪和他们的能力组成的。
战斗数据集由两只口袋妖怪之间的战斗组成。
“#”号用于口袋妖怪数据集和战斗数据集之间的映射。

# Plot the number of pokemon present in each category of "type 1"ax = pokemon['Type 1'].value_counts().plot(kind='bar',
                                    figsize=(14,8),
                                    title="Number of pokemons based on their type 1")
ax.set_xlabel("Pokemon Type 1")
ax.set_ylabel("Frequency")

# Plot the number of pokemon present in each generation.generation =  dict(pokemon['Generation'].value_counts())
gen_counts = generation.values() # No of pokemon in each generation
gen = generation.keys()  # Type of generationfig = plt.figure(figsize=(8, 6))
fig.suptitle("Percentage of generation based distribution of pokemon")
ax = fig.add_axes([0,0,1,1])
explode = (0.1, 0, 0, 0, 0, 0)  # explode 1st slice
ax.axis('equal')plt.pie(gen_counts, labels = gen,autopct='%1.2f%%', shadow=True, explode=explode)
plt.show()

# Plot the number of legendary and non-legendary pokemongeneration =  dict(pokemon['Legendary'].value_counts())
gen_counts = generation.values() 
gen = generation.keys()fig = plt.figure(figsize=(8, 6))
fig.suptitle("Percentage of lengendary pokemons in dataset (False: Not Lengendary, True: Legendary)")
ax = fig.add_axes([0,0,1,1])
explode = (0.2, 0)  # explode 1st slice
ax.axis('equal')plt.pie(gen_counts, labels = gen,autopct='%1.2f%%', shadow=True, explode=explode)
plt.show()

数据预处理

1。处理丢失的数据:在一个数据集中可能有几个点的值丢失。我们不能让这些地方空着。此外,我不想删除这些样本,因为这会减少我的数据集。
数值可填写该栏中的平均值、中值或最大值。

口袋妖怪数据集的列“类型 2”包含空点。这是一个分类列,因此,我可以用该列中最常见的值来填充缺少的值。
但我选择创建另一个名为 NA 的类别(不适用)。它就像“类型 2”专栏的任何其他类别一样。

pokemon["Type 2"] = pokemon["Type 2"].fillna("NA")

2。分类值到数值:机器学习模型对数字起作用。我们不能给它输入字符串或单词,因此我们必须将每个分类值转换成数值。

有几种方法可以做到这一点,如标签编码器,一个热编码器,功能哈希。

# Convert "Legendary" column, False is converted to 0 and True is converted to 1.pokemon["Legendary"] = pokemon["Legendary"].astype(int)

我使用 FeatureHasher 将列“Type 1”和“Type 2”转换成数值。FeatureHasher 还解决了由于 one-hot 编码而创建的大量列的问题(如果类别的数量非常大)。

h1 = FeatureHasher(n_features=5, input_type='string')
h2 = FeatureHasher(n_features=5, input_type='string')
d1 = h1.fit_transform(pokemon["Type 1"])
d2 = h2.fit_transform(pokemon["Type 2"])# Convert to dataframed1 = pd.DataFrame(data=d1.toarray())
d2 = pd.DataFrame(data=d2.toarray())# Drop Type 1 and Type 2 column from Pokemon dataset and concatenate the above two dataframes.pokemon = pokemon.drop(columns = ["Type 1", "Type 2"])
pokemon = pd.concat([pokemon, d1, d2], axis=1)

我们的口袋妖怪数据集被转换成一个新的数据集。

我将战斗数据集的数据与口袋妖怪数据集进行了映射,并创建了一个新的训练数据集。

新训练数据集的格式将为:

For each row in combat dataset:
    concatenate (data of First_pokemon, data of second_pokemon, winner)Winner = 0, if first pokemon wins, else, Winner = 1Data of each pokemon will have following columns (All columns except # and Name):
[HP, Attack, Defense, Sp. Atk, Sp. Def, Speed, Generation, Legendary, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4] = 18 columns.

比如:
战斗的第[0]排是:
first_pokemon = 266,Second_pokemon=298,Winner = 298。

因此,根据上述算法,新数据行将是:

First_pokemon = [50, 64, 50, 45, 50, 41, 2, 0, 0.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0]Second_pokemon = [70, 70, 40, 60, 40, 60, 3, 0, 2.0, 0.0, 0.0, 0.0, -1.0, 2.0, 0.0, 0.0, 0.0, 0.0]Winner = 1concatenate(first_pokemon, second_pokemon, winner) = [50, 64, 50, 45, 50, 41, 2, 0, 0.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 70, 70, 40, 60, 40, 60, 3, 0, 2.0, 0.0, 0.0, 0.0, -1.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1]Code:data = []
for t in combats.itertuples():
    first_pokemon = t[1]
    second_pokemon = t[2]
    winner = t[3]

    x = pokemon.loc[pokemon["#"]==first_pokemon].values[:, 2:][0]
    y = pokemon.loc[pokemon["#"]==second_pokemon].values[:, 2:][0]
    diff = (x-y)[:6]
    z = np.concatenate((x,y))

    if winner == first_pokemon:
        z = np.append(z, [0])
    else:
        z = np.append(z, [1])

    data.append(z)# Convert list to numpy array
data = np.asarray(data)

3。将数据拆分成训练和测试:将数据集拆分成训练和测试数据集。我们将使用一些数据来训练模型,并使用剩余的数据来测试模型。

X = data[:, :-1].astype(int) # Input features
y = data[:, -1].astype(int) # Output label (Winner column)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

模型选择、训练和预测

我选择了随机森林分类算法来构建我的模型。

clf = RandomForestClassifier(n_estimators=500)
model = clf.fit(X_train,y_train)
pred = model.predict(X_test)
print('Accuracy of {}:'.format(name), accuracy_score(pred, y_test))
print(classification_report(y_test, pred))

准确率 94.76%。相当不错!

来源:男高音

接下来我们可以做什么来提高我们的准确性?

  1. 调整随机森林的“n 估计量”超参数。
  2. 尝试不同的机器学习算法,如 SVM 的 AdaBoost。
  3. 试着建立一个神经网络。
  4. 做特征工程,即在现有数据的基础上创建新的数据点(列),比如增加攻防比例,特殊攻击和特殊防御。

准备好一些口袋妖怪战斗了吗?

我看了口袋妖怪,用我的模型预测了战斗的赢家。

来源:期限

感谢您的阅读!继续学习!

免责声明:口袋妖怪公司保留所有口袋妖怪角色。我不是在为口袋妖怪或口袋妖怪公司的内容做广告。

成为 Python“一行程序”专家

原文:https://towardsdatascience.com/become-a-python-one-liners-specialist-8c8599d6f9c5?source=collection_archive---------8-----------------------

终极指南

少写代码,多成就!

你只需要一句台词!

图片由 Hitesh Choudary 在 Unsplash 上拍摄

由于其简单的语法,Python 是一种初学者友好的语言。与其他需要特定使用花括号和分号的语言不同,Python 只关心缩进。到这一点,已经显得 Python 关心用户了,不是吗?然而它并没有就此停止,Python 通过其编写单行代码片段的能力给了我们更多的便利。虽然很短,但这些单行代码可以像用 Python 或任何其他语言编写的冗长乏味的程序一样强大。

你为什么关心这个?

通过使用 Python 一行程序,您将能够编写更少的代码并实现更多,这直接转化为生产力的提高。最重要的是,一行代码读起来更有趣,并且可以展示你对 Python 语言的熟练程度。

我们开始吧

1.交换两个变量的值

你们大多数人可能会这样做。

a = 1
b = 2
temp = a
a = b
b = temp

这样就可以了,a 的值现在是 2,b 的值是 1。但是,考虑一下这个!

a, b = b, a

它甚至适用于任何数量的变量!

a, b, c, d = b, c, d, a

2.列表理解

列表理解可以用来代替制作列表所需的 for 循环。

ls = []
for i in range(5):
    ls.append(i)

你可以这样做,而不是使用 for 循环。

ls = [i for i in range(5)]

您还可以添加 use list comprehension 来迭代现有的列表,并提供元素需要满足的一些标准。

ls = [-1, 2, -3, 6, -5]ls = [i for i in ls if i > 0] #ls = [2, 6], positive integers only

3.地图方法

Python 中的 map 方法为列表中的每个元素执行特定的函数。

ls = list(map(int, ["1", "2", "3"])) #ls = [1, 2, 3]

这里,我们将列表中的元素类型转换为整数类型。您不再需要使用循环函数遍历每个元素并逐个转换,map 会为您完成这些工作。

4.过滤方法

Python 中的 filter 方法检查 iterables,例如,列表的元素,并删除返回 False(不符合标准)的元素。在这个例子中,我们将利用 filter 方法来查找两个列表中的公共元素。

ls1 = [1, 3, 5, 7, 9]
ls2 = [0, 1, 2, 3, 4]
common = list(filter(lambda x: x in ls1, ls2)) #common = [1, 3]

与 map 方法一样,您不再需要遍历每个元素。

5.还原方法

Python 中的 Reduce 方法用于对每个元素应用一个函数,直到只剩下一个元素。顾名思义,该方法将数组简化为单个元素。

Reduce 函数是在“functools”模块中定义的,所以不要忘记预先导入它!

from functools import reduceprint(reduce(lambda x, y: x*y, [1, 2, 3])) #print 6

6.λ函数

def fullName(first, last):
    return f"{first} {last}"name = fullName("Tom", "Walker") #name = Tom Walker

Lambda function 是一个小型匿名(单行)函数,它能够替换用 def 关键字声明的常规函数。上面的片段和这个类似。

fullName = lambda first, last: f"{first} {last}"name = fullName("Tom", "Walker") #name = Tom Walker

当我们把 lambda 作为高阶函数使用时,它的威力会更加明显。高阶函数是将其他函数作为自变量或返回其他函数的函数。

highOrder = lambda x, func: x + func(x)result1 = highOrder(5, lambda x: x*x) #result1 = 30
result2 = highOrder(3, lambda x : x*2) #result2 = 9

注意,通过使用 lambda 函数,我们可以很容易地使用不同的 lambda 函数作为 func(x)的参数。它不是给了我们很大的自由吗?

7.使用 reverse 方法反转列表

也许你们都非常熟悉我下面介绍的列表切片方法:

ls = [1, 2, 3]
ls = ls[::-1] #ls = [3, 2, 1]

但是,这种方法会使用更多的内存,所以可以考虑使用相反的方法。

ls = [1, 2, 3]
ls.reverse() #ls = [3, 2, 1]

8.使用*多次打印同一元素

而不是像这样使用 for 循环

for i in range(5):
    print("x", end = "") #print xxxxx

你可以这样做

print("x"*5) #print xxxxx

例子

既然我们已经研究了用 Python 中的一行代码能做些什么,现在是实现它的时候了。这里有一些例子,你可以应用到目前为止你所学到的东西。

  1. 求一个数的阶乘

一个数的阶乘,用 n 表示!是所有小于或等于 n 的正整数的乘积。也许你们大多数人会考虑使用这样的递归函数。

def fact(n):
    if n == 1:
        return 1
    else:
        return n*fact(n-1)

相反,我们可以这样做:

from functools import reducereduce(lambda x, y: x*y, range(1, n+1)) #n factorial

2.寻找斐波那契数

斐波那契数列是一个数字序列,从 0 开始作为第 0 个数字,1 作为第 1 个数字。序列从一个数字开始,该数字是前面两个数字的和。斐波那契数列的前 8 项是 0,1,1,2,3,5,8,13。直觉上,你可以像这样使用递归。

def fib(n):
    if n == 0 or n == 1:
        return n
    else:
        return fib(n-1) + fib(n-2)print(fib(n)) #prints the nth Fibonacci number

或者,您可以这样做:

fib = lambda x: x if x<=1 else fib(x-1) + fib(x-2)print(fib(n)) #prints the nth Fibonacci number

3.检查一个字符串是否是回文

回文是一个单词、短语或序列,前后读起来是一样的。这段代码没有错:

def is_palindrome(string):
    if string == string[::-1]:
        return True
    else:
        return Falseprint(is_palindrome("abcba")) #prints True

然而,这样做不是更优雅吗?

string = "abcba" #a palindromeprint(string == string[::-1]) #prints True

4.展平二维数组

我们希望给定的二维数组是一维数组。这可以通过用 for 循环遍历每个元素来实现。

ls = [[1, 2], [3, 4], [5, 6]]
ls2 = []for i in ls:
    for j in i:
        ls2.append(j)print(ls2) #prints [1, 2, 3, 4, 5, 6]

然而,我们可以用这个一行程序实现同样的事情:

ls = [[1, 2], [3, 4], [5, 6]]print([i for j in ls for i in j]) #prints [1, 2, 3, 4, 5, 6]

结束语

学习这种一行程序 Python 技巧不会让你成为编程奇才。然而,这将是一件有趣的事情,它将帮助你变得更有效率(更少的代码行→更少的时间需要)。除此之外,在你的代码中加入这些技巧会很酷。嘘…你也许可以用这个打动某人。

我希望你能在你的代码中直接应用这些很酷的技巧。也许这些技术中的一些在你第一次使用时不会下沉。放心吧!随着你使用它的次数越来越多,它会变得越来越自然。

问候,

弧度克里斯诺

成为技术试听专家—第二部分

原文:https://towardsdatascience.com/become-an-expert-at-the-technical-audition-part-ii-a337f979b88a?source=collection_archive---------32-----------------------

本周,我深入探讨了在面试准备中实施刻意练习的细节

照片由来自 Pexels 的 Kulik Stepan 拍摄

在本博客系列的第一部分中,我讨论了将现场技术面试视为试听而非面试的想法,我们可以利用专业音乐人采用的练习技巧来确保我们的准备更高效,更有利于成功。

其中一种练习技巧是一种叫做刻意练习的方法,我将在这篇博客中深入探讨。请务必查看第三部分,该部分概述了一个实施刻意练习的学习计划。

刻意练习

在第一部分,我提到了刻意练习的概念,这是安德斯·埃里克森博士创造的一个术语,被认为是许多人用来超越自己成为专家的一种方法。在这篇文章中,我将深入探讨什么是刻意练习,并建议你如何将刻意练习应用到你的技术试听准备中。

举例来说,我将把这个计划组织成一个软件工程面试(/audition),并组织这个计划来解决 Gayle McDowell 的《破解代码面试书》中的主要话题。我在书中确定了 20 个主要话题,并将它们分为 3 个主要研究领域——你可以根据自己的需要调整列表。这 20 个主题的列表将在本文后面显示。

我还想先说一句,这个计划是一个“完美世界”计划——请记住,我们并不是生活在一个完美的世界里,你不可能总是完美地遵循一个计划——做好灵活的准备,并根据需要进行调整。

好吧,我同意——那么什么是刻意练习呢?

刻意练习是两件事的结合:

刻意练习=有目的的练习+专家指导

所以,为了知道什么是刻意练习,我们需要理解这两个组成部分。让我们进一步细分这两个领域:

有目的的实践

有目的的练习由 4 个部分组成:

  1. 具体,目标目标
  2. 对特定时间段和任务的高度关注
  3. 反馈
  4. 频繁的操作在你能力的边缘

让我们深入探讨一下:

有目的的练习:

  1. 具体、客观的目标:

你会注意到我会在整篇文章中频繁使用“目标”这个词。这可以说是设定目标最重要的部分。你知道自己是否在进步的唯一方法是制定可衡量的目标。他们可能以二元方式来衡量:“正确”或“错误”,或者以评分系统来衡量:“1/10”为例。

来自 Pexels 的马库斯·温克勒的照片

为了能够设定你的目标,你需要了解你目前所处的位置——你的基线——以及你正在努力达到的位置——你的最终目标。

你的最终目标既大又广,因此我们需要将它分解为子目标,并对它们进行分类,使它们尽可能具体和客观。

比如说—

最终目标:

自信地成功完成现场面试。

哇哦。很宽泛,不太具体。

让我们思考一下如何在这里衡量成功,并得到更具体的。

要成功完成面试,你需要在你知道可以测试的 20 个话题上有能力。这 20 个话题可以分为 3 类(耶,现在我们开始具体了!).

因此,我们的最终目标现在变得更加具体,例如:

在测试的 20 个主题中获得能力。

这仍然不够具体——我们可以做得更好。比如,我们如何定义‘能力’?

基线:

为了确定从哪里开始以及如何构建我们的目标和学习计划,我们首先需要弄清楚我们现在对所有这些主题的立场。

请记住,我们正努力做到客观和可衡量。为了建立一个基线,请花些时间浏览每个主题,并在 1-3 的范围内对每个主题进行评分:

1 =我对此知之甚少,只能回答不到 20%的问题

2 =我对此有些熟悉,可以回答大约 50%的问题

3 =我对此非常有信心,可以回答至少 80%的问题

在这项任务中不要掺杂任何情绪。记住——这是客观存在的!

如果你的回答大多是 1,这个任务应该不会让你不知所措——这完全在意料之中!我们只需要建立一个基线。

保持客观!

我可能会这样组织:

主题:

将主题分类,并按 3 分制评分。(图片由作者提供)

创建一个表格,将 20 个主题按照它们的 3 个类别组织起来,并留出空间输入您的基线评分。请注意,我还在主题标题旁边放置了答案行——这是一个好主意,可以评定您对哪些类别最有信心/最没有信心。

通过我们的评级系统,我们现在已经找到了一种方法来使我们的目标更加具体和客观。

这样,我们的目标是在所有科目上都达到 3 级,因此,我们现在将“能力”定义为“达到 3 级”。每周,我们将对每个主题重新评分,以跟踪我们的进展。

太好了!我们现在已经建立了一个 目标 最终目标:

每个主题都达到 3 级。

接下来我们发现有目的的练习…

2。强烈聚焦

当我说面试准备中最困难的事情是不要被太多的话题淹没时,我是发自内心的。这就是为什么专注是一项需要磨练的关键技能。

照片由 SplitShire 从 Pexel。

高度集中包括对一个话题的隧道式关注,同时模拟“真实的面试环境”。

隧道视野焦点:

隧道视野焦点包括确保当你在研究一个话题时,它是你在学习期间头脑中唯一的事情。如果你在链表上工作,你在专用时间内考虑链表(更具体地说,你只关注链表中已识别的问题区域——稍后会详细介绍)。试着忘记任何其他存在的话题。

模拟真实的面试体验:

模拟真实面试的真实环境是培训重点的一个重要部分。

在 COVID times,这实际上对我们来说更容易做到,因为你的面试地点几乎肯定是你学习的地方。

在音乐界,专业音乐人可能会预订他们试听的场地,用同样的房间、椅子和音响等来练习。作为真实的事件,或者至少,在练习的时候观想处在这个环境中。

除了模拟面试的物理环境,我们还需要训练大脑限制在面试时间间隔内。

如果你知道你的现场面试将持续 50 分钟,你应该以 50 分钟为间隔进行学习。这可以让你的大脑适应回答问题的时间框架和时间长度。不仅如此,大脑在更短的时间内更好地处理信息,让你始终保持专注。

我建议设置计时器,强迫自己在两次休息之间休息 10 分钟。我还建议为每次学习/练习设定小目标,因为这也有助于你每次坐在办公桌前时保持专注。

3.反馈

他。大多数。危急关头。部分。

对我们进展的反馈是我们决定下一步工作的方式。它驱动着我们的目标设定和每次学习的焦点。

反馈需要针对特定的

照片由驼鹿照片从像素

例如,如果你对比特操作的理解很弱,你不知道的具体是什么?你有什么问题?路障在哪里?

如果你自己在识别困难的具体方面有困难,这就是你的“专家教练”的用武之地。

最有可能的是,你在 disposal⁴没有“技术教练”,所以我们需要在如何获得定期反馈方面更有创意一些。您的反馈将来自:

你自己-

将会有许多话题,你将能够自己确定你的不足之处,你将能够指出“啊,如果我知道之类的,我就能够克服这些”,因此你将接着去做之类的事情。

解决方案-

这将是你在学习期间的主要反馈来源。对于你做的每一道题,详细研究解答。突出显示解决方案中您弄错的部分,并深入探究为什么这是解决方案。

出于这个原因,我强烈建议不要做没有解决方案的问题——当然你可以尝试,但你将无法获得反馈(除非你有教练)。

很多人经常不做的事情其实很重要:研究你答对的题的解答!

如你所知,解决问题通常有很多方法,所以我们总能找到更好的方法。因此,检查一下你的解决方案是否是最佳方案(考虑时间和空间的复杂性),如果是,把它储存在你的大脑里并记下来。如果解决方案与你的不同,并解释了为什么它可能更好,耶!你刚刚学会了一种新的做事方法,并对这个话题有了更深的理解。

希望不言而喻,以确保你得到你的解决方案从一个有点声誉的来源。你应该能够信任来自 LeetCode、HackerRank、破解代码书等平台的解决方案。如果你正在阅读论坛讨论的解决方案,请注意这些可能是非常固执己见的,并不是每个参与讨论的人都有资格发表评论,所以一定要核实论坛的建议和解决方案。

最后,理想情况下,找到详细说明“如何做”和“为什么”的完整解决方案。如果没有可用的解决方案,你可能需要用谷歌搜索来研究解决方案,并把事情拼凑在一起。这是一个更耗时的过程,但这通常会让你在这个过程中学到更多。

专家蔻驰-

这是刻意练习公式的第二部分,所以我将在下面的“专家蔻驰”部分谈论它!

4.经常在你能力的边缘操作:

把这想象成一种向前一步,向后两步的方法。

照片由卡拉·缪斯从派克斯拍摄

致力于在你已经知道的和你不知道的边缘工作。这意味着研究你不理解的领域,并利用你所知道的知识来获得新的理解。

这在我们的理解中创造了凝聚力,意味着我们永远不会盲目地一个接一个地学习新的话题。做一些新的事情,同时重温前面的 2 个步骤/构建模块。

这个过程与反馈回路紧密相连。

我可以这样做:

记录下你所做的所有问题,并确保你将它们归类在相关的标题下。对于每个主题标题,有一列你答对的问题和一列你答错的问题。这里的目标是不断重新测试“错误”的问题,以便最终所有的问题都在“正确”的一堆。

但是,不要重考题,除非你已经研究了的解答,并进一步研究了那个问题区域→这是‘能力边缘的操作’部分。

一个切实可行的方法是一次做 3 个问题——1 个新问题和 2 个“错误”的旧问题。

最后,也是最重要的一点,为了持续了解你的能力优势在哪里,你需要按照我们之前提到的 3 分制对你的主题重新打分。我建议在每个周末做这件事。

即使你“知道”你没有取得任何进步,因为那一周你没有做太多的学习,重新评估仍然是重要的,因为很容易忘记你取得的一些小进步。也许只有一个题目改变分数, 但那仍然是有形的,客观的进步。

专家指导

专家指导比有目的的实践更能说明问题,然而在技术面试的背景下,这一点并不明确。要成为一名专业教练,

  1. 一个人必须是他们领域的专家,并且在你的知识水平之上,
  2. 他们需要能够发现需要改进的地方,并提供有效的、客观的反馈
  3. 他们需要能够帮助培养心理表征

专家教练的主要作用是提供反馈。

不像运动员,舞蹈家,音乐家,软件工程师很少有 1:1 的教练!这就是我们必须在上面提到的反馈方法上有所创新的地方。把这些结合起来,充当你的“教练”。

寻找科技蔻驰:

如果你已经是这个领域的专业人士,并且和一群专家一起工作/社交,那么这就太棒了!找出你周围的人,他们在各自的领域表现出色,或者是你想去的地方(或者得到了你想要的工作)。

照片由 Pexels 的 cottonbro 拍摄

理想情况下,你需要一个善于沟通的人,当你要求反馈时,他不会拒绝你。这些人将会是你要与之进行模拟面试、阅读你的代码或讨论概念的人。如果有一个概念你不明白,让他们帮你指出题目的哪一部分是最大的空白。

如果你是这个行业的新手,你有两个选择:付费教练和有机教练。

你可以从类似熟练、面试查询等网站找到付费教练。

有机教练可以通过加入社区团体和定期参加聚会找到。这需要多一点时间(和信心),但是不要害羞——问问团队中一个你认为“不错”的资深成员,他们是否愿意帮你检查一些代码或者进行一次模拟面试。人们比你想象的更乐于助人。

接收“建议”的注意事项:

我强烈建议你对选择谁做你的教练和听取谁的建议要挑剔。这适用于日常生活,不仅仅是科技!

当收到建议时,确保该人勾选以下三个:

  1. 这个人必须是他们给出建议的领域的专家。
  2. 这个人必须熟悉你的个人情况。
  3. 你必须尊重这个人。

就我个人而言,我是按照这些标准生活的,每当有人抛出 advice⁵.时,我都会评估这三点这并不意味着如果某人没有勾选其中一个选项,你就无视他的观点,这只是意味着你会对他的建议有所保留。

但是我强烈建议你在评估谁会受到影响时记住这一点。尤其是在当今世界,每个人都有自己的观点⁶…

既然我们已经理解了刻意练习的方法,是时候把它们整合到学习计划中了!

查看这个博客系列的第三部分,看看我是如何将所有这些整合到一个针对软件工程面试者的具体学习计划中的!

脚注

这里有一个很棒的视频(壮举。Ericsson)很好地总结了有意的实践。

我已经确定了 20 个与软件工程能力相关的主要话题,但是请根据你的需要调整、增加和减少话题!当然,如果你在为数据科学面试而学习,话题会有所不同。

不要误解我的意思,这说起来容易做起来难,一开始可能会是一项艰巨的任务——我自己也在为此奋斗!

⁴Although:这些越来越受欢迎,也越来越容易租到

⁵Don't 担心,讽刺我给建议给建议对我没有失去

⁶What:是他们说的关于的意见吗?

成为技术面试专家——第一部分

原文:https://towardsdatascience.com/become-an-expert-at-the-technical-interview-part-i-2f3db6273982?source=collection_archive---------33-----------------------

改变我们思考和准备技术面试的方式。

照片由来自佩克斯的埃伯哈德·格罗斯加斯泰格拍摄

这是一个由三部分组成的博客系列,我希望就我们如何对待技术面试展开讨论。

在第一部分,我将谈到为什么我认为这是必要的和相关的。

在第二部分中,我会更具体地讲述刻意练习的概念,以及如何在技术面试的背景下思考这个问题。

最后,在第三部分中,我非常具体地为准备面试的软件工程师制定了一个学习计划!我也给出一些关于数据科学面试的注意事项!

可怕的技术面试

如果你正在读这篇文章,那么你很可能正在为技术面试(软件工程师、数据科学家等)做准备。

现在你应该知道科技面试不像常规的“老派”面试——我们不能仅仅用我们的魅力吸引招聘经理,说些废话——我们实际上必须表现

虽然这些工作需求量很大,但申请人的拒绝率很高,而且这还是在你能通过最初的筛选步骤进入现场面试的情况下。

问题是,如果你能参加现场面试,这意味着这家公司真的想雇用你——你现在只需要让他们的决定合理。那么,如果招聘经理希望你成功,为什么会有这么多应聘者在最后一轮现场面试中失败呢?

我相信很多去现场的人确实知道他们的东西,可能会成为优秀的员工,他们只是没有为现场面试的表现做好准备(这是我第二次使用这个词了……)。

还有哪个行业的招聘过程需要多次预先筛选和艰苦的“现场”表现?

音乐!

更确切地说,是专业管弦乐行业。

科技公司和管弦乐队在招聘过程中的主要区别在于,管弦乐队的职位竞争更加激烈,通常会有数十名极具天赋和资质的乐器手争夺管弦乐队中的一个职位(T2)。

在技术领域,有如此多的职位可供竞争,招聘经理迫切希望这些职位有人填补。他们不会浪费时间给不合格的人提供现场面试机会,也不会勾选最低标准——所以如果你得到了现场面试机会,他们现在只想看看你在工作中表现如何。

这是一个也被称为试音的过程。

我认为技术候选人需要开始把技术现场当成试听,而不是面试。

考虑到这一点,我将分享一些专业音乐家在准备试演和演出时使用的实践原则,我相信我们也可以用同样的精神来对待我们的技术试演。

当前的方法

有一件事让准备这些面试变得特别艰难,那就是👏🏻许多👏🏻主题👏🏻覆盖👏🏻。退一步说,这可能会让人不知所措。

照片由energepic.com从像素拍摄

这个问题已经得到了一定程度的确认和解决,优秀的资源包括 LeetCode 、 HackerRank 、 Interview Query 以及许多其他在线编码网站和书籍。这很好,确实有助于解决“学什么”的问题。然而,你怎么知道你的学习计划是有效的,并且实际上会得到你想要的结果呢?

准备这些面试不仅仅是“擅长你的工作”。我见过经验丰富的专业人士(他们确实擅长自己的工作)在现场面试后被拒绝。

技术面试是一个完整的游戏,需要不同于工作本身的技能。

当我看到过多的科技 YouTubers 和博客分享他们的科技面试经验时,我意识到需要一种更结构化的研究方法来进行这些面试。我反复听到的最大的收获是

这很难,在你得到一份工作之前,你会遭到大约 20 次拒绝,但只要坚持练习就好。

这让我很不舒服。

如果你一次又一次地被拒绝,这意味着你一遍又一遍地做着同样的事情,期待着不同的结果(也就是精神错乱的定义)。

我注意到许多“技术大师”的建议是

尽可能多地做问题,全部做,做真正难的问题,如果你总是做错,那就做简单的,这样你会保持自信,但每天都要做新的问题!!!你最终会明白的!要有信心!”

还有一些人试图用他们难以置信的智慧(呕吐)压倒你,让一切看起来比实际复杂 100 倍,只是为了让自己看起来更聪明...

总而言之,我意识到除了【练习】之外,对于如何应对技术面试准备,没有任何结构化的建议或提议。

准备技术试镜

在成为数据科学家之前,我曾是一名成功的职业钢琴家和音乐教育家。在专业音乐界,人们非常关注对 T4 的精通。没有人想仅仅是“好”,他们想掌握他们的乐器。因此,音乐家花费大量的时间来完善他们的练习习惯,以尽可能高效地获得他们领域的专业知识。

照片由波琳娜·齐默曼从 Pexels 拍摄

在我的音乐生涯中,我迷上了教育学,并理解了专家是如何成为专家的。关于这一点有大量的文献,但是我不会在这里用细节来烦你!

我制定的学习计划是为了实施一个叫做“刻意练习”的过程。这是我在音乐生涯中学到的技巧,并在我自己的实践和我的学生的日常练习中运用。

将这一研究领域正式化的人是安德斯·ericsson⁴博士,他在他的书《巅峰》中详细介绍了他的大部分工作(这是我最喜欢的书之一,强烈推荐)。

但只是面试而已,不可能那么严重吧?

我想指出的是,这整个想法是基于‘精通’和成为某方面的专家。这通常适用于职业,如职业运动员、音乐家、战斗机飞行员、棋手等。他们希望在各自的领域出类拔萃,成为大师。

但是,这实际上可以适用于任何你想变得更好的背景——你可以运用这些原则成为制作一杯完美咖啡、叠衣服、挖鼻孔的专家

在这种情况下,我们的目标是成为技术面试的专家。然而,默认情况下,你也会在你的工作中表现出色,这是由过程的性质决定的。

敬请关注

在这个博客系列的第二部分中,我将深入探究刻意练习的细节,在第三部分中,我将提供一些如何为技术试听构建学习计划的想法。

照片由 cottonbro 从 Pexels 拍摄

脚注:

当然,总有例外——一个主要的例外是,并不是每个候选人都符合良好的文化,这是许多公司非常重视的。让我补充一下,虽然你也可以通过有意识的练习来准备你的文化契合度面试,但我确实认为这应该由想要为公司工作的真正动机和对公司价值观的信念来支持。

也许应该…

我在这里假设你能胜任这项工作。我说的不是被一份不具备最低学历或经验要求的工作拒绝。

⁴You 可能对马尔科姆·格拉德威尔著名的“一万小时规则”很熟悉。嗯,安德烈斯·爱立信实际上是一个谁产生了神奇的 10,000 小时的专业知识的研究,但格拉德威尔通过把它变成一个时髦的短语来赚钱,并且没有承认爱立信的发现的重要性。爱立信强调,精通或专业知识是在特定领域经过 10,000 小时的刻意练习后获得的。这一点怎么强调都不为过。事实上,爱立信称格拉德威尔对他的工作的结论为“……对我们工作的一种大众化但简单化的观点……这表明,任何人只要在某个领域积累了足够多的实践时间,就会自动成为专家和冠军。”

成为一名数据科学家是一场马拉松,而不是短跑。

原文:https://towardsdatascience.com/becoming-a-data-scientist-is-a-marathon-not-a-sprint-f85b214304e5?source=collection_archive---------79-----------------------

一路上有很多障碍。

约翰·卡梅隆在 Unsplash 上拍照

自从数据科学成为“21 世纪最性感的工作”以来,人们对这一领域的兴趣大增。有了它,就有了获取必要知识的课程。尽管这很好,但不利的一面是,这个领域被宣传成可以在几周内掌握的东西,你会从中受益。是的,它可以学得很快,但这不是结束,数据科学是一个你将永远继续学习并面临大量挑战的领域。考虑到这一点,我开始认为数据科学类似于运动员,你训练(练习),赢或输,并重复一遍。我开始在我的职业生涯和研究生院中应用体育职业道德,我的好/坏时刻发生了巨大的变化。

注意:这不是一个简单的复制别人的惯例并强迫自己遵循的指南。相反,我想提供一个对我有帮助的实用列表,任何人都可以自己应用和修改。

练习,练习,我说练习了吗?

这也是我一直需要的提醒。我相信您已经了解了我们需要如何练习(插入主题)来提高(插入适用内容)。作为一名有抱负的数据科学家,我开始认为练习不仅仅是一项不方便的任务,而是像运动员一样是过程的一部分。每场比赛都有多次练习。目标是让练习尽可能成为常规,以建立一个坚实的基础并达到期望的水平。

作为数据科学家,我们需要开始将实践视为帮助我们实现预期目标和达到下一个水平的一部分。练习是我们技能发展的地方,我们需要像运动员一样对待它,从不错过练习。

以下是我最喜欢的一些练习资源:

对于 Python 和 R: Dataquest(免费)课程

Udemy Python 课程(这个是要收费的,但是要找优惠码!)

失败是过程的一部分。

失败和成功一样都是过程的一部分。我开始把失败视为走向全面胜利的必要一步。一旦我开始把这种心态应用到我的求职中,处理拒绝就变得可以忍受了,花在犹豫上的时间也少了。

我们需要开始思考,在一个“是”之前,我会被拒绝 10 次。如果第五次回答是,你的情况会更好。如果没有,你的动力不会随着每一个而减少。被拒绝只是这个过程的一部分,每一次拒绝,你都会学到一些新的东西,可以应用到下一次。需要的时候休息,继续。被拒绝并不断尝试总比总是想知道结果会怎样要好。

有时我们甚至没有注意到我们让失败的恐惧吞噬了我们所做的工作。当我第一次开始学习 Python 时,我会编写代码,并在运行它之前确保一切正常,因为我害怕不能得到正确的结果。尽管它只是运行程序来看看目前为止进展如何,我还是担心第一次尝试没有得到正确的结果,尽管这并不重要。但是看到我因为做错而“失败”会导致更多的时间浪费,因为我没有注意到我应该做的事情。

失败是过程的一部分,它和我们什么时候做对了一样重要。它让你越来越接近你想要达到的目标,不管我们喜不喜欢,它都会发生。

多功能性

我们有这样一个观念,只有有才华的人才能在他们的职业生涯中扮演多重角色。但这种想法并不适用于我们不断发展的社会,尤其是在我们当前的疫情世界。

重要的是发展多种技能,开始探索新的兴趣,看看这些道路通向哪里。只坚持你知道的一件事会很快走向灭亡。科技让人们可以身兼数职,在我们的大多数服务中寻找一站式服务。此外,人们已经对多个领域感兴趣,珍惜它们,并应用它们。甚至迈克尔·乔丹也对棒球有所涉猎,他是他那个时代最伟大的篮球运动员。

在不断变化的数据科学领域,具备多方面的知识是关键,因为只专注于一个主题是不可持续的。例如,我对环境产生了兴趣,并利用编程和讲故事来展示我在不经常讨论的话题上的技能,例如我们当前的废物管理系统。我们的大部分兴趣可以应用在大多数领域,让我们扩展到新的领域。

我希望这些职业应用程序能够帮助您作为数据科学家和在您的职业生涯中学习和成长。如果你有其他职业/工作申请,请联系我。记住,明智地运用你自己!

成为数据科学家:走哪条路?

原文:https://towardsdatascience.com/becoming-a-data-scientist-which-path-to-take-438af9a78c08?source=collection_archive---------73-----------------------

你成为数据科学家有哪些选择?

莉莉·波普在 Unsplash 上的照片

无论您是已经进入数据科学领域还是刚刚进入,我相信您将在许多方面从这篇文章中受益匪浅。我们首先概述了数据科学领域的重要性,然后讨论了不同类型的组织,强调了数据驱动的重要性。然后我们讨论数据科学家的需求,以及他们的技能;强调领域的动态性和持续学习的需要。然后,我们深入探讨可供您成为数据科学家或让您的技能更上一层楼的不同途径。

由活动创作者在 Unsplash 上拍摄的照片

你一定听说过数据科学是 21 世纪最性感的工作这一事实,并且可能想知道为什么它会被过度宣传?为什么每个人都在谈论它?甚至在疫情之后,人们开始更多地谈论它,并使用数据科学技术来分析数据。有的做对了,有的做错了;这超出了我们在这里讨论的范围。

毫无疑问,数据和人工智能是发展最快的行业,具有数十亿美元的潜力。因此,每个组织都试图充分利用它。有三种类型的组织。

  • 1) 他们拥有数据,并且希望从中获得洞察力,
  • 2) 拥有技能、能够获得洞察力并帮助企业成为数据驱动型企业的人。提供数据科学技能、专家和咨询服务的公司,
  • 3) 提供专业平台以支持组织实现其数据相关目标的人员。

您可能会看到一些组织将这些技能混合在一起。然而,这些是企业成为数据驱动型企业所需的能力。考虑到成本和相关的起伏,一些公司可能会开发自己的能力或外包。

注意:关于成为数据驱动型企业的更多细节,你可以关注我的数据驱动型企业系列,如下所示

  1. 什么是数据驱动的业务?
  2. 成为数据驱动的组织:挑战和阻碍
  3. 成为数据驱动型企业需要实施的变革
  4. 对数据驱动型企业的启示:他们获得了什么?

上述不同类型的组织及其成为数据驱动的迫切愿望决定了对数据科学家和机器学习工程师的高度和迫切需求。他们最终会处理这些数字,理解它们,并为企业揭示数据中隐藏的洞察力。

数据科学家面临着各种令人兴奋的机会,让自己掌握技能并熟悉数据科学是展示您的竞争优势和证明您对企业的价值的绝佳方式。数据科学是一个非常复杂、动态且不断发展的领域,这使得它既充满挑战又令人兴奋。所需的技能、你可以用来构建数据科学和机器学习管道的语言、库、框架、工具都在不断变化和成熟——这要求的不外乎持续学习。

让我们讨论一下您成为数据科学家的不同选择和途径,以及(如果您已经是数据科学家)要达到下一个专业水平还需要做些什么。

1。学位

有几所大学以不同的名称提供数据科学学位(硕士水平)或研究生水平的课程,如数据分析、机器学习、数据科学、商业分析等。还有各种在线(远程)替代方案。人们必须根据他们的情况、适合性和支付能力来评估他们。你可以选择大学或在线学习,在在线学习的情况下,你不必搬迁,但费用可能仍然很高,这取决于你选择的项目。

2。数据科学奖学金项目

有许多研究所、公司或初创公司提供为期几个月的实践奖学金,这让你有可能为研究所/奖学金的合作伙伴(或赞助商)之一解决商业问题。从长远来看,这对企业和员工来说都是一个很好的机会,看看他们是否适合对方;从短期来看,公司解决了他们的问题,而你作为毕业生获得了实际项目的实践经验。

3。通过在线平台学习

许多在线网站都提供课程,你可以通过这些课程成为数据科学领域的专家。我称之为艺术和科学,因为它涉及到这两者;解决商业问题是一门艺术,用数据科学来解决,顾名思义,就是科学。而你两者都需要;在今天的就业市场上,只有一个是不够的。

有许多在线平台提供数据科学方面的课程;一些提供商包括 Coursera、Edx、DataCamp、Udacity、Udemy 等等。此外,许多大学通过这些平台提供在线课程和专业。这些项目对几乎每个人来说都是经济可行的,你可以按照自己的进度来进行,这有助于学生掌握概念并完成整个课程。这是由你来决定个人课程,微硕士或纳米学位课程

此外,还有一些实践项目,帮助您逐步了解如何针对业务问题构建项目。

4。做动手项目

这围绕着你自己掌握它,把控制权掌握在你自己手中,并自己驾驶它。虽然这适用于所有其他情况,但在这种情况下更是如此。你必须从一个动手项目开始,然后针对应用场景、算法等进行扩展。

5。看书

尤其是对于爱读书的人来说,要学习一个概念,然后去实施或者掌握它。对许多人来说,这也是一个很好的方法,但也许不是对所有人;这需要时间,在动手实践的时候,你可能会迷失方向。只有当你有了必要的实践经验并了解基本原理后,我才会推荐你这么做。在当今敏捷和快速发展的世界中,我想强调的是从你喜欢的任何资源开始,并在你前进的过程中将其与其他资源结合起来。没有一种灵丹妙药。

6。中等

媒体上几乎每一个主题都有大量的文章。它们通常不会很长,这在很多方面有助于保持你的注意力,获得有价值和有用的知识,并付诸实施,把它变成坚持的东西。为了能够使用这个平台,你可以创建一个免费帐户或付费/会员帐户。然后下一步是寻找顶级出版物中的文章,如对数据科学和对 sAI 。我通常在这些刊物上发表我的文章。几篇示例性文章是关于一个 特征库对数据驱动业务 的影响。

照片由 Isaac Owens 在 Unsplash 上拍摄

学习机器学习(当然还有其他任何东西)的一个好方法是写下你所学到的东西。你也可以在 Medium 上成为一名作家,把你关于数据和 AI 的故事提交到这个这里。

7.Kaggle 等比赛

许多人通过参加像 Kaggle 和其他人的竞赛来确定技术概念。这也是一个很好的方法,让你把自己放入一个纪律的框架中,遵守截止日期,接受挑战,并取得一些成就,除了掌握概念,还能给你带来金钱上的好处,让你得到认可,你可以为自己的名声索赔。当然,这不会在一夜之间发生,需要时间,任何事情都是如此,所以无论你做什么都要有耐心和毅力。

8。Youtube 视频

你也可以通过关注 YouTube 来学习数据科学。有许多课程或特定主题的短片和长视频,你可以快速搜索和浏览。

总的来说,你是最了解自己的人,知道什么适合你,什么不适合你。你知道你可能不愿意与他人分享的事情,但这将帮助你决定哪个选项(或它们的组合)最适合你。让我在这里提出一些问题,这些问题可能有助于您思考、规划和执行成为数据科学家的旅程。

  1. 我应该考虑在线还是面对面的计划?
  2. 考虑到我的具体情况、生活状况、经济状况和其他方面,他们各自的优缺点是什么?
  3. 我可以将它们与我目前的工作结合起来吗,或者我应该休息一下,加入一个现场伙伴关系?
  4. 有哪些我很了解的概念,需要掌握哪些,还是应该从零开始?
  5. 有什么先决条件吗?例如,我需要先学习一门编程语言吗?
  6. 需要投入多少时间?
  7. 我需要支付多少费用?

思考这些问题和其他问题,并尝试自己回答它们,以评估您学习和掌握数据科学的最佳方式。

成为统计推断的大师

原文:https://towardsdatascience.com/becoming-a-master-of-statistical-inference-230597498e07?source=collection_archive---------25-----------------------

图片来自 Pixabay 的 StockSnap

推论的意义是什么?

推断是通过一些观察数据的样本得出关于更大人群的结论。例如,你有一些国家对总统的看法的样本,你想对大众做出一些结论。显然,你不会询问每一个公民,而是使用样本数据对潜在人群进行推断。

概率从何而来?

虽然推理是关键,但我们只能通过一些模型生成的数据进行推理;队列概率…概率用于从给定模型生成数据的过程。

为了以简单的方式将所有这些放在一起,请考虑以下内容:

观察/样本数据->模型->概率/数据生成->推理

经典的抛硬币和二项分布

是时候打破二项分布的魔力了。

掷硬币是帮助分解二项分布的经典例子。

就像我们刚才建立的一样,我们将创建一个模型,允许我们基于简单的抛硬币的想法来生成随机数据。

突击测验!任何给定的掷回正面或反面的可能性有多大??你成功了!😉 50/50.

所以让我们跳到 R 来生成这种类型的实验。为此,R 中有一个很棒的函数叫做rbinom。我们将用它来模拟抛硬币。

在 R 中抛出下面的命令,看看会得到什么?第一个参数是“拉动”或运行的次数。想运行多少次就运行多少次,您会看到大约 50%的时间该函数返回 1,另外 50%返回 0。

把所有等于或大于 0.5 的都称为“正面”,我们第一次掷硬币是正面。我们再来一次,但是要 10 次。

rbinom(10,1,.5)

这次我们 80%的时候都是正面

如果你一遍又一遍地这样做,你会有 50%的机会接近头部。你也应该做越来越多的翻转。

查看给定翻转发生的时间百分比的好方法…

flips = rbinom(10000, 1, .5) mean(flips == 1)

几乎有一半的时间是正面。

现在让我们稍微改变一下。我们将在实验中抽取 100 万次,但这次每个实验将包括 10 次翻转,有 50%的可能性翻转 5 个头。

flips = rbinom(1000000, 10, .5)

当我们将flips传递给一个hist()函数时,我们得到如下结果:

大约 25%的时间里,你看到的是 5 次翻转。这个度量被称为该点的二项式密度。

模拟帮助我们回答关于分布及其行为的问题

累积密度

下一个概念是所谓的累积密度。类似于我们如何查看该点的二项式密度,我们可以查看该点及其上下的密度,代表累积计算。

让我们像前面一样分解同一个例子…通过声明翻转必须小于或等于 5 而不是等于 5,我们的代码对大约 50%的人群评估为真。

flips = rbinom(100000, 10, .5) 
mean(flips <= 5)

结论

干得好!这里面有很多需要理解的东西,但我希望这已经被证明是有用的,可以作为二项式分布的入门&如何考虑为了推断而抽样。

如果您觉得这很有用,请随时查看我在 datasciencelessons.com 的所有其他帖子&一如既往,祝您数据科学愉快!

成为一名定量 UX 研究人员是一件棘手的事情

原文:https://towardsdatascience.com/becoming-a-quantitative-ux-researcher-is-messy-1c9b9460e36b?source=collection_archive---------29-----------------------

不要期望轻易获得冠军,见鬼,甚至不要去争取冠军

奇怪的物体在花园中间。就像 qUXR 一样。(摄影:兰迪·欧)

出于某种原因,在过去的几个月里,我多次被问到成为量化 UXR 的问题,显然是因为我一年前写的关于我如何成为量化 UXR 的帖子。由于这个职位在野外成长非常缓慢,我想我应该为那些对如何成为一个好奇的人写下这个世界的现状。

Quant UXR 只是一个一直存在的工作的新标签

现在的 UX 分析师本质上是一种通才形式的数据科学家,他们更喜欢专注于理解用户行为,而不是建立其他类型的模型。因此,他们可以被视为数据科学家的一种形式(这意味着他们融合了分析师、研究员和工程技术)。通才部分可能就在那里,因为这个角色相当新,专业化还没有必要。

但是这个角色的功能早于数据科学。

总有一些人(调查专家,有市场研究背景的人,等等)致力于理解用户。分析师(以及将成为数据科学家的分析师),以及用户研究人员。这些人将与产品团队紧密合作,以确定产品应该何去何从。所有的角色都有自己的半独特的工具箱,但最终这些人是他们主类的一个以产品为中心的子类。

因此,在建立了 UX 研究部门(传统上是一个更定性的领域)的大型组织中,出现了处理大量数据的需求。数据科学家拥有处理数据的技能,但他们的任务通常是为用户创建工具和产品。高级分析师也可以做这项工作,但是他们经常被业务目标所束缚。于是这种需求出现了,拥有相关技能和对用户感兴趣的人去填补了这个空缺。

忘记标题,瞄准角色

当人们问我“我如何找到一个 Quant UXR 角色?”我告诉他们,不要找那个特定的标题。只有少数公司甚至有这样的角色,大 FAANGs,如果没有数据科学/分析/研究领域的经验,很难进入。在竞争如此激烈的公司,技能几乎成了赌注,领域知识和经验成了一个与众不同的点。

因此,与其在这些条件下竞争,希望进入该领域的人最好去看看旨在帮助产品团队更好工作的研究员、分析师和数据科学职位。这些角色是存在的,但是没有以容易搜索的方式进行区分。这是一种痛苦,但每个基于产品的公司都会需要这些人,不管他们是否明确表达出来。

你需要寻找与产品团队紧密合作的团队。

  • 你会直接与工程师、设计师和产品经理一起工作吗?
  • 你能接触到数据吗?
  • 团队是否有助于产品战略的制定?
  • 你能运行实验或做出改变来收集数据吗?
  • 是否有其他数据团队(分析师、科学、工程)可以合作?
  • 互动模式是什么?顾问、嵌入式团队成员等。

你接触这些东西越多,你就越能做定量的 UX 工作。有些东西比其他东西更重要,但很少什么都有。期望做大量的宣传,建设基础设施,建立信任和同盟来完成任务。

这不是 2020 年的入门级职位。期望爬上这个角色

就像早期的数据科学家一样,Quant UXRs 倾向于成为多面手,因为这个角色是新的和不明确的。这种模糊性可能就是为什么有这么多奇怪的全才数据科学家/研究员类型的原因。非常需要足够的灵活性来做必要的事情来完成研究,即使这意味着为你编写的调查系统建立你自己的数据收集和分析基础设施。

这也意味着定量分析师必须更多地使用“软”技能。你的经理可能不是量化分析师,没有人可能不知道量化分析师应该做什么。你将会接到与用户研究工作无关的工作请求,并且有一个不可能的截止日期。你将需要管理期望、推后、建立跨职能和团队的关系、请求资源、展示工作以及展示价值和影响的技能。这些都是很难的东西。

如果您还不知道如何实现这些软功能,那么您肯定不希望在学习硬技能的同时被迫学习软技能。一下子学太多了。学习所有这些东西最有效的方法是找到一个你可以用你的有生力量发挥作用的位置,然后学习所有其他的东西。

你需要一个团队

做一个孤独的定量分析师压力非常大,因为你必须兼顾我上面提到的所有事情。我已经在初创公司里做了 5 年多的单干分析师/定量分析师,这仍然是一项艰苦的工作。但是在这 5 年之前,我花了将近 6 年的时间在一个好的经理和团队的指导下学习。没有那些年的学习,我不会有今天。

所以你肯定不想成为一家公司里第一个处理数据的人,除非你有一个对使用数据略知一二的直接经理的大力支持。那是给那些有多年经验的人准备的。

你可能想要较小/中等尺寸的东西

较小的组织(无论是公司还是产品团队都是<150 people) are more likely to have roles that let you drift into a product supporting role by virtue that they’ll let people wear more hats. The company itself doesn’t have to be small, there are often subdivisions/groups within larger organizations that more or less act autonomously.

The goal is to find a place that has a certain degree of role-ambiguity. That’s your opportunity to take on stretch goals and grow into a quant role.

Don’t expect this to be a full career ladder, it’s just a role

Just like with data science, the field is too young to have an actual career ladder. At best there may eventually be junior, and senior distinctions. No one has any idea what a Quant UXR with 15 years experience is going to look like. You can of course just keep doing the work indefinitely, but there’s not much available in terms of taking on “more”.

Moving up beyond being a researcher would involve either leading a team of quants, or branching out to leading entire research programs, both quantitative and qualitative. Transferring into other roles like UX leader, project management and product leads, is also possible with all the cross-functional skills and domain knowledge at your disposal. All of those require you to expand your skill set even beyond what they are now.

Good luck out there

It’s confusing out there. Do your best. People can always feel free to ping me on twitter ( @Randy_Au )有问题,我总是可以根据这些问题写一篇后续文章。

本帖原载于 兰迪的计数玩意儿简讯 。这是一份致力于数据科学和技术的重要、平凡部分的时事通讯。免费注册,在你的收件箱里获得类似的文章。

成为 AWS 认证数据分析专家—2020 年 4 月全新

原文:https://towardsdatascience.com/becoming-an-aws-certified-data-analytics-new-april-2020-4a3ef0d9f23a?source=collection_archive---------10-----------------------

该认证面向设计、构建、保护和维护分析解决方案的个人。我们将介绍如何准备考试、练习测试和之前推荐的知识。

我刚刚通过了 AWS 认证数据分析专业考试(DAS-C01),获得了我的第二个 AWS 认证。如您所知,该认证是最新的 AWS 版本(2020 年 4 月)之一,将取代 AWS 认证的大数据专业。该认证面向设计、构建、保护和维护分析解决方案的个人。

您有 3 个小时的时间来回答 65 个基于场景的问题。

由 Bradyn Trollip 在 Unsplash 上拍摄的照片

如果你想了解更多,请访问oscargarciaramos.com

以 50%的折扣获得为期 1 年的所有 Whizlabs 课程—立即订阅

或者

购买 100 多个 AWS 认证数据分析的独特练习题—专业考试

之前推荐的 AWS 知识

  1. AWS 认证数据分析专业(DAS-C01)考试分为及格或不及格。您有 170 分钟的时间来完成考试。它由大约 65 个问题组成。
  2. 和往常一样,考试中有两种类型的问题:选择题和多选题。
  3. 未回答的问题被视为不正确;猜测是没有惩罚的
  4. 您的考试可能包括未评分的项目,这些项目被放在测试中以收集统计信息。这些项目在表格上没有标明,不影响你的分数。
  5. 考试结果以 100-1,000 分报告,最低及格分数为 750 分。考试采用补偿评分模式,这意味着您不需要“通过”个别部分,只需通过整体考试(新)
  6. 除了 2 年的 AWS 实践经验外,现在建议至少 5 年的通用数据分析技术经验才能获得该认证。(新)

内容大纲

让我先来并列比较一下考试形式的变化:

数据分析—专业

大数据—专业

正如您所看到的,分析和可视化领域从 29%增加到 18%,更加重视处理(+ 8%)和存储及数据管理(+ 5%)领域。

就其本身而言,集合域的总权重增加了 1%,而安全性减少了-2%。

主要提示

主要服务是 EMR,红移,Kinesis 和 S3+胶水+雅典娜。这使得大约 80%的考试,而且如果你有 准水平认证 它将更容易通过其余的概念。

如果我不得不从头开始,我会建议花更多的时间学习最重要的概念、细节、选项和主要数据分析技术的组件,而不是练习那些肯定不同于真实考试的模拟测试。此外,截至目前,该认证的考试并不多。

我强烈建议先做 解决方案架构师助理 ,原因如下:

  • 作为进入 AWS 云世界的第一步,它要简单得多,也有用得多。
  • 帮助您熟悉测试方法和节奏,以及 AWS 堆栈中的其他服务,让您真正专注于本次考试的主要数据分析技术。
  • 你目前在下一次考试中获得 50%的折扣。因此,如果您选择较便宜的联营公司(150 美元),您将获得较贵的联营公司(300 美元)的 50%。

如何备考

这些是我通过考试所依赖的资源:

  • 在线课程

毫无疑问,最优秀的课程是由 Sundog Education 的弗兰克·凯恩创建的 Udemy 的 AWS 认证数据分析专业 2020 (ex Big Data) ,夏羽·马雷克| AWS 认证解决方案架构师&开发助理弗兰克·凯恩

凭借其超过 12 小时的点播视频、全面的测试考试以及对其资源的无限访问,它是本次考试的最佳指南和最佳资源之一。

从我的角度来看,我认为有必要看两遍视频。我以 2 倍速收听,并通过浏览参考资料部分的链接白皮书和文档来复习每一堂课。

可选: 您还可以报名参加云专家的 AWS 大数据专业课程,以获得所有产品和重要概念的高级概述,作为起点。目前,他们还没有推出数据分析认证的具体课程。

  • AWS 白皮书

亚马逊有无数引用数据分析产品的文档。但是,我推荐数据分析学习路径中的这两篇文章,它们可以帮助您更好地理解现有的服务。就我而言,我决定阅读 Kinesis 白皮书,因为它是一种需要记住许多细节和不同实现选项的技术,例如它的生产者、消费者、加密和安全性,以及这些服务的输入和输出。

—采用亚马逊 Kinesis 的 AWS 上的流数据解决方案(29 页)

本白皮书讨论了分析从批处理到实时的演变。它描述了如何使用 Amazon Kinesis Streams、Amazon Kinesis Firehose 和 Amazon Kinesis Analytics 等服务来实现实时应用程序,并提供了使用这些服务的通用设计模式。

—AWS 上的大数据分析选项(56 页)

本白皮书通过提供服务概述,以及以下信息,帮助架构师、数据科学家和开发人员了解 AWS 云中可用的大数据分析选项:理想使用模式、成本模型、性能、耐用性和可用性、可扩展性和弹性、接口和反模式。

  • AWS 培训

—考试准备:AWS 认证数据分析—专业(免费课程,3 小时)

这门课程通过探索考试的主题领域,让你熟悉问题风格和考试方法,帮助你准备考试。

它以一种非常直观的方式,让你了解考试中最重要的组成部分、需要记住的最重要的细节以及考试中可能出现的问题示例。此外,它们还包括指向这些技术中通常出现的主要主题或问题的参考链接。

这次培训,在我看来,必不可少。因为这是一个如此短而有用的课程,我可以很容易地从头到尾复习 2-3 遍。

  • 模拟考试

—去查查

以 50%的折扣获得为期 1 年的所有 Whizlabs 课程—立即订阅

正如我之前提到的,浏览官方 AWS 培训和认证网站上的免费样题和考试准备问题。这些问题帮助你想象考试会是什么样子,并让你评估你正在获取的知识。

我的情况,另外,我买了whiz labs练习测试。这些问题不遵循模型,也与官方考试问题不一致。然而,它们帮助你探索新的知识领域,这些领域你以前可能没有见过,被认为是重要的,或者在以前的材料中没有如此详细地涉及。关于 Whizlabs 的好处是,它用新的信息链接和支持材料来证明答案是正确的。****

本次考试中您应该熟悉的流行分析服务的快速快照:

  • 用于流数据的 Kinesis 数据流、Kinesis 消防软管和 Kinesis 分析。
  • 亚马逊为卡夫卡(MSK)管理流媒体
  • 用于消息排队的简单队列服务(SQS)
  • 物联网
  • AWS 数据库迁移服务(DMS)
  • 简单存储服务(S3)
  • 优化事务查询的 dynamo db
  • 自动气象站λ
  • AWS 胶水
  • 使用 Elastic MapReduce 处理无限规模的数据,包括 Apache Spark、Hive、HBase、Presto、Zeppelin、Splunk 和 Flume
  • 亚马逊弹性搜索服务,用于搜索和分析 Pb 级数据和 Kibana
  • 雅典娜用于查询 S3 数据湖
  • 红移和红移光谱
  • 关系数据库服务(RDS)和极光
  • Quicksight 用于交互式可视化您的数据
  • 用加密保护你的数据安全, KMSHSMIAMCognitoSTS 等等。

如何回答问题

采取这种方式回答问题:

  • 在阅读答案选项之前阅读并理解问题(假装答案选项一开始根本不存在)。
  • 找出问题中的关键短语和限定词。
  • 试着在看答案选项之前回答问题,然后看看这些答案选项是否与你的原始答案相符。
  • 根据你对问题的了解,排除答案选项,包括你之前强调的关键短语和限定词。
  • 如果你仍然不知道答案,考虑标记这个问题,然后继续问更简单的问题。但是请记住在考试时间结束前回答所有问题,因为猜错是没有惩罚的。

有用的链接

  • 获取 AWS 认证数据分析学习指南

  • edu reka 提供的 AWS 架构师认证培训掌握使用 Amazon Web Services 设计基于云的应用程序的技能。了解更多!

  • 为 AWS 认证数据分析专业考试购买 100 多个独特的练习题

  • AWS 认证解决方案架构师助理考试的 17 个多小时的培训视频和 38 个实验室|立即注册

  • https://AWS . Amazon . com/certificate/certified-data-analytics-specialty/?nc1=h_ls

  • https://D1 . AWS static . com/training-and-certification/docs-Data-Analytics-Specialty/AWS-Certified-Data-Analytics-Specialty _ Sample-questions . pdf

  • https://www.udemy.com/share/101WhCAkodeVtRQXg=/

  • https://d0 . AWS static . com/white papers/white paper-streaming-data-solutions-on-AWS-with-Amazon-kine sis . pdf

  • https://d0 . AWS static . com/white papers/Big _ Data _ Analytics _ Options _ on _ AWS . pdf

  • https://www.aws.training/Details/eLearning?id=46612

那都是乡亲。希望这篇文章对你有用。

欢迎发表评论或分享这篇文章。关注 me 未来岗位。😉

祝你考试顺利!

**记住,如果你想了解更多,你可以在oscargarciaramos.com找到我

与+1K 人一起加入我的电子邮件列表,获取更多独家内容

**** [## AWS 认证数据分析-专业是由亚马逊网络服务培训和…

获得这一认证的人对如何使用 AWS 服务进行数据收集、存储…

www.youracclaim.com](https://www.youracclaim.com/badges/0b507f03-8d5d-40bf-b950-eedcfa763480/public_url)****

在 2 个月内获得 AWS 大数据专业认证

原文:https://towardsdatascience.com/becoming-aws-certified-in-big-data-specialty-in-2-months-ecf77d3e06db?source=collection_archive---------28-----------------------

AWS 考试学习指南&忙碌的专业人士的小贴士

斯蒂芬·道森在 Unsplash 上拍摄的照片

我最近通过了 AWS 大数据专业考试,获得了我的第二个 AWS 认证。去年我参加了 Google Cloud 的同等学力考试,分享了我用来通过考试的学习资料集。在这篇文章中,我分享了我的学习指南和我用来在短时间内获得认证的计划。在这次考试之前,我已经完成了助理解决方案架构师考试,并且拥有不到一年的 AWS 大数据产品工作经验。

学习计划

这个学习计划是为繁忙的专业人士在紧张的时间表成为 AWS 认证而设计的。为了真正深入了解 AWS 大数据解决方案和设计最佳实践,我会将研究计划扩展到实验室工作,获得实践经验,并通读公开的案例研究。

在线课程

由于我并不熟悉所有的 AWS 大数据产品,我首先报名参加了云专家的 AWS 大数据专业课程,以获得所有产品和重要概念的高级概述。我以 2 倍速收听,并通过浏览参考资料部分的链接白皮书和文档来复习每一堂课。

Youtube re:发明视频或白皮书

AWS 有大量关于每个大数据产品的在线文档,但观看云专家或其他博客( Simon 的帖子、Ashwin 的帖子)推荐的 re:Invent 视频或精选白皮书节省了时间,并专注于重要的设计考虑事项,而不是考试中未测试的低级细节。请仔细注意图表和比较图,以及对每个产品的限制。

重要链接:

  • AWS re:Invent 2019:Amazon dynamo db deep dive—高级设计模式
  • AWS re:Invent 2019:用亚马逊 Kinesis 搭建流媒体数据平台
  • AWS re:Invent 2019:亚马逊红移的深度探索和最佳实践
  • AWS re:Invent 2019:深入研究在亚马逊 EMR 上运行 Apache Spark
  • 【2018 年创新大会上的 AWS 大数据和分析会议

安全性和 Hadoop 工具集开发人员指南

您仍然需要通读每个 AWS 产品的开发人员指南中的安全部分,以记住加密选项、备份机制和跨区域复制。除非您有针对各种加密约束进行设计的实践经验,或者在工作中使用跨区域备份构建全局表,否则这一部分主要是记忆。Hadoop 生态系统也是如此。了解何时使用 Presto vs. Hive 以及流行的 Hadoop 产品的高级描述。

重要链接:

  • (Skim) 亚马逊 EMR 迁移指南
  • 红移安全
  • DynamoDB 安全

模拟考试

浏览 AWS 官方培训和认证网站上的免费样题和考试准备问题。我发现这些测试不太关注大数据,但仍然很好地代表了 AWS 风格的问题。我还从 Whizlabs 买了练习题。考试形式与正式考试不一致,因此如果您在模拟考试中得分较低,也不要气馁(例如,在真正的考试中,没有多项选择题,您必须从 6 个选项中选择 4 个正确答案)。最重要的是找出不同产品或概念的知识差距。

学习指南

我整理了一份学习指南来复习关于 Kinesis、EMR、数据管道、DynamoDB、QuickSight、Glue、Redshift、Athena 和 AWS 机器学习服务的大量测试主题。在实际考试中,我发现 EMR、红移和 DynamoDB 依次是重点。对于每种产品,关注以下主题:

  • Kinesis :数据流、消防水管、视频流和数据分析的区别。KPL(聚集/收集)、KCL 和 Kinesis 代理收集数据的概念和最佳实践。
  • DynamoDB :表格设计(WCU/RCU,GSI/LSI),加密和安全,使用最佳实践提高性能
  • EMR: Hadoop 生态系统,加密&安全选项,选择最佳格式以提高性能
  • 红移:加载、复制、更新和删除数据的最佳实践。访问控制、加密、安全和复制选项。
  • 其他:对每种产品及其如何适应大数据的高层次理解(例如,使用 Lambda 过滤数据或将数据路由到 S3/红移)

最后,AWS 将在 4 月份更新大数据考试,并将头衔更名为数据分析专业。然而,根据网上的考试描述,似乎涵盖的主题保持不变,但我们将看到测试人员的结果何时开始出来。

祝你考试好运!

(你可以看看我的徽章)

获得 AWS 认证—准备参加 2020 年 AWS 认证考试

原文:https://towardsdatascience.com/becoming-aws-certified-prepare-for-your-aws-certification-exam-2020-f5392fcbec44?source=collection_archive---------29-----------------------

根据角色和专业从各种认证考试中进行选择,旨在帮助个人和团队实现您的独特目标。

如果您想要验证您的技术技能和云专业知识,以促进您的职业和业务发展…

祝贺你,今天是你的大日子!

将工作负载迁移到公共云是一项持续的艰巨任务,以前这是公司内部的一项技能,现在它已经成为任何业务团队的核心能力。

凭借 33%的市场份额,亚马逊 AWS 继续引领 2020 年 Q2 公共云的采用,目前提供 12 项认证,其次是微软 Azure 和谷歌云平台,分别占 18%和 9%。

凭借超过 175 种不同的服务,AWS 提供了大约 40 种其他云提供商不提供的服务。

照片由 Cookie 在 Unsplash 上的 Pom 拍摄

以 50%的折扣获得为期 1 年的所有 Whizlabs 课程—立即订阅

或者

成为 AWS 认证专家|使用优惠券— WHIZAWS20 并享受八折优惠|立即购买

与+1K 人一起加入我的电子邮件列表,获取更多独家内容

成为 AWS 认证需要多长时间?

我会告诉你,根据我的经验,在全职工作的情况下,需要投入 2 到 3 个月的时间。也就是说,总共投入 80 到 120 个小时来准备所有的认证。

随着您知识的增长,许多认证共享高级概念、服务和其他细节,您将在学习过程中不断强化这些内容。从基础知识开始,然后进入解决方案架构师—助理学习路径。

我从哪里开始?哪个云认证最好?

AWS 目前总共提供 12 种不同的认证:

  • 一项基础认证: AWS 认证云从业者
  • 三项助理级认证:
    AWS 认证开发人员助理
    AWS 认证系统运行管理员助理
    AWS 认证解决方案架构师助理
  • 两项专业级认证:
    AWS 认证 DevOps 工程师-专业
    AWS 认证解决方案架构师-专业
  • 六大专业认证: S 认证数据分析-专业(旧大数据-专业)
    如果你想了解更多,去查一下 成为 AWS 认证数据分析-2020 年 4 月新
    AWS 认证高级联网-专业
    AWS 认证安全-专业
    AWS 认证机器学习-专业
    AWS 认证数据库-专业
    AWS 认证 Alexa 技能构建器-专业

您可以在此找到所有学习途径的完整概述。

获取 AWS 认证解决方案架构师学习指南

我如何获得 AWS 认证?

嗯,每个人都有一套窍门。虽然没有单一的方法来准备每一项认证,但至少以我的经验来看,我确实使用特定的方法来参加和通过认证。

  1. 下载考试指南和样题。

我想说,这是开始任何认证工作之前要做的第一件事。重要的是要知道从哪里开始,每个认证涵盖的材料,并能够选择哪一个适合您的需求或关注。例如,准备 AWS 认证数据库—专业与准备 AWS 认证数据分析不同。虽然他们可能会分享知识和服务,但你应该提前知道你想专注于哪里。

2。探索 AWS 学习途径

每种认证都提供了不同的学习途径,详细介绍了成功通过认证的建议步骤。

在每条学习路径中,都推荐了不同的入门或免费培训课程、要阅读或至少要考虑的 AWS 白皮书,以及用户在参加最终考试之前必须具备的其他要求或知识。

此外,每个步骤都根据其复杂程度(基础、中级或高级)进行分类,如有必要,还包括为保证当前认证成功而必须获得的推荐的先前认证。

3。阅读 AWS 白皮书
这似乎是不必要的,当然,在许多情况下我们忽略了这一步,但我告诉你这是值得的。

这些文章中涉及的所有细节对于深入理解考试中涉及的每项服务的内容至关重要。

事实上,许多问题都是从这些白皮书中摘录的,因此,如果我是您,我会花时间阅读这些白皮书,并查看您的认证中的一些常见问题或主题。

4。参加考试准备培训
我在上一次认证中发现了这一步骤,并取得了成功。
这些免费的 AWS 培训允许用户学习如何解释考试问题,并为考试中的每个部分分配必要的时间。

根据认证的不同,我们会以面对面课程、在线和其他网络研讨会的形式提供不同的培训,在这些培训中,我们会复习每个领域中的试题示例,以及如何解释不同的可能答案,以便更轻松地消除错误答案。全力推荐!

5。练习考试
练习,练习,练习。如果你想确保你控制了考试的所有环节,你想在考试中减轻任何担心或压力,那就练习吧!

而且不止一次,很多次。直到你差不多把问题和答案都背熟了。开始的几次可能是一场灾难,然后就值得了。
我建议在你以至少 80–85%的分数通过所有考试或测试之前,不要参加考试。

你的口袋会很感激!

获得 AWS 认证需要多少钱?

根据您考试的认证级别,价格如下:

  • 从业者 = 100 美元
  • 关联 = 150 美元
  • 专业 = 300 美元
  • 特产 = 300 美元

记住,一旦你通过了一门考试,你在下一门考试中会得到 50%的折扣。因此,如果您选择较便宜的联营公司(150 美元),您将获得较贵的联营公司(300 美元)的 50%。

让我用一个表格来分享这 12 项认证的详细信息:

耶,我有了我的第一个认证!现在怎么办?…

重新认证和保持最新状态

恭喜!这是第一步,但还没有全部完成。AWS 每年提供的新功能和服务的数量,我甚至可以说每个月都在增加。为了证明这不是巧合,并且您继续拥有更新 AWS 服务所需的经验和知识,认证持有者需要每两年重新认证一次。

您有两种选择:要么通过同一认证的专业水平重新认证,要么通过当前认证的重新认证考试。考试持续 80 分钟,费用 75 美元。

我可以在线获得 AWS 认证吗?

全力推荐。我上一次认证是 100%在线。
现在,您可以在线参加 AWS 认证,也可以在自己舒适的家中参加。但是,有些方面您可能需要考虑:

  • 你必须能够与说英语的监考人交流。考试可以用不同的语言进行,但会有一个“控制者”在考试前问你一系列问题,并帮助你解决任何问题。总是用英语。您可以用英语、日语、韩语或简体中文参加考试,但与监考人的交流将使用英语。
  • 在参加考试之前,您必须确保您的计算机符合系统要求(浏览器、麦克风、摄像头,以及工作区)。您必须拍摄工作空间的照片,以验证它是一个有效的房间。
  • 考试期间不能被打扰,考场必须在一个私密安静的地方。
  • 与面对面考试不同,考试期间你不允许离开房间或离开摄像头的范围(准备坐 3 个小时😉)
  • 目前,在线监考仅适用于与我们的考试供应商皮尔逊 VUE 安排的 AWS 认证考试。

最后,让我来帮你!

关于不同 AWS 认证的所有信息可以在这里找到。

不过,让我来帮你让这次冒险更加愉快:

  • edu reka 的 AWS 架构师认证培训 掌握使用亚马逊 Web 服务设计基于云的应用的技巧。了解更多!
  • 以 50%的折扣获得为期 1 年的所有 Whizlabs 课程—立即订阅
  • 成为 AWS 认证专家|使用优惠券— WHIZAWS20 并享受八折优惠|立即购买

那都是乡亲。希望这篇文章对你有用。

欢迎发表评论或分享这篇文章。跟随 me 进行未来岗位。😉

祝你考试顺利!

与+1K 人一起加入我的电子邮件列表,获取更多独家内容

【oscargarciaramos.com】记住,如果你想了解更多,可以在 找我

[## AWS 认证数据分析-专业是由亚马逊网络服务培训和…

获得该认证的人员对如何使用 AWS 服务进行数据收集、存储…

www.youracclaim.com](https://www.youracclaim.com/badges/0b507f03-8d5d-40bf-b950-eedcfa763480/public_url) [## AWS 认证解决方案架构师助理由亚马逊网络服务培训和…

获得该认证的人员对 AWS 服务和技术有全面的了解。他们展示了…

www.youracclaim.com](https://www.youracclaim.com/badges/36a66d5e-c27d-4ca6-bd65-80b64fec61a4/public_url)

啤酒分析——从网络数据中分析啤酒价格的指南

原文:https://towardsdatascience.com/beeralytics-a-guide-to-analyzing-beer-prices-from-web-data-37d4ba206071?source=collection_archive---------30-----------------------

使用散景在交货地点寻找价格最优惠的啤酒

由阿尔班·马特尔在 Unsplash 上拍摄的照片

几周前,我和女朋友在酒吧喝酒,开始争论菜单上最便宜的啤酒是什么。挑战本身是 20 种左右的啤酒有多种尺寸和酒精含量,这使得简单的比较成为一个挑战。赌注下好了,我们开始做手机数学(我发誓我们一直都这么兴奋),用一个基本公式来标准化它们:

奥兹。每$' =(('总盎司。'* '酒精%') / 100) /价格

这表明,高 ABV 的 IPAs 是你的钱的最大价值!现在我又输给了我的女朋友,我很好奇这是一个当地的选择(也许酒吧很难出售这种饮料)还是这种定价在规模上是一致的?这似乎是一个有趣的数据科学问题,所以我开始头脑风暴来回答这个问题。

10 年前,如果没有专有数据集或走访每家商店并记下所有价格,这可能是不可能的(我肯定店主喜欢这样)。相反,我们现在有过多的送货服务,如 Drizly 和 Minibar,它们通过当地商店提供啤酒送货服务。

本文的其余部分将介绍如何使用 Python Requests 库从网站中提取数据的方法、基于所提取数据类型的图表和库选择,以及使用 Bokeh 库的中级到高级可视化技术。下面解释的最终文件和代码可以在这里找到并分支。

数据争论

正如我在介绍中所说的,第一个挑战是捕获数据,以便我可以对其进行分析。两者都没有 API,所以我开始研究他们的网站和网络调用的结构,看看哪一个/哪一个是可行的。Drizly 有一种非常奇怪的方式将数据直接注入 react 组件,这样在网络调用中就不会有简单的 JSON 有效载荷(也许是为了混淆的目的?),显然要花很多时间才能把它变成可用的形式。将焦点转移到 Minibar 上,我很快发现他们不仅有一个容易抓取的标准 JSON 有效载荷,而且还有一堆元数据,耶!

XHR 的 JSON 来电

一旦我发现了这一点,就可以使用 Requests 库来拉 JSON 了…或者我是这样认为的。创建一个简单的请求后,我遇到了一条错误消息:

告诉我你的秘密

嗯,这有点尴尬。运行item_count.status_code还确认了一个 401 未授权错误,这意味着我们的响应正确地到达了服务器,但是由于请求中缺少某种凭证而被拒绝。由于令牌不是凭空创建的,并且站点不需要登录,唯一合乎逻辑的结论是,一旦用户访问站点,就必须为会话创建令牌。这促使我检查上面提到的 XHR 请求的请求头部分,瞧,我发现了一个不记名令牌:

啊,缺失的拼图

一旦我添加了头参数,我就能够确认这个工作并返回数据了!下一个挑战是弄清楚如何以编程方式获取不记名令牌并将其添加到请求中,因为令牌可能会在一定时间内自动过期。我的计划大致变成了:

  1. 首先向https://minibardelivery.com/发出请求,因为它不需要特殊授权就可以访问并获取它给我的不记名令牌
  2. 使用头有效负载中的载体向我的目标 JSON 目标发出请求
  3. 循环遍历并将数据展平到一个数据帧中

在主页上很难找到持有人,因为它不在任何 XHR 请求中,而是作为一个元名称标签包含在内:

偷偷摸摸

那么如果它不在 json 中,我们如何获取它呢?简单,我们就当普通网页用美汤!这可以通过编写一个非常简单的函数来实现:

def get_token():
    url = '[https://minibardelivery.com'](https://minibardelivery.com')
    r = requests.get(url)
    soup = BeautifulSoup(r.text, 'html.parser')
    bearer_token = soup.findAll(attrs={"name":"access-token"})[0]['content']
    return bearer_token

如您所见,我们所做的只是向 Beautiful Soup 指定文本应该像 HTML 一样处理,然后告诉它返回 access-token 属性的内容。这使我们不用做任何复杂或容易出错的正则表达式来寻找令牌。既然我们可以随时动态获取数据,那么只需将它展平到一个数据帧中。

查看 JSON,许多啤酒都有“变种”(不同的价格取决于包装尺寸/特定商店的销售额/容器类型等。)我也想捕捉和对比。使用下面的代码,我能够根据初始调用中的 count 变量遍历所有的 beers,将每个变量添加为单独的行项目,然后将其输出到单个数据帧中

import requests
import pandas as pd 
import numpy as np
import time
from bs4 import BeautifulSoupdef get_token():
    url = '[https://minibardelivery.com'](https://minibardelivery.com')
    r = requests.get(url)
    soup = BeautifulSoup(r.text, 'html.parser')
    bearer_token = soup.findAll(attrs={"name":"access-token"})[0]['content']
    return bearer_tokenurl = '<the json url>'
bearer_token = get_token()
header = {'Authorization': 'bearer {}'.format(bearer_token)}
item_count = round(requests.get(url+str(1), headers=header).json()['count']/20)def alc_pct(x):
    if x is None:
        x = np.nan
    else:
        x = x['value']
    return xbeer_df = pd.DataFrame([])
for x in range(1,item_count+1):   
    time.sleep(3)
    data = requests.get(url+str(x), headers=header).json()
    for i in range(0, len(data['product_groupings'])):
        core_data = {key: data['product_groupings'][i][key] for key in data['product_groupings'][0].keys() & {'name','type','brand'}} 
        core_data['hierarchy_type'] = data['product_groupings'][i]['hierarchy_type']['name']
        core_data['hierarchy_subtype'] = data['product_groupings'][i]['hierarchy_subtype']['name']
        core_data['alcohol_pct'] = alc_pct(next((item for item in data['product_groupings'][i]['properties'] if item["name"] == "Alcohol %"), None))
        variant_df = pd.DataFrame([])
        for v in range(0, len(data['product_groupings'][i]['variants'])):
            variant_data = {key: data['product_groupings'][i]['variants'][v][key] for key in data['product_groupings'][i]['variants'][v].keys() 
                            & {'price','short_pack_size','short_volume','container_type','supplier_id'}}
            core_data.update(variant_data)
            variant_df = variant_df.append(core_data, ignore_index=True)
        beer_df = beer_df.append(variant_df)beer_df.to_csv('beer_data.csv')

一旦我的数据框中有了大约 2000 瓶啤酒,我就使用 missingno 库来了解这些数据有多完整:

哎呀,酒精百分比

结果是,酒精百分比,我整个实验的关键,在很多啤酒中都找不到,大约是数据集的 3/5。固执和热情蒙蔽了我的双眼,我做了任何一个理性的人在这种情况下都会做的事情——我从商店里拿了一罐 6 罐装啤酒,然后花了几个小时手动输入我在搜索 https://untappd.com/等网站时找到的数值。最终,我完成了啤酒和数据输入,并准备进入下一阶段。

选择正确的可视化

现在我们有了一个好的数据集,我们需要考虑如何有效地可视化数据。数据有定量和分类两个维度,我们想要比较诸如啤酒类型、容器类型等。针对不同的属性。考虑到任何给定点的潜在数据点的数量,散点图是一个很好的选择,因为它们能够轻松地显示模式和相关性趋势。我还知道我想用可视化来执行一些不同的高级交互:

  • 我希望它是高度互动的,因为“最好”的啤酒可能是我再也不想喝的(看着你眼镜王蛇)。我还想过滤和理解复杂的情况,如“价格最好的 IPA 6 包装,ABV 至少为 6%”
  • 我希望能够将颜色映射到显示中的定量点和分类点。这将使得在查看不同度量时更容易识别模式成为可能。由于一些数据也是高度基数的,我想分配独特的颜色,而不是一遍又一遍地重新映射 10 或 20 种颜色。

在尝试了一些熟悉的简单图形库之后,我意识到如果没有一个高度灵活和可定制的库,这是行不通的。我最终选择了散景,它不仅有一个巨大的预制图表库,还提供了一些很棒的例子——尤其是这个移动评级一。我决定这一个将适合我的需要,只有小的调整,所以它是全速前进!

被散景弄得又脏又脏

我现在警告你,如果你想用散景做基本图形之外的事情,阅读文档。一开始我很抗拒,结果我像一个迷路的孩子一样在 Stack Overflow 和 Google 上过滤了几个小时。理解在哪里访问和更新像字形这样的对象的结构以及ColumnDataSource如何更新数据是你应该尝试和理解的关键概念,而不要深入太多。

我的第二个免责声明是,这些代码中的一些可能效率不高,但如果我试图调整/理解它,我就永远不会发表这些。

脚手架

在浏览了他们网站上的一些例子后,大部分散景都很容易理解,而且我基本上是用电影的例子。要点中的想法是:

  • 导入库和数据,创建所需的自定义指标,对数据集应用任何格式化/清理:
import os
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import column, layout
from bokeh.models import ColumnDataSource, Div, Select, Slider, LinearColorMapper, ColorBar, CategoricalColorMapper, Legend, LegendItem, CustomJS
from bokeh.plotting import figure
from bokeh.transform import jitter
from bokeh.palettes import Reds9, Turbo256, d3
from bokeh.models.widgets import CheckboxButtonGroup, DataTable, TableColumndf = pd.read_csv('beer_data.csv')
df['brand'] = ['uncat' if str(x) == 'nan' else x for x in df['brand']]
df['hierarchy_type'] = ['uncat' if str(x) == 'nan' else x for x in df['hierarchy_type']]
df['hierarchy_subtype'] = ['uncat' if str(x) == 'nan' else x for x in df['hierarchy_subtype']]
df['total_oz'] = df['short_pack_size_num'] * df['standard vol']
df['cost_per_oz'] = round(df['price'] / df['total_oz'], 2)
df['oz_of_alcohol_per_dollar'] = round(((df['total_oz'] * df['alcohol_pct']) / 100) / df['price'], 2)
  • 为轴和颜色选择创建字典。用户可以选择 x/y 轴以及颜色所基于的尺寸/度量:
axis_map = {
    "Oz of Alcohol per $": "oz_of_alcohol_per_dollar",
    "Cost per Oz": "cost_per_oz",
    "ABV": "alcohol_pct",
    "Pack Size": "short_pack_size_num",
    "Volume (Oz)": "standard vol",
    "Price": "price"}color_axis_map = {
    "ABV": "alcohol_pct",
    "Brand": "brand",
    "Container Type": "container_type",
    "Category": "hierarchy_type",
    "Sub-Category": "hierarchy_subtype",
    "Price": "price",
    "Pack Size": "short_pack_size",
    "Volume": "short_volume",
    "Supplier": "supplier_id",
    "Type": "type",
    "Oz of Alcohol per $": "oz_of_alcohol_per_dollar",
    "Cost per Oz": "cost_per_oz"}
  • 创建工具提示格式,一个解释图表的描述部分,然后我们将在边上使用的小部件过滤器。然后,我们将为图形和表格创建一个 ColumnDataSource:
tooltips = [
    ("Name", "[@name](http://twitter.com/name)"),
    ("Brand", "[@brand](http://twitter.com/brand)"),
    ("Price $", "[@price](http://twitter.com/price)"),
    ("ABV", "[@alcohol_pct](http://twitter.com/alcohol_pct)"),
    ("Category", "[@hierarchy_type](http://twitter.com/hierarchy_type)"),
    ("Category Sub-type", "[@hierarchy_subtype](http://twitter.com/hierarchy_subtype)")]# Create description at top of webpage
desc = Div(text=open("description.html").read(), sizing_mode="stretch_width")# Create unique option lists for some of the widget filters
container_options = list(df['container_type'].unique())
pack_size_options = sorted(list(df['short_pack_size'].unique()))
hierarchy_options = sorted(list(df['hierarchy_type'].unique()))
sub_hierarchy_options = sorted(list(df['hierarchy_subtype'].unique()))
brand_options = sorted(list(df['brand'].unique()))for i in [pack_size_options, hierarchy_options, sub_hierarchy_options, brand_options]:
    i.insert(0, "All")# Create widget filters
min_abv = Slider(title="ABV", start=0, end=20, value=1, step=1)
jitter_amt = Slider(title="Jitter", start=0, end=1.0, value=0.1, step=0.1)
container_check = CheckboxButtonGroup(labels=container_options, active=[0, 2])
brand = Select(title="Brand of Beer", value="All", options=brand_options)
pack_size = Select(title="Pack Size", value="All", options=pack_size_options)
hierarchy = Select(title='Category', value="All", options=hierarchy_options)
sub_hierarchy = Select(title='Sub-Category', value="All",
                       options=sorted(sub_hierarchy_options))
y_axis = Select(title="Y Axis", options=sorted(axis_map.keys()),
                value="Oz of Alcohol per $")
x_axis = Select(title="X Axis", options=sorted(axis_map.keys()), value="ABV")
circle_color = Select(title="Circle Color",
                      options=sorted(color_axis_map.keys()), value="Price")# Create Column Data Sources that will be used by the plot and table
source = ColumnDataSource(data=dict(df))
table_source = ColumnDataSource(data=dict(df))

这看起来有很多代码,但主要是为过滤器创建唯一的列列表,将这些列表分配给小部件,并为过滤器设置默认值。

我们还将添加一个部分来创建图形、字形和最终图表所需的所有样式。我们在这里有一个条形图和图例,因为我们需要切换它们的可见性,以便在定量和分类选择之间切换:

p = figure(background_fill_color='black', background_fill_alpha=0.5,
           border_fill_color='gray', border_fill_alpha=0.25,
           plot_height=250, plot_width=500,               toolbar_location='below', tooltips=tooltips, tools="pan,box_select,wheel_zoom,reset,help",
           active_drag="box_select", active_scroll='wheel_zoom'))c = p.circle(x=jitter('x', width=jitter_amt.value, range=p.x_range),
             y=jitter('y', width=jitter_amt.value, range=p.y_range),
             source=source, size='price', line_color=None,
             fill_color={"field": color_axis_map[circle_color.value], "transform": cmap})bar = ColorBar(background_fill_color='gray', background_fill_alpha=0, color_mapper=cmap, location=(0, 0), visible=True)legend = Legend(items=[LegendItem(label=dict(field="x"), renderers=[c])],location=(10, -30), background_fill_alpha=0, visible=False)columns = [
    TableColumn(field="name", title='Name'),
    TableColumn(field="type", title='Type'),
    TableColumn(field="container_type", title='Container Type'),
    TableColumn(field="short_pack_size", title='Pack Size'),
    TableColumn(field="short_volume", title='Volume'),
    TableColumn(field="price", title='Price'),
    TableColumn(field="alcohol_pct", title='ABV'),
    TableColumn(field="cost_per_oz", title='Cost per Oz'),
    TableColumn(field="oz_of_alcohol_per_dollar", title='Oz of Alcohol per $')]data_table = DataTable(source=table_source, columns=columns, selectable=False)p.add_layout(bar, "right")
p.add_layout(legend, 'right')

完美!既然基础知识已经完成,我们可以进入更高级的概念了。

挑战 1 —色彩映射

我想做的事情之一是将分类数据或定量数据映射到图上的点。我希望颜色条也能根据定量数据进行调整,否则异常值(比如小桶的价格)会扰乱过滤数据的颜色分布。在没有深入基本问题的情况下,我的逻辑最终是这样的:

  • 基于默认变量定义初始颜色映射。我选择了 price,所以我默认使用 Bokeh 的LinearColorMapper,但是如果我默认使用一个分类值的话,我会把它变成一个CategoricalColorMapper
  • 创建一个rescale_color函数,在更新时将线性颜色映射重新调整到新的最小/最大过滤值
  • 创建一个categorical_color_scale函数,将分类色标映射到提供的任何分类列表。我还添加了一个特殊的色标,用来更好地映射高度基数的数据(比如品牌)
  • 创建一个cat_linear_color_toggle函数,在更新时确定颜色窗口小部件过滤器中的当前活动值是分类的还是定量的
  • 创建一个show_hide_legend函数来切换颜色条(定量图例)和图例(分类图例)的可见性
def rescale_color(cmap, df):
    """Rescale the linearcolormapper based on the dataframe provided"""
    cmap.low = min(df[color_axis_map[circle_color.value]])
    cmap.high = max(df[color_axis_map[circle_color.value]])
    return cmapdef categorical_color_scale(color_list):
    """Returns a different size color scale based on color list size"""
    if len(color_list) < 30:
        colors = d3['Category20'][20]+d3['Category20b'][10]
    else:
        colors = Turbo256
    return colorsdef cat_linear_color_toggle(color_col, df):
    """Changes color scale based on whether color is displaying a quantitative
    or categorical value upon a transformation"""
    if df[color_col].dtype == 'float64' or df[color_col].dtype == 'int64':
        color_mapper = rescale_color(cmap, df)
    else:
        cat_list = list(df[color_col].astype(str).unique())
        color_mapper = CategoricalColorMapper(
            factors=cat_list, palette=categorical_color_scale(cat_list))
    return color_mapperdef show_hide_legend(attr, old, new):
    """Used for switching to and from categorical scale"""
    color_val = color_axis_map[circle_color.value]
    if df[color_val].dtype in (float, int):
        p.legend.visible = False
        bar.visible = True
    else:
        p.legend.visible = True
        bar.visible = False

现在我们已经有了更新色标/图例的框架,我们可以继续讨论一旦用户与我们的小部件过滤器交互,如何更新所有内容。

挑战 2 —更新图表和过滤数据

为此,我们将在很大程度上反映电影图表示例,但我将简要介绍一下这些概念。我们希望创建一个名为select_beer()的函数,它将为我们的小部件过滤器找到所有当前值,然后根据这些选择过滤数据集:

def select_beers():
    """Filter data source based on widget filter input"""
    container_check_val = container_check.active
    abv_val = min_abv.value
    brand_val = brand.value
    pack_size_val = pack_size.value
    hierarchy_val = hierarchy.value
    sub_hierarchy_val = sub_hierarchy.valueselected = df[df['alcohol_pct'] > abv_val]
    if (container_check_val != 4):
        container_name_list = [container_check.labels[i] for i in container_check_val]
        if len(container_name_list) == 0:
            container_name_list = container_options
        selected = selected[selected.container_type.isin(container_name_list)==True]
    if (brand_val != "All"):
        selected = selected[selected.brand.str.contains(brand_val)==True]
    if (pack_size_val != "All"):
        selected = selected[selected.short_pack_size.str.contains(pack_size_val)==True]
    if (hierarchy_val != "All"):
        selected = selected[selected.hierarchy_type.str.contains(hierarchy_val)==True]
    if (sub_hierarchy_val != "All"):
        selected = selected[selected.hierarchy_subtype.str.contains(sub_hierarchy_val)==True]
    return selected

我们要写的下一件事是一个update()函数,它将更新图形元素(例如轴的名称和所选啤酒的总数),以及更新ColumnDataSource,这是图形上的数据是如何更新的。它将通过调用cat_linear_toggle并更新图例,最终强制更新图例/色标。最后一点适用于新过滤数据的抖动:

def update():
    """Updates graph elements and source.data based on filtering"""
    filtered_df = select_beers()
    x_name = axis_map[x_axis.value]
    y_name = axis_map[y_axis.value]
    p.xaxis.axis_label = x_axis.value
    p.yaxis.axis_label = y_axis.value
    p.title.text = "%d beers selected" % len(filtered_df)
    color_select = color_axis_map[circle_color.value]source.data = dict(
            x=filtered_df[x_name],
            y=filtered_df[y_name],
            name=filtered_df["name"],
            brand=filtered_df["brand"],
            price=filtered_df["price"],
            container_type=filtered_df["container_type"],
            hierarchy_type=filtered_df["hierarchy_type"],
            hierarchy_subtype=filtered_df["hierarchy_subtype"],
            short_pack_size=filtered_df["short_pack_size"],
            alcohol_pct=filtered_df["alcohol_pct"],
            short_volume=filtered_df["short_volume"],
            supplier_id=filtered_df["supplier_id"],
            type=filtered_df["type"],
            oz_of_alcohol_per_dollar=filtered_df["oz_of_alcohol_per_dollar"],
            cost_per_oz=filtered_df["cost_per_oz"])
    table_source.data = source.datatransform_scale = cat_linear_color_toggle(color_select, filtered_df)
    c.glyph.fill_color = {"field": color_select, "transform": transform_scale}
    p.legend.items[0].label = {'field': color_select}
    if filtered_df[color_select].dtype in (float, int):
        bar.color_mapper = rescale_color(cmap, filtered_df)
    c.glyph.x = jitter('x', width=jitter_amt.value, range=p.x_range)
    c.glyph.y = jitter('y', width=jitter_amt.value, range=p.y_range)

在这之后,我们需要做的就是为我们所有的控件设置回调。最终输出与电影示例中的普通散景非常相似。我在末尾添加了一个os.system(...),以便于在本地运行:

# Determine if legend type needs to change
circle_color.on_change('value', show_hide_legend)controls = [min_abv, jitter_amt, container_check, brand, pack_size, hierarchy,
            sub_hierarchy, x_axis, y_axis, circle_color]for control in controls:
    if (control == container_check):
        container_check.on_change('active', lambda attr, old, new: update())
    else:
        control.on_change('value', lambda attr, old, new: update())inputs = column(*controls, width=320, height=500)
inputs.sizing_mode = "fixed"
l = layout([[desc], [inputs, p], [data_table]], sizing_mode="scale_both")update()  # initial load of the datacurdoc().add_root(l)
curdoc().title = "Beer Plot"os.system("bokeh serve --show bokeh_scatter.py")

运行这一切让我第一次看到了我们放在一起的东西,不错!

最终的图形,过滤器,色标和数据表!

最终挑战—基于图形选择的过滤

在这一点上,我对输出感到非常满意,并认为我已经完成了,但是一旦我开始检查数据,我就试图突出显示图表上的点区域来过滤数据表。许多数据点相互重叠,如果没有办法看到底层的选择区域,就很难进行检查。散景图自然地通过它们的默认工具如box_select来处理图表上的数据选择,但是没有默认的方法来在数据表上反映这一点。

在阅读和搜索了更多相关信息后,我得出了一个不幸的结论,那就是使用默认库无法做到这一点……ughhhhh。幸运的是,Bokeh 允许通过 CustomJS 模型使用 JavaScript,我需要完成的事情只需要很少的 JS 知识。我们想要做的如下:

  • 数据上的选择发生变化时,创建一个执行定制 javascript 的回调
  • 获取所选点的指数
  • 如果 selection > 1,则创建一个空字典,然后用 source.data 中索引与索引匹配的数据填充
  • 用新字典更新表格
# Use custom JS so that filtering on the graph affects the data table as well
source.selected.js_on_change('indices', CustomJS(args=dict(source=source, table_source=table_source), code="""
        var inds = cb_obj.indices;
        var d1 = source.data;if(inds.length == 0){
            table_source.data = d1
        }
        else{
        d2 = {'name': [], 'type': [], 'container_type': [],
              'short_pack_size': [], 'short_volume': [], 'price': [],
              'alcohol_pct': [], 'cost_per_oz': [], 'oz_of_alcohol_per_dollar': []}for (var i = 0; i < inds.length; i++) {
            d2['name'].push(d1['name'][inds[i]])
            d2['type'].push(d1['type'][inds[i]])
            d2['container_type'].push(d1['container_type'][inds[i]])
            d2['short_pack_size'].push(d1['short_pack_size'][inds[i]])
            d2['short_volume'].push(d1['short_volume'][inds[i]])
            d2['price'].push(d1['price'][inds[i]])
            d2['alcohol_pct'].push(d1['alcohol_pct'][inds[i]])
            d2['cost_per_oz'].push(d1['cost_per_oz'][inds[i]])
            d2['oz_of_alcohol_per_dollar'].push(d1['oz_of_alcohol_per_dollar'][inds[i]])
        }
        table_source.data = d2
        }
    """))

我们做到了!最终结果应该只显示数据表中反映的选定点,类似于我在图表上选择几个数据点时看到的内容:

选择被突出显示,表格被动态过滤

结论

我知道你可能在想什么——那真正的啤酒呢?!结果很少有惊喜,麦芽饮料品牌 4Loko(又名罐装电池酸)是我所在地区最便宜的,每盎司酒精 0.72 美元,比第二名挑战者每盎司便宜 0.10 美元。“酒精%”(ABV)被证明是价值的最佳基线预测值,您可以通过探索性数据分析或其他方式进行确认。

最终,您可能会做更多的事情,例如将额外的邮政编码区域或站点包括在此分析中,但是过多的丢失数据肯定会影响您在没有一些手动数据清理的情况下所能做的事情。使用散景也很有趣,但我不确定将来我会不会把它作为图形的首选。也许如果我正在做数据可视化的工作,我会考虑它,但是对于人们需要用图表显示的大多数东西来说,学习曲线是相当陡峭的。

希望这对任何人都有帮助,并随时联系或在下面评论问题/评论。感谢阅读!

预测黄金之前:探索 ETF 的跟踪误差

原文:https://towardsdatascience.com/before-predicting-gold-exploring-etfs-tracking-error-9e7c3bec4490?source=collection_archive---------36-----------------------

金的探索性数据分析

跟踪误差 EDA。使用 ETF 作为因变量的好处和注意事项。

“作为人类,我们被五颜六色的树叶所吸引,有时很少注意对树的生命至关重要的根、茎和枝。这相当于做一个金融模型,一个定量分析师新手没有花足够的时间探索数据的复杂细节就匆忙开始建模过程。

来自笔记本的 LBMA PM Fix 和 GLD ETF

在这篇文章中,我将分享我个人做全球贵金属研究项目的经验。我的公司是贵金属市场的利基参与者,为潜在客户提供从销售和交易到储存和交付贵金属的全球端到端服务。他们的目标是“给传统的物理作业带来一些量化的实践”。我将参与这场革命,并帮助公司实现一种系统化的方法来将资金配置到黄金上。该公司可能不熟悉回归模型的数学成本函数,但他们知道黄金行业的机制。我总是对围绕这种两极分化的资产的大量信息和发现感到惊讶,这从第一天起就点燃了我的探索。

我告诉自己“忘了建模吧,该学学黄金了”。

使用黄金交易所交易基金作为黄金现货价格的替代品进行建模有很多好处和警告。我还会提到基金跟踪误差的概念和偏离的潜在因素。跟踪误差存在于每一个跟踪基准的基金中。因为它的存在,人们不得不质疑黄金 ETF 是否能代表黄金的真实价值。它不仅给黄金模型制作者,也给投资者带来了警示。本文不会深入探讨跟踪错误的机制,但会引导您了解我的解决方法。

本文将在开发黄金模型之前解决以下考虑事项:

  • 我们的模型所基于的普通黄金资产,以及为什么 ETF 是一个可行的选择
  • 计算/可视化不同黄金 ETF 的跟踪误差
  • 验证影响黄金 ETF 跟踪误差的因素
  • 根据跟踪误差选择黄金 ETF

关于黄金选择的一点细节

所以我们想创造一个黄金投资模型。第一个问题是我们用哪种黄金资产建模。一些资产选择包括:

  1. 实物黄金:伦敦黄金场外交易市场(LBMA)向投资者提供黄金这种有形资产。以这种方式持有黄金可以维持长期财富,而没有任何交易方风险。尽管 LBMA 位于伦敦,但市场可以在全球范围内交易。 LBMA 网站 保存了一些关于定价和交易条款的有用信息。
  2. 交易所期货合约:期货合约交易者主要由套期保值者和投机者组成。套期保值者将买入/卖出他们希望持有的黄金的当前合约价格(在未来交割),并对冲到期日之前价格上涨/下跌的风险。投机者进行交易是为了从他们对价格运动的投机中获利,因为他们的目标不是持有实物黄金本身。
  3. 黄金追踪交易所交易基金(ETF) :这类 ETF 通过持有实物黄金和期货合约来追踪现货黄金价格的回报。投资者将投资于 ETF 的股票。期货投机者和 ETF 投资者类似,因为他们交易黄金而不持有黄金。还有一些黄金 ETF 不直接投资于该商品,而是投资于专门从事黄金的公司。

那么用哪种黄金做模特呢?

假设你的目标是投资和储存黄金。黄金的分配将每周重新平衡。我们决定使用一个 ML 模型,通过每日观察来预测一周的回报方向。

使用期货价格是不可能的,因为我们既不对冲也不投机期货价格。我们可以将模型建立在 LBMA 现货价格的基础上,但是这种方法在构建我们的特征集时会带来一些问题。

数据-时间对齐问题 — LBMA 每天两次在拍卖中设定黄金价格(工作日伦敦夏令时 10:3015:00 )。因此,只有每日上午下午的价格数据。考虑这些场景:

  • 包含存在于不同时区的非伦敦 BST 市场指标要求这些指标的生成时间与 AM 或 PM 价格相匹配。如果我们想使用 GC 期货的价格衍生品,那么我们必须在美国东部时间 10:00 对每日观察数据进行采样,以匹配伦敦夏令时 15:00。然而,并不是每个人都可以访问当天的数据,数据订阅会产生巨大的成本。想象一下,必须将 50 个基于美国的特征与现货金对齐。大多数美国经济指标都不是当天的,调整这些指标是不明智的。
  • 调整我们的投资组合以包括其他资产,如现货白银(不同的 LBMA 结算时间)将在投资组合回溯测试中造成障碍 ,因为现货价格不一致。我们也有向前/向后看的偏见的风险。

解决方案这就是黄金 ETF 的用武之地。因为我们的许多功能都是基于美国的(大多数模型都是这样),所以使用在美国交易所交易的黄金 ETF 作为目标变量是明智的。与使用 LBMA 现货价格不同,现在时区是同步的,数据对齐过程变得更容易。你可能不得不使用一些日内数据,但是你减少了大量不必要的工作。此外,投资组合现在也可以通过使用白银 ETF 的价格作为现货白银的代理来进行调整。通过使用相应的收盘价,可以毫不费力地调整黄金 ETF 价格和白银 ETF 价格。

然而,由于 ETF 的跟踪误差,与使用现货价格相比,使用 ETF 的价格作为代理会出现一些回溯测试滑动。每个试图跟踪指数/资产的 ETF 都会有跟踪误差。好消息是,我们可以选择一只黄金 ETF,表现出可容忍的跟踪误差。

总的来说,我们正在用最小的滑动来换取正确和干净的数据。

导入数据和时区

对于后续的分析,我们将需要 LBMA 黄金固定和 ETFs 数据。我们知道这些时间序列位于不同的时区。为了适应性,我们将把所有时间序列标准化为 UTC,消除日光节约的细微差别。

我们导入 pytz 并定义时区实例:

import pytz
london_tz = pytz.timezone('Europe/London') ***# for LBMA fix***
est_tz = pytz.timezone('US/Eastern') ***# for ETFs***
target_tz = pytz.timezone('UTC') ***# target timezone***

我们从Quandl下载 LBMA 黄金修复 CSV 数据,通过熊猫导入。数据来自 1968 年 1 月 2 日。通过使用 PM fix time,我们可以确保对应的 ETF 价格在市场时段(伦敦时间 15:00 相当于美国东部时间 10:00)。

***#importing LBMA Gold Fix data***from datetime import datetime
import pandas as pd
lbma_gold = pd.read_csv('LBMA-GOLD.csv',index_col = 0,parse_dates=True).sort_index()***#creating gold settlement london pm time***
lbma_gold = lbma_gold.reset_index() 
lbma_gold['PM_TIME'] = '15:00'***#joining date and time***
dt = pd.to_datetime(lbma_gold['Date'].astype(str) + ' ' + lbma_gold['PM_TIME'])***#localize the datetime using london TZ and normalize using UTC TZ***
lbma_gold['UTC_PM'] = [pd.to_datetime(target_tz.normalize(london_tz.localize(x)).strftime("%Y-%m-%d %H:%M:%S")) for x in dt]lbma_gold = lbma_gold.set_index('UTC_PM')lbma_gold.head(10)

UTC LBMA 金牌服务从笔记本中修复数据

处理 NaN 值的方法将在后面介绍。

接下来,我们将获取以下 ETF 数据进行分析:

  • GLD-SPDR 黄金信托公司
  • IAU-iShares 黄金信托公司

这些 ETF 在 NYSEARCA 交易所交易,并跟踪金条,这使它们成为衡量其表现的候选对象。我们将使用来自 、firstratedata.com的分钟数据,这是一家可靠的各种资产的日内数据提供商。数据下载到每个跑马灯的多个文本文件中,并按日期范围分开。我们也将美国东部时间转换为 UTC 时区。

***# function for loading txt files, input in a list of file names***
def load_etf(file_list):
    df = pd.DataFrame()for txt in file_list:
        ***#iterate and concat data***
        temp_df = pd.read_csv(txt,sep=',',header=None)
        temp_df.columns = ["dt", "o", "h", "l","c","v"]
        df = pd.concat([df,temp_df]) 

    df['dt'] = pd.to_datetime(df['dt'])
    df = df.set_index('dt')
    ***#sample to hourly, to speed up time normalization process***  
    df = resample_prices(df,freq='H').dropna() #sample to hour
    df = df.reset_index()
    ***#normalize to UTC* **  
    df['dt']  =  [pd.to_datetime(target_tz.normalize(est_tz.localize(x))
.strftime
("%Y-%m-%d %H:%M:%S")) for x in pd.to_datetime(df['dt'])]df = df.set_index('dt')return df
#==========================================================***# GLD***
gld = load_etf(['GLD_2000_2009.txt',
'GLD_2010_2019.txt','GLD_2020_2020.txt'])***# IAU***
iau = load_etf(['IAU_2000_2009.txt',
'IAU_2010_2019.txt','IAU_2020_2020.txt'])gld.head(10)

笔记本中的 UTC GLD 数据

计算跟踪误差和跟踪差

跟踪误差来源于跟踪差。根据 etf.comT5的说法,跟踪差的定义是“ETF 的表现与指数表现之间的差异”。跟踪误差是指基金的总回报表现与其标的指数的总回报表现之间的跟踪差异的年化标准差。根据每日回报数据,可以通过找出指数回报和 ETF 回报之间的差异来计算每日观察的相应跟踪差异。由此,我们可以计算每日跟踪差异的年化标准差。

我们现在将 LBMA 金牌 PM 修复与 GLD 保持一致。我们移除任何 NaN 行,而不是使用前端填充,因为我们希望我们的计算尽可能真实。

lbma_gld = lbma_gold.merge(gld,how='inner',
left_index=True,right_index=True).loc[:,['USD_PM','o']].dropna()lbma_iau = lbma_gold.merge(iau,how='inner',
left_index=True,right_index=True).loc[:,['USD_PM','o']].dropna()

下面是计算跟踪误差和创建一个新的有跟踪差的数据帧的函数:

***# T.E.Function***
def tracking_error(dff):

    df = dff.copy()
    ***# spot and etf returns* ** 
    df['spot_ret'] = df['USD_PM']/df['USD_PM'].shift(1) - 1
    df['etf_ret'] = df['o']/df['o'].shift(1) - 1
    df = df.dropna()***# daily T.D.***
    df['te_term'] = (df['spot_ret'] - df['etf_ret'])
    ***# take annualized std of daily T.D.***
    te = df['te_term'].std() * np.sqrt(252)return(te,df)lbma_gld_te,lbma_gld_te_df = tracking_error(lbma_gld)
print("Spot vs GLD TE: " + str(lbma_gld_te * 100) + '%')lbma_iau_te,lbma_iau_te_df = tracking_error(lbma_iau)
print("Spot vs IAU TE: " + str(lbma_iau_te * 100) + '%')

与 GLD 一起可视化

import matplotlib.pyplot as plt
%matplotlib inline***# T.D. with std reference lines***
fig = plt.figure(figsize=(15,8))
lbma_gld_te_df['te_term'].plot(label='T.D.')
plt.axhline(lbma_gld_te_df['te_term'].std(), color='r',     
                        linestyle='--',label='+STD')
plt.axhline(-lbma_gld_te_df['te_term'].std(), color='r', 
                        linestyle='--',label='-STD')
plt.legend()
plt.show()***# T.D. probability density plot***
fig = plt.figure(figsize=(15,8))
plt.hist(lbma_gld_te_df['te_term'], color = 'purple', edgecolor = 
                        'black',bins = 200,label='T.D. PDF')
plt.legend()
plt.show()

GLD 每日时间序列和 PDF 图

时间序列和 PDF 图中偶尔会出现时间峰值。理论上,它们代表了异常值,但实际上,它们反映了 GLD 的实证表现。

在下一节中,我们将调查 T.E .和建议因素之间的因果关系。

影响热电势的潜在因素

以下是一些可能影响商品跟踪基金 T.E .的潜在因素:

  1. 基金费用率
  2. 波动性
  3. 期货滚动

费用率

每个基金都有一个费用比率费用。这是向投资者收取的管理费和运营费。潜在的情况是,费用越高,基金在跟踪指数时的表现差距就越大。让我们比较一下 GLD 和 IAU 的费用率和成本费用。众所周知,GLD 的费用率高于 IAU。此外,我们将仅使用 2017 年的数据来重新计算我们的 T.E 。,因为它将描绘与当前费用率更现实的关系。

lbma_gld_te,lbma_gld_te_df =       
                     tracking_error(lbma_gld.loc['2017-01-01':])print("Spot vs GLD TE: " + str(lbma_gld_te * 100) + '%')lbma_iau_te,lbma_iau_te_df = 
                     tracking_error(lbma_iau.loc['2017-01-01':])print("Spot vs IAU TE: " + str(lbma_iau_te * 100) + '%')

成绩对比:

费用率取自 ETF.com

GLD

费用率:0.40%

(2017 年起):3.05%

(自成立以来):3.91%

IAU

费用率:0.25%

(2017 年起):2.95%

(自成立以来):3.87%

结果表明,教育费用与费用率之间存在正相关关系。考虑到 GLD 较高的费用率,IAU 的 T.E .一直相对低于 GLD。

波动性

人们的假设是,当价格大幅波动时,基金将更难跟踪黄金的走势,从而造成回报之间的差异。让我们和 GLD 一起利用这一点。

我们将需要来自 Finnhub.io 的 GLD 每日数据来使用 Wilder 的 ATR 计算滚动波动率。Finnhub 提供了一个免费的 api,允许我们从一开始就获取股票/ETF 的每日数据。

# fetch data from finnhub start and end date in unix timestamp
gld_daily = pd.read_csv('https://finnhub.io/api/v1/stock/candle?symbol=GLD&resolution=D&from=1009843200&to=1588291200&adjusted=true&format=csv&token=' + apikey)# extract UTC timestamp from unix timestamp
gld_daily['dt'] = [datetime.utcfromtimestamp(x) for x in        
                   gld_daily['t']]
gld_daily = gld_daily.set_index('dt')gld_daily.head(10)

来自笔记本的 GLD 每日数据(Finnhub)

我们定义 ATR 函数和一个数据框架函数来创建一个新的数据框架,将现有的 T.D .数据框架与包含每日滚动 ATR 的数据框架合并。20 天的回顾用于定义波动性,相当于 1 个月的跨度。

***# wilder's atr***
def wwma(values, n):
    **"""
     J. Welles Wilder's EMA 
    """**
    return values.ewm(alpha=1/n, adjust=False).mean()def atr(dff, n):
    data = dff.copy()
    high = data['h']
    low = data['l']
    close = data['c']
    ***# calculate true range***
    data['tr0'] = abs(high - low)
    data['tr1'] = abs(high - close.shift())
    data['tr2'] = abs(low - close.shift())
    tr = data[['tr0', 'tr1', 'tr2']].max(axis=1)

   ** *# find ewm of true ranges for n lookback***
    atr = wwma(tr, n)

    return atrdef make_atr_df(df,df_te,n=20):
    mdf = df.copy()
    mdf_te = df_te.copy()
    mdf['ATR'] = atr(df,n)

    ***# convert datetime to date***
    mdf_te['dt'] = list(mdf_te.reset_index()['index'].dt.date)
    mdf['date'] = list(mdf.reset_index()['dt'].dt.date)***# merge atr df with original tracking difference df***
    dff = mdf_te.merge(mdf,how='inner',left_on='dt',right_on='date')
.loc[:,['dt','USD_PM','o_x','spot_ret',                                                            'etf_ret','te_term','ATR']]

 ***# need shifting since vol of previous day will reflect on 
    # subsequent price on 10 AM next day***
    dff['ATR_shift'] = dff['ATR'].shift(-1) dff['dt'] = pd.to_datetime(dff['dt'])
    dff = dff.set_index('dt')

    dff = dff.rename(columns={'o_x':'etf_price'})return(dff.dropna())gld_atr_df = make_atr_df(gld_daily,lbma_gld_te_df,n=20)
gld_atr_df.head(10)

笔记本中的组合数据帧

用 T.D .可视化波动

fig = plt.figure(figsize=(17,7))
graph = gold_atr_df.copy()
graph['te_term'].plot(label='T.D.')plt.axhline(graph['te_term'].std(), color='r', linestyle='--',label='+STD')
plt.axhline(-graph['te_term'].std(), color='r', linestyle='--',label='-STD')plt.legend()
fig = plt.figure(figsize=(17,7))
graph['ATR_shift'].plot(color='green',label = '20 day ATR')plt.legend()
plt.show()

波动性对交易时间的影响

这些图说明了 ETF 的价格波动对 T.D .的影响。当出现突然的波动峰值时,T.D .也会随后出现峰值。在最近的新冠肺炎疫情期间,黄金价格的熊市下跌导致新台币上涨。这些是波动性和 ETF 表现之间因果关系的证据。****

期货卷

许多商品交易所交易基金通过期货市场跟踪商品的价格。该基金将在交割日期前卖出附近的合约,以便【滚动】买入下一个附近的合约。由于黄金期货的期货溢价性质,即使现货价格保持不变,期货价格上涨也会给 ETF 带来损失。我们不确定 GLD 是否存在这种机制,也不确定基金滚动合同的时间。下面的分析检验了我们的假设。****

*****# extract the day of date***
gold_atr_df['day'] = list(gold_atr_df.reset_index()['dt'].dt.day)**

黄金期货合约的第一个交割日期是每个月的第一个交易日。因此,假设 GLD 将在每月的最后 10 天滚动其合约,考虑到某些天不是交易日。我们将数据框架分为 3 天范围:每月的 1 日至 10 日、11 日至 20 日和 21 日至 31 日。然后我们计算每个数据帧的时间长度。为了保证我们分析的可信度,我们每年迭代一次,计算每年的 T.E .并取每年值的平均值。前提是,我们的数据应该代表总体。

*****# separate T.D. series by date ranges***
gld_te_1st_df = gold_atr_df[(gold_atr_df['day'] >= 1) & (gold_atr_df['day'] <= 10)]['te_term']
gld_te_2nd_df = gold_atr_df[(gold_atr_df['day'] >= 11) & (gold_atr_df['day'] <= 20)]['te_term']
gld_te_3rd_df = gold_atr_df[(gold_atr_df['day'] >= 21) & (gold_atr_df['day'] <= 31)]['te_term']***# extract unique years***
years = np.unique(gold_atr_df.index.strftime('%Y'))***# initiate list to store yearly T.E. for each series***
te_1st = []
te_2nd = []
te_3rd = []***# iterate through each year and calcualte T.E.***
for y in years:

    te_1st.append(gld_te_1st_df.loc[y].std() *np.sqrt(252))
    te_2nd.append(gld_te_2nd_df.loc[y].std() *np.sqrt(252))
    te_3rd.append(gld_te_3rd_df.loc[y].std() *np.sqrt(252))***# take the mean* **   
print(np.array(te_1st).mean())
print(np.array(te_2nd).mean())
print(np.array(te_3rd).mean())**

结果

  • 第一至第十区间 T.E.: 3.26%
  • 第 11 至 20 个区间 T.E.: 3.67%
  • 第 21 至 31 个区间 T.E.: 4.02%

我们的结果表明,随着日期范围接近月末,T.E .会增加。虽然 values 没有准确地推断出 T.E .的上升是由于期货滚动结算,但它表明存在一些导致基金表现不佳的交易/再平衡活动。至少,我们确信 GLD 在接近月底时会出现追踪困难。这为未来关于 T.E .上升的潜在月末活动提供了研究机会..

GLD vs IAU:哪一个更好?

我们现在将选择我们的候选 ETF。ETF 的价格将被选为我们预期 ML 模型的目标变量。

方法是计算每个 ETF 的回报对现货回报的敏感度。这种灵敏度被称为线性系数β。另一个要观察的指标是 R 平方,这是衡量 ETF 和黄金价格变动相关性的统计指标。越接近 1,基金表现越好。

我们对每个 ETF 数据框架进行线性回归,观察 R 平方和 Beta,并使用线性拟合可视化散点图。

*****# Beta, R-Squared and plots***
def sensitivity_score(df,c):

    X = df['spot_ret'].values.reshape(-1,1)
    y = df['etf_ret'].values.reshape(-1,1)
    reg = LinearRegression(fit_intercept=False).fit(X, y)print(reg.score(X, y)) ***# R-Squared***
    print(reg.coef_[0][0]) ***# Beta coefficient***

    y_line = reg.coef_ * X ***# Regression line***

    fig = plt.figure(figsize=(18,10))
    plt.scatter(X,y,label='Scatter ETF vs Spot',color=c)
    plt.plot(X,y_line,label='Linear Regression ETF vs Spot',color='black')
    plt.legend()
    plt.show()sensitivity_score(lbma_gld_te_df,'green')
sensitivity_score(lbma_iau_te_df,'red')**

GLD vs 即期回报+回归线

IAU vs 即期回报+回归线

分数:

  • GLD:β= 0.955,R = 0.967
  • IAU:贝塔= 0.956,R = 0.97

IAU 的分数略高于 GLD。仅基于相关性的标准,分数彼此如此接近,以至于我们可以使用 GLD 或 IAU。然而,IAU 的跟踪误差低于 GLD,这反映了 IAU 更好的长期表现。此外,IAU 的费用率低于 GLD,因此我们可以预期长期回报偏差较低。因此,这表明 IAU 可能是一个更好的模型候选人。

结论

我们已经走过了建立黄金模型的先验知识的过程。该流程的重点是分析您的黄金数据,并研究跟踪误差的小细节,从而为模型构建流程添加上下文。我们分析了基金跟踪误差的潜在因素,并提出了一种选择黄金 ETF 目标变量的方法。这里的要点是探索数据与构建高性能 ML 模型一样重要。

未来考虑

  • 对比其他黄金追踪 ETF 的结果
  • 考虑流动性。流动性与买卖价差有直接关系,这一特征会导致回溯测试中的滑动

联系人

领英简介

概率分布之前

原文:https://towardsdatascience.com/before-probability-distributions-d8a2f36b1cb?source=collection_archive---------11-----------------------

为什么我们要使用概率分布,为什么它们很重要?

梅尔·普尔在 Unsplash 上的照片

我决定写这篇介绍概率分布的文章,目的很明确:解释我们为什么使用它们,并应用现实生活中的例子。学习概率时,我厌倦了听掷硬币、纸牌游戏和编号球。除非你只喜欢赌博(这不是我的情况),你需要真正务实地应用概率概念来解决其他问题,而不是彩票中奖的几率。但是在陷入实用主义之前(这将是我们的第一次冲突),我们需要经历一些概念上的事情。这篇文章描述了我们为什么关心概率,并且将帮助你发展一些关键术语,我们将需要这些术语来理解如何把它应用到我们的现实生活问题中。

概率是什么,我们为什么要关心它?

概率是关于解释和理解生活中的随机事件,由于我们生活在绝对的随机性中(即使我们试图相信我们没有),它的有用性变得相当明显。概率是某个随机过程发生某种结果的长期可能性。它基本上告诉你不同种类的事件发生的频率。

使用概率的一些实际例子是:

  • 金融:通过估计给定金融资产在特定范围内下跌的可能性,可以开发交易策略来捕捉预测的结果。
  • 天气预报:气象学家不能准确预测天气,所以他们使用工具和仪器来确定下雨、下雪或冰雹的可能性。他们还检查历史数据库,以估计当天或一周的高温和低温以及可能的天气模式。
  • 保险:概率在分析保险单以确定哪些计划最适合客户以及他们需要多少免赔额时起着重要作用。
  • 运动:运动员和教练用概率来决定游戏和比赛的最佳运动策略。像 BWin 这样的公司已经以此为业,你甚至可以使用不同的策略下注。
  • 广告:概率用于根据潜在客户的消费模式,估计他们更有可能对特定活动做出积极反应。

从数字上来说,概率是一个范围从 0(意味着事件不可能发生)到 1(意味着事件肯定会发生)的数字,如果你把所有可能的结果加起来,你的总和就是 1。概率值越大,事件发生的可能性越大。

所以比如你会说明天下雨的概率是 40%(表述为" P(雨)=0,4" ),或者某个特定地区发生汽车盗窃的概率是 2%(定义为" P(汽车盗窃)=0,02 )。在第一种情况下,您对变量“雨”感兴趣,而在第二种情况下,您对变量“偷车”感兴趣。这些变量,以及任何其他随机过程的结果,被称为“随机变量”。

随机变量是一个受随机变化影响的变量,因此它可以呈现多个不同的值,每个值都有一个相关的概率

它没有特定的值,而是潜在值的集合。在进行测量并显示具体值后,随机变量就不再是随机变量,而变成了数据。

当试图估计它们时,不同的概率呈现不同的复杂性。通常,过去的数据被用作可能发生的事情的代理,但这并不总是适用的(例如,对于没有历史的新事件),或者在极端事件发生时可能具有误导性:想想 2011 年的福岛事故,海啸的高度被低估了,因为概率计算导致了比实际发生的地震小得多的地震。也有不同的方法来计算概率(例如,使用计算机模拟,或收集数据并计算事件发生的时间百分比),但所有这些方法都和你用来提供它们的数据一样好。

概率分布

概率分布是一个随机变量所有可能结果的列表,以及相应的概率值。概率分布将随机变量或过程的每个结果与其出现的概率联系起来。例如,如果你在一个给定的地方采集不同个体的血液样本,你可以计算出他们血型的概率分布:

你在这里做的是统计不同血型的个体数量,然后用每个血型组除以个体总数。这样你就能得到每种血型的概率。

在这种情况下,血型是随机变量。概率分布显示,A 型血的人发病概率最高,而 AB 型血的人发病概率最低。同样,如果你把不同的概率加起来,你会得到 1。你是怎么做到的?简单:你定义你要分析的随机变量(在这个例子中是“血型”),你设置你要统计的类别(“O”、“A”、“B”和“AB”),你统计每个类别中出现的次数。然后,你要么处理这个绝对数字(例如,150 例血型为“A”的病例),要么用它除以病例总数(使它占总数的百分比,就像我们的例子一样)。

但是这里有一个技巧。当您估计随机变量(如血型或任何其他变量)的概率分布时,您实际上是在使用仅代表您正在分析的随机变量的真实行为的一部分的数据。你没有看到所有可能的数据值(用概率术语定义为“群体”),因为你只从给定时间和空间的一个子集(称为“样本”)中获得数据。

样本是总体的子集

由于随机变量的值在分析它们的上下文中会发生变化,所以每次计算结果的概率时,您都需要获取数据的子集(采样),并且由于您是在特定条件下进行的,这意味着如果您将来再次重复分析,您可能会得到不同的结果(由于变量的随机性)。有些值今天比其他值更有可能产生,但其他值可能在其他时间更有可能产生。这样,样本就是我们想要分析的人群的代表,但它永远不会与它 100%相同。

如果我们随时随地测量我们感兴趣的随机变量的所有可能结果,并捕捉它的真实行为,会怎么样?

我的答案是,如果你能做到这一点,那么你的问题就解决了:你可以绝对确定地计算所有结果的概率分布,理解你感兴趣的随机变量的行为,甚至更准确地预测它。然而,大多数情况下(如果不是一直的话),获取您感兴趣的全部数据是极其昂贵的(有时甚至是不可能的)。

举个例子:假设我们对 2000 个成年人进行调查,估计德国(+8000 万栖息地)赞成死刑的成年人比例。如果我们得出 60% (1.200)的被调查者是赞成的,是否可以得出 60%的德国人也是这么想的?显然不是。我们需要使用概率(和统计)工具从我们的样本中建立一个结论,或者获得全部数据,忘记那些烦人的概率概念。你能想象调查 8000 万人吗?

如果你只有有限的结果,而且它们的行为也是随机的,你怎么能描述你正在分析的随机变量的真实行为呢?

好了,现在我们知道,我们想要根据我们在分析中发现的东西(仅限于我们可以得到的样本),对随机变量的“真实行为”得出可靠的结论(不仅在我们的样本中,而且在样本之外)。有没有一种方法可以概括这些结果,使它们具有代表性?

答案是肯定的,这个概括掌握着预测的秘密。如果您可以将特定随机变量的样本结果推广到总体,那么您就可以预测这些随机变量的行为。

预测的力量

概率分布模型帮助你预测特定情况下的结果。当满足某些条件时,这些概率分布模型会帮助您计算每个结果概率、长期平均结果,并估计随机变量结果的可变性,而不需要您感兴趣的随机变量的所有实际结果。

这意味着有一种方法可以将你对随机变量的有限分析结果推广到更广泛的行为,这将帮助你节省时间和金钱,并获得更有信心的结果。许多概率分布模型存在于不同的情况下,关键是你必须选择一个适合你的数据,并帮助你解释你试图理解的正确的模型。

简单来说,概率分布模型是你用来拟合随机变量以概括其行为的指南。这些模型有数学背景,可能非常挑剔。为了使它们正常工作,您试图拟合的随机变量必须满足不同的假设,以便模型的结果具有正确的概率,并且您可以根据随机变量的真实数据来测试和验证模型。

随机变量的类型

到目前为止,我们一直在谈论随机变量,但有不同类型的随机变量。嗯…有意思,但是我们为什么要关心它呢?因为在定义应该选择哪种概率分布模型时,随机变量的类型是一个关键参数。

有两种主要类型的随机变量:

  • 离散随机变量:是那些有有限或可数个可能结果的变量。你通过计数来计算它的值。

比如,想一想“某年某个地方的出生人数”。这是一个离散的随机变量,因为结果可能是 0,1,2…999 或任何其他值。你通过计数得到变量的值。在离散随机变量中,如果你选择任何两个连续的结果,你不可能得到一个介于两者之间的结果。

  • 连续随机变量:有不可数的无限个可能值。你通过测量来计算它的值。

考虑“一个算法运行一项任务所需的时间”。时间通常被四舍五入到合适的间隔,比如秒或毫秒,但事实是它实际上是一个连续体:它可能需要 1.6666666…秒才能运行。体重,温度,价格,都是连续的随机变量。

在概率术语中,离散和连续随机变量是两种不同的生物,应该完全分开对待,它们中的每一个都有不同的概率分布模型。这意味着,如果你在处理一个离散的随机变量(例如,某一地区房主的手机数量),你需要选择一个处理离散随机变量的概率分布模型(你不能选择一个只处理连续随机变量的模型)。

与统计数据共舞

概率与统计学有着密切的关系。事实上,它们是如此紧密地联系在一起,以至于谈论一个而不提及另一个几乎是不可能的。统计学被应用于数据集,以确定表征它们的因素或属性,从而获得关于它们的信息:它是一门与收集和解释定量数据有关的学科,它与概率相结合,使我们有可能对结果进行预测。

一个统计是一个描述数据的一些属性的数值度量,信不信由你,我们每天都在使用它们。例如,当你检查一个足球运动员的平均得分率(在统计学术语中称为“平均值”),或在给定时期你的国家最受欢迎的新生男孩的名字(在统计学术语中称为“模式”),你是在使用统计学。

统计中只描述数据的部分叫做 【描述性统计】 ,而让你做出预测的部分叫做 【推断统计】

均值、众数、中位数、方差、标准差,这些是你可以用来描述数据的一些统计数据,就像在概率中一样,除非你可以访问所有可用的数据(总体),否则一个“统计数据”总是从一个样本中获得:如果你可以从总体中获得它,你会称它为一个“参数”。根据这些信息,可以建立预测模型,并在结果真正实现之前确定某些结果的概率。这样,你就可以用统计学来计算出某一事件发生的概率。

例如,如果你想知道你的假日飞机坠毁的几率(抱歉这个黑暗的例子),你可以想到一年内通常有多少架飞机坠毁,由于这个数字非常小,你可以推断出你的飞机坠毁的概率也很小。在这里,您实际上是通过计算某个参数来应用统计数据,例如失事飞机的数量除以航班总数。或者,您可以使用统计数据,例如来自给定城镇的女性样本数据,对居住在城市等更大区域的大量女性(年龄范围相似)做出推断。

再说一次,我们这样做是因为估计或推断参数比处理现实生活更容易。我们需要统计学来描述我们的可用数据,理解它,然后将它与概率混合,以猜测“真实”(不可用)数据的行为。

这是因为统计数据是可观察的,是根据观察结果计算出来的,而总体参数是抽象的,是不可观察的,必须进行估计(除非您完全可以访问它)。

可以从样本中估计总体参数(推断)

那么,我们如何推断呢?

随机变量的可能结果可以使用统计和概率以不同的方式进行估计:

  1. 计算一个随机变量的单个结果的值(如股票价格均值的精确值),称为点估计
  2. 估计一个随机变量可能结果的一个区间或范围(如股票价格均值的不同值),称为区间估计
  3. 通过使用统计方法来确认或拒绝某个陈述,从而测试该陈述(相对于总体参数)的有效性。这种说法被称为假设,用于此目的的统计测试被称为统计假设测试。

这些方法依赖于概率分布的概念,因为您需要使用概率分布模型来进行推断和归纳您的结论。

最后的想法

概率分布有助于模拟我们的世界,使我们能够获得某一事件可能发生的概率估计,或估计发生的可变性。它们是描述和预测事件概率的一种常用方法。

主要的挑战是定义我们试图描述其行为的变量的特征,因为有必要确定什么分布应该应用于特定过程的模型。

正确分布的识别将允许模型(例如,标准化正态分布)的适当应用,该模型将容易预测给定事件的概率。

对这些话题感兴趣?关注我 Linkedin Twitter

在您开始在线学习数据科学之前

原文:https://towardsdatascience.com/before-you-start-learning-data-science-online-e82415ff8909?source=collection_archive---------40-----------------------

关于年轻有志者在线学习数据科学时犯的错误以及如何克服这些错误的笔记。

背景图片由斯坦纳恩格兰

我们每天产生超过 2.5 万亿字节的数据。仅在过去两年中,我们拥有的世界上 90%的数据都是由[1创造的。于是,出现了很多与数据相关的领域。许多年轻的有志之士每天都开始学习数据科学。我见过我的朋友和其他人在学习它的时候开始犯错误。当我开始学习数据科学时,我也犯过错误。

有很多来自数据科学领域知名机构的伟大教授开设的令人惊叹的课程。很多年轻考生都犯过错误,至少有一次是在学习的时候。甚至你可能曾经犯过这些错误,或者希望有人在你开始学习数据科学之前告诉你这些事情。当我开始的时候,我没有意识到很多事情。我整理了一些人们在开始在线学习数据科学之前应该知道的要点。

在线课程不会教你领域知识

在解决任何问题之前,您需要拥有正确的领域知识。正确的领域知识将帮助您很好地理解数据集的特征,并帮助您构建分析数据集的方法来讲述其中的故事。大多数有志青年都忘记了这一点。领域知识是最容易被忽视的技能,但对初学者来说却是最重要的。但是人们应该意识到,花时间去了解这个领域和他们试图解决的问题是必要的。

领域知识是解决问题的第一步。这是整个解决方案所依赖的基础。

你需要理解数据集

在您匆忙寻找丢失的值或开始清理数据之前,请适当地查看数据集,并尝试很好地理解它。使用 pandas 库中的 describe()方法提取关于数据的更多信息,如平均值、标准差、第一个四分位数。从数据集中选取任何特定的示例,并使用特征来理解它。

图片由斯科特·格雷厄姆

不要急于创建机器学习模型

许多初学者在预处理任何数据之前直接应用 ML 算法。任何人都可以写两到三行来训练算法和预测结果。数据科学家花费 80%的时间准备和管理数据。寻找异常值和相关性,填写缺失值。了解哪个功能影响最大。例如,如果你想解决一个分类问题,那么就要检查分类的不平衡。通俗地说,如果类不包含相同数量的例子,数据集就是不平衡的。例如,在一个二元分类任务中,我的 A 类占总数据的 99%,B 类占 1 %。不平衡的数据可能会导致所谓的过度拟合。

花时间准备和管理数据。在这个预处理中花点时间是没问题的。

在解作业之前理解已经写好的代码

许多初学者通常会学习他们之前在课程的那一周所做的事情,并将其应用到数据中。例如,如果学生正在学习支持向量机(一种分类算法)。在作业中,如果学生必须训练和测试我的模型。大多数学生都会完成这项任务。他们不会注意到之前编写的关于预处理数据的代码。

不要羞于提问

论坛是提问的好方法。不要羞于提问。永远清除你的疑虑。任何人都不应该对提问感到尴尬。继续满足你的好奇心。

重要的是不要停止质疑。好奇心有它存在的理由。——阿尔伯特·爱因斯坦

如果你不懂算法,那就从头实现

如果你在理解一个特定的算法时有问题,那么最好的方法就是自己编写算法。在这个过程中,您将了解它,这将帮助您理解 scikit-learn 这样的库是如何工作的。

图片由 Hitesh Choudhary 提供

不要欺骗自己

当你做作业或测验时,不要抄袭互联网资源。如果你被任务困住了,那就慢慢来。而是你认为解决问题有多聪明,而不仅仅是为了一个证书。我学到的大部分东西都来自于被困在一个问题中。

图像由【JESHOOTS.COM】

以前的编码和数学知识是非常有益的

我不同意有人说学一些数据科学的课程不需要有编码方面的经验。有编码的基础知识有助于相处。他们以后可能会教你 Python/R,但是如果你正在某个课程中学习它,那么我会建议你在像 HackerRank 、 HackerEarth 这样的平台上解决问题,以获得更多关于特定语言的经验,这样以后如果你使用任何像 matplotlib、NumPy 这样的库,你就可以轻松地编写它的代码了。如果你不知道基础数学,那么不要担心,YouTube 上有很好的资源可以学习。如果你想学微积分,那么我会推荐 3Blue1Brown 的微积分、线性代数频道,以及 Stat Quest 的统计学频道。对于希望开始学习数据科学数学的初学者来说,它们是极好的。

图片由 Antoine Dautry 提供

不要满足于 ML 算法的初始结果

您可以随时调整各种算法的值来改进您的模型。不要满足于模型的初始结果。始终使用超参数调整来获得更好的结果。许多算法允许您更改它们的超参数值,如 K 最近邻算法允许您更改可能会改善结果的邻居数量。记住你总是可以表现得更好。

永远不要停止学习

完成任何在线课程后,不要停止学习。在线课程将帮助你建立坚实的基础,但你必须不断学习。不断寻找各种数据集,练习。实践是做好任何工作的关键。不断查看各种博客帖子、笔记本、视频、研究论文,以了解更多信息。永远不要限制自己做任何事。作为一名数据科学家,你需要不断学习新技术。不要放弃。

图像由元素 5 数字

参考资料:

[1] blazon,我们每天创造多少数据 (2019)

适合初学者的机器学习资源

原文:https://towardsdatascience.com/beginner-friendly-resources-for-machine-learning-fd198f844dc3?source=collection_archive---------22-----------------------

闯入人工智能

Avel Chuklanov 在 Unsplash 上拍摄的照片

传统的程序是我们提供给机器的一组指令,用来执行特定的任务。另一方面,机器学习是非常不同和独特的。机器学习是人工智能的一个子集,机器有能力根据经验学习和改进自己,而无需任何人明确编程。机器学习正处于蓬勃发展的阶段,有许多有趣的研究工作正在进行。每个人都想了解它,为了利用它的力量而闯入 AI。不幸的是,它通常被视为一个神奇的黑匣子,接受一些输入数据并给出神奇的预测,但它远不止如此。来自不同特征和领域的学生和开发人员希望开始在他们的项目中使用机器学习,但重要的问题是,

“我从哪里开始机器学习?”

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

进入这个领域不是几天的任务,但今天的许多资源已经使初学者更容易起步。今天,你不需要注册一个博士项目,或者你甚至不需要获得一个计算机科学学位来学习这项新技术。不管背景如何,您都有各种选择来开始使用 ML。在这篇文章中,我们将回顾一些最好的初学者友好的机器学习资源。

在直接进入之前,你应该知道基本上有各种各样的路径可以让你进入 ML 和 AI。有一种自顶向下的方法,在这种方法中,您只需简单地学习高层次的东西,并使用 TensorFlow 和 Pytorch 等框架关注实现[我们将在本文后面讨论这些框架]。另一种方法是,你专注于每一个算法及其背后的所有数学和统计。后一种方法对于想进入人工智能和人工智能研究领域的人来说是最有益的。确定更适合自己的。

根据我的看法,自顶向下的方法更适合大多数想要进入 AI 和 ML 并开始从事他们的项目的初学者。在这种方法中,你可以在需要的时候学习背后的数学知识。在这里,你可以直接体验实际工作,这让你有动力继续学习。然而,如果他们只是不停地学习 ML 的理论,而没有在任何地方使用它,他们可能会失去兴趣。需要记住的重要一点是,在这种方法中,人们倾向于跳过感知部分,只是从互联网或课程中复制粘贴一些代码。代码将会工作,但是理解它背后的直觉和推理是必要的。你必须知道你写的每一行代码的原因。

如果你想从自上而下的方法开始,那么互联网上有很多免费的资源。人们问我的最常见的问题是,“我做过 Python。现在,我如何从 ML 开始?”我的答案是一系列的步骤,我将在这篇文章中讨论。如果你有 Python 语言的知识,那很好,因为它有大量的机器学习库,这使它成为 ML 的最佳语言之一。但是如果你对这种语言一无所知,也不要气馁。这是最简单的编程语言之一。

学习 Python

1-Python for Everybody Specialization由密歇根大学在 Coursera 上开设— 链接 这是 Coursera 上最好的 Python 编程语言入门课程之一。它涵盖了所有的主题,如数据结构,数据库和网络应用程序接口。

[## 面向所有人的 Python

由密歇根大学提供。这种专业化建立在 Python 面向所有人课程的成功基础上,并且…

www.coursera.org](https://www.coursera.org/specializations/python)

2 - 从零开始学习 Python【Python boot camp】在 YouTube 上从零到精通— 链接 Andrei Neagoie 是一位很棒的导师,在 Udemy 上有很精彩的点评。我个人很喜欢他所有的课程。这是他为想开始学习 Python 的人开设的课程。

3 - 学习 Python —初学者的完整课程【教程】由 YouTube 上的 freeCodeCamp 提供— 链接 这是一个大约 4 小时 30 分钟长的视频,在这里您将获得开始学习 Python 语言所需的一切。本课程由 Mike Dane 开发。

用于机器学习的 Python

学习完 Python 之后,最好先掌握一些在 ML 和 AI 项目中需要用到的库的知识,比如 Pandas、Matplotlib、Numpy。

1-Python for Data Science and AI由 IBM 在 Coursera 上— 链接 这涵盖了第一周 Python 的一些基础知识。然后它前进到数据结构和使用 python 处理数据。最后一周包括分析美国经济数据和建立一个仪表板。

[## 用于数据科学和人工智能的 Python

由 IBM 提供。用这个开始你的数据科学 Python 学习,以及一般的编程…

www.coursera.org](https://www.coursera.org/learn/python-for-applied-data-science-ai?)

密歇根大学 Coursera 上的 2 - 应用数据科学与 Python 专业——链接 对于所有 ML 爱好者来说,这是一个非常棒的专业。如果你完成了这门课程,你将会非常熟练地使用 python 语言进行数据可视化、挖掘、操作以及数据科学中需要的其他东西。

[## 使用 Python 的应用数据科学

由密歇根大学提供。密歇根大学专业的 5 门课程向学习者介绍了…

www.coursera.org](https://www.coursera.org/specializations/data-science-python)

3 - 用于数据科学的 PythonupGrad-链接 本课程涵盖的主题包括 Python 简介、使用 Python 编程、数据科学库和数据可视化。

[## upGrad 的免费在线课程

upStart 是 upGrad 中一个独特的生态系统,帮助您保持领先地位,并体验 upGrad 的一部分…

www.upgrad.com](https://www.upgrad.com/free-courses/?utm_source=organicchannels&utm_medium=web&utm_campaign=banner_homepage)

熟悉这些库的最佳资源是浏览它们的官方文档。它们是探索和深入了解它的最佳场所。

https://numpy.org/doc/
熊猫—https://pandas.pydata.org/docs/
马特普洛特利—https://matplotlib.org/3.3.2/contents.html

ML 和 AI 的基础

在学习 python 和函数库的时候,最好继续学习人工智能的基础课程,这样你就能直观地了解它到底是什么。

Reaktor 和赫尔辛基大学合作的 1 - 人工智能元素——链接 人工智能元素是一门免费的在线课程,面向所有初学者。你会得到人工智能的基本概念,他们的主要目标是揭开人工智能的神秘面纱。

[## 面向非专家的免费人工智能在线介绍

2018 年春天,Reaktor 和赫尔辛基大学携手合作,旨在帮助人们获得力量…

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

2-AI For every oneby deep learning . AI on Coursera—链接 这是吴恩达策划的又一场精彩课程。它涵盖了任何人在涉足人工智能之前可能想知道的所有要点。这是为各种性格和背景的人准备的。

[## 面向所有人的人工智能

由 DeepLearning.AI 提供 AI 不仅仅是给工程师的。如果你想让你的组织更好地使用人工智能…

www.coursera.org](https://www.coursera.org/learn/ai-for-everyone)

3-Google 开发者在 YouTube 上的机器学习方法——链接 在这个系列中,乔什·戈登很好地解释了任何人如何使用 Scikit Learn 和 TensorFlow 这样的库开始使用 ML 的基本代码。

4-upGrad 上的机器学习概念介绍——链接 这是一门为期 6 周的课程,涵盖了线性回归、逻辑回归、聚类和推荐系统等 ML 主题。

[## upGrad 的免费在线课程

upStart 是 upGrad 中一个独特的生态系统,帮助您保持领先地位,并体验 upGrad 的一部分…

www.upgrad.com](https://www.upgrad.com/free-courses/?utm_source=organicchannels&utm_medium=web&utm_campaign=banner_homepage)

机器学习深入

在经历了人工智能的基础知识并准确理解其背后的概念后,ML 不再是一个神奇的黑匣子。现在,您应该更深入地了解它,并学习如何使用 TensorFlow 和 PyTorch 这样的框架来构建自己的 ML 模型。

1 - 机器学习斯坦福大学 Coursera — 链接 如果你想深入了解所有类型的机器学习算法,这是你的不二之选。课程内容非常精彩,形式也很好。在本课程中,您将看到回归、分类、神经网络、异常检测、推荐系统等等。它充满了伟大的内容。

[## 机器学习

机器学习是让计算机在没有明确编程的情况下行动的科学。在过去的十年里…

www.coursera.org](https://www.coursera.org/learn/machine-learning?)

2 - 机器学习速成班 by Google — 链接 本速成班是有志于机器学习从业者的自学指南。它包含一系列课程,包括视频讲座、真实案例研究和动手实践练习。

[## 机器学习速成班|谷歌开发者

学习和应用基本的机器学习概念的速成课程,获得现实世界的经验与…

developers.google.com](https://developers.google.com/machine-learning/crash-course)

3 - MIT 6。S19:深度学习入门 — 链接 麻省理工学院关于深度学习方法的官方入门课程,应用于机器人、游戏、艺术、计算机视觉、语言、医学等领域!学生将获得深度学习算法的基础知识,并获得在 TensorFlow 中构建神经网络的实践经验。

[## 麻省理工深度学习 6。S191

麻省理工学院关于深度学习方法的入门课程,应用于计算机视觉,自然语言处理…

introtodeeplearning.com](http://introtodeeplearning.com/)

4 - 深度学习。AI TensorFlow 开发者专业证书 — 链接 TensorFlow 是 Google 的一个开源机器学习库,它让构建深度学习模型变得非常容易。这是一个非常强大、可伸缩和灵活的框架。本课程将引导你了解从初级到中级的所有关于 TensorFlow 的知识。

[## 深度学习。AI TensorFlow 开发者

由 DeepLearning.AI 提供。TensorFlow 是最受欢迎和最受欢迎的开源深度学习框架之一…

www.coursera.org](https://www.coursera.org/professional-certificates/tensorflow-in-practice)

5 - 用 PyTorch 介绍深度学习由脸书人工智能在 Udacity 上——链接 PyTorch 是脸书 AI 研究实验室的另一个开源机器学习库。它基于 Torch 库。它允许用户很容易地在较低的级别上进行修改和更改,因此它主要在研究领域流行。本课程涵盖了 PyTorch 入门所需的所有基础知识。

[## PyTorch 深度学习简介| Udacity 免费课程

深度学习正在推动人工智能革命,PyTorch 正在让任何人比以往任何时候都更容易建立深度学习…

www.udacity.com](https://www.udacity.com/course/deep-learning-pytorch--ud188)

根据领域定制

一旦你熟悉了机器学习和之前课程中的所有基本算法,你会想要探索机器学习中的特定领域,如深度学习、自然语言处理、计算机视觉等。这里有一些很好的课程,将从零开始涵盖这些主题。

1 - 深度学习专业化由 Coursera 上的 Deep Learning . ai—链接 入门神经网络和深度学习,对我来说,这是最重要的课程之一。他们的项目笔记本是测试我们能即时应用多少知识的好方法。

[## 深度学习

从 deeplearning.ai 学习深度学习,如果你想打入人工智能(ai),这个专精…

www.coursera.org](https://www.coursera.org/specializations/deep-learning)

2 - 自然语言处理专门化由 Coursera 上的 deep learning . ai—链接 深度学习蓬勃发展的另一个领域是 NLP。NLP 需要大量的预处理,并且总体上有一种不同的方法。通过专业学习后,你会对这个领域充满信心。

[## 自然语言处理

自然语言处理(NLP)使用算法来理解和操纵人类…

www.coursera.org](https://www.coursera.org/specializations/natural-language-processing)

3-fast . ai 为编码人员提供的实用深度学习——链接 Fast.ai 是另一个库,旨在让任何背景的人都更容易建立 ML 模型。这是基于 PyTorch 的,有很大的特点。他们的课程涵盖了这个图书馆的一切,Fast.ai 的创始人杰里米也以非常易懂的方式解释了机器学习的大多数重要概念。

[## 面向编码人员的实用深度学习

如果你现在就准备好投入进去,下面是开始的方法。如果你想更多地了解本课程,请阅读…

course.fast.ai](https://course.fast.ai/)

4 - 医药专用 ai由 deeplearning.ai 上 Coursera — 链接
医药用 AI 和其他用途 AI 不是很像。它要求更高的精度,更高的准确度,而我们可用的数据却非常少。本课程展示了数据扩充和其他方法的力量,用更少的数据建立更好的模型。

[## 医学人工智能

模型解释图像分割自然语言提取机器学习时间到事件建模深度…

www.coursera.org](https://www.coursera.org/specializations/ai-for-medicine)

5 - 强化学习由佐治亚理工学院在 Udacity 上— 链接

[## 强化学习| Udacity 免费课程

免费课程由佐治亚理工学院提供,编号为 CS 8803。关于本课程的免费课程,如果你需要,你应该选修本课程

www.udacity.com](https://www.udacity.com/course/reinforcement-learning--ud600)

6 - 深度强化学习课程 — 链接 本课程是一系列文章和视频,在这里您将掌握成为深度强化学习专家所需的技能和架构。您将通过 Tensorflow 和 PyTorch 实现出色的代理来建立强大的专业投资组合,这些代理学习玩太空入侵者、《我的世界》、星际争霸、刺猬索尼克等等!

[## 深度强化学习课程

深度强化学习课程是一个关于深度强化学习的免费课程(文章和视频),其中…

simoninithomas.github.io](https://simoninithomas.github.io/deep-rl-course/)

7-Coursera 上的 deeplearning.ai 提出的生成对抗网络——链接 GANs 是 Ian Goodfellow 在 2014 年提出的一个相对较新的概念。GANs 概念对深度学习的认知产生了巨大的变化。这是一门很好的课程,你以后可能会想学。

[## 生成对抗网络

由 DeepLearning.AI 提供关于 GANs 生成对抗网络(GANs)是强大的机器学习模型…

www.coursera.org](https://www.coursera.org/specializations/generative-adversarial-networks-gans)

8 - 关于深度学习和自然语言处理的介绍关于 upGrad-链接 了解更多关于 AI 和 ML 背后的数学这门课程包括为期 4 周的数据分析背后的数学、深度学习的介绍和自然语言处理的介绍。

[## upGrad 的免费在线课程

upStart 是 upGrad 中一个独特的生态系统,帮助您保持领先地位,并体验 upGrad 的一部分…

www.upgrad.com](https://www.upgrad.com/free-courses/?utm_source=organicchannels&utm_medium=web&utm_campaign=banner_homepage)

9 - 机器学习和云高级认证由 IIT 马德拉斯在 upGrad — 链接 在本课程中,您将学习使用云计算和印度最先进的认证计划部署机器学习模型,该计划由 IIT 马德拉斯& upGrad 独家提供。

[## IIT 马德拉斯大学的机器学习和云计算高级认证| upGrad

通过印度最先进的认证计划,学习使用云计算部署机器学习模型…

www.upgrad.com](https://www.upgrad.com/advanced-certification-ml-cloud-iitm/)

有趣的播客

播客是与机器学习领域保持同步的最佳资源,因为它非常活跃并且不断变化。我提到了一些我听过的最好的播客。

1 - 线性题外话 — 链接

2 - 莱克斯·弗里德曼播客 — 链接

3 - 数据怀疑者 — 链接

最佳书籍

就我个人而言,在学习完这些课程后,我发现书籍是最好的知识来源。这是你可以加强对你在 ML 项目中使用的概念的理论理解的地方。

1 - 百页机器学习书作者安德烈·布尔科夫
一本很短但知识很完善的书。安德烈已经压缩了 AI/ ML 中所有至关重要的点,放在这本 100 页的书里【准确的说是 138 页】。

2 - 用 Scikit-Learn、Keras 和 Tensorflow 2.0 实践机器学习的书作者 Aurelien Geron-O ' Reilly
对我来说,这本书是 deeplearning.ai 的机器学习和深度学习专业的替代物。我更喜欢这本书,因为它有完美的解释,每个概念都有很好的代码可以一起尝试。你也可以通过以下链接获得本书的开源代码—https://github.com/ageron/handson-ml2

3 - 深度学习书作者:Ian Goodfellow
如果你想更深入地了解深度学习的数学方面,那么这本书有你需要的一切。是 2015 年出版的,所以比较老但是内容很棒。

乙举证书

Max Tegmark
Life 3.0 不是用来学习 AI 和 ML 的,但它是一本美丽的书,讨论了人工智能对人类未来的影响和宇宙的影响。作者的观点很有趣,这的确是一本好书。

结论

最后,我们已经到达了整个资源列表的末尾。这些很多,还有更多!但不要不知所措。一旦你浏览了大部分的资源,你会发现自己探索更多和发现新的有用资源是很有趣的。最重要的是要知道,你不应该停留在完成课程和书本上。时不时地继续做项目。让你在学习每项新技能后建立项目成为一种习惯。对我来说,这是你知道自己学到了什么的方法,也是你保持动力的方法——通过建立有趣的项目。

此外,继续阅读技术博客和文章。Medium、Wired、TechCrunch 是这类技术博客的好去处。了解最新的研究成果。你会注意到,开始时你不会理解很多,但随着你的进步,一切都变得有意义了。很高兴看到 ML/ AI 最近的进展,因为一切都在快速变化。

前方是一段伟大的旅程……继续学习!

初学者指南,在 10 分钟内构建、比较和评估机器学习模型

原文:https://towardsdatascience.com/beginner-guide-to-build-compare-and-evaluate-machine-learning-models-in-under-10-minutes-19a6781830de?source=collection_archive---------35-----------------------

通过 Python 示例笔记本,探索构建机器学习模型的主要步骤。

初学者指南,在 10 分钟内建立、比较和评估机器学习模型。约书亚·索蒂诺在 Unsplash 上拍摄的照片

本笔记本的目标是给出构建和评估机器学习模型的步骤的高级概述。这是通过将每一步总结成最短的形式来完成的,所以请记住,在现实生活中,每一步都要复杂得多。

你可以跟着一起过来 完整笔记本

机器学习的步骤

  1. 数据准备— 检查并准备数据集
  2. 定义模型验证策略— 在训练、验证和测试集中拆分数据
  3. 模型开发— 使用 Python 中的 sklearn 库构建三个不同的模型:随机森林、决策树、逻辑回归。
    模型评估和微调使用 GridSearch 交叉验证
  4. 型号选择
  5. 最终模型评估

步骤 1:数据准备

对于这个项目,我将使用现有的网络安全数据集。该数据集的目标是预测某个连接是否是网络攻击。

数据集包含许多历史连接数据。对于这些连接中的每一个,已经注册了关于它们的不同变量。我们还有一个变量来表示连接是否危险(网络攻击)。

目标是开发一个能够“学习”如何区分正常连接和危险连接的模型。我们还不知道如何做到:我们的机器学习模型将不得不学习这一点。

这一行的结果:scikit learn 获取数据集。

下面我们看到了数据的快速打印。第一列给出了关于连接类型的信息,其他列是关于连接的数字信息(参见 kddcup99 以获得关于变量内容的更多详细信息)。

这一行的结果:我们数据的前 5 行。

在现实生活中的机器学习案例中,我们需要检查这些数据,并找出我们应该使用哪些变量,或者我们应该明确忽略哪些变量。但这是一个简单的例子,所以我们按原样取数据,看看我们在 10 分钟内可以获得什么样的精度。因此,我们删除了关于连接类型的列,并且我们以相同的方式对待每种类型的连接。

我们还检查了因变量,我们注意到它不是我们想要的数字 1 对 0 格式。让我们改变这一点。

这是目标变量的格式。我们想把它转换成 0 和 1。

为了快速了解数据,我们在数据中绘制了攻击和正常连接的计数。请注意,我们的数据是有偏差的,因为“攻击”连接比正常连接多得多。

正常(0)连接和攻击(1)连接的最终分布不是 50–50。

第二步:定义模型验证策略:训练验证测试分割

为了验证任何预测模型,我们最好将一部分数据分开。当完成开发一个模型时,我们将能够在这个测试数据上应用它。这允许我们在实际部署模型之前,测量我们的模型在现实生活中的效果。

我们有很多观察结果,所以我们可以允许分成三个部分:训练、验证、测试。在数据较少的情况下,我们通常一分为二:训练和测试。

  • 训练数据:用于开发 3 个模型,并通过超参数调谐(网格搜索)进行微调
  • 验证数据:用于型号选择
  • 测试数据:用于对我们的分类模型的样本外精度有一个客观的最终估计

第三步:模型开发

在模型开发步骤中,我们将构建三个不同的模型,并应用 GridSearch 进行超参数调整。实际上,测试三个模型是您应该测试的最少模型数量。尝试更多的模型有更高的机会找到一个伟大的结果!

我们将使用的三种模型是:

  • 随机森林
  • 决策图表
  • 逻辑回归

除了玩模型的选择,我们还可以玩每个模型的超参数的选择。有一种自动化的方法可以测试大量的超参数组合,并保留最佳评分超参数组合:网格搜索。

将使用 GridSearchCV 调整以下超参数:

  • 对于随机森林:“最大特征”
  • 对于决策树:“最大特征”和“最小样本分割”
  • 对于逻辑回归:“C”

步骤 3a:随机森林超参数调整

步骤 3a 结果:对验证数据应用随机森林并打印 roc_auc_score

99%很高!

步骤 3b:决策树超参数调整

步骤 3b 结果:对验证数据应用决策树并打印 roc_auc_score

也 99%,也很高!

步骤 3c:逻辑回归超参数调整

步骤 3c 结果:对验证数据应用逻辑回归并打印 roc_auc_score

94%也高,但是有点不太好。

第四步:在验证数据集上选择性能最佳的模型

根据 GridSearch 的分数,选择的模型将是随机森林!

步骤 5:精度的最终估计:将选择的模型应用于测试数据

为了获得随机森林准确性的最终估计,我们将其应用于测试数据。这为我们提供了一个新的准确度分数,该分数可能更接近于从任何新的(外部)数据中获得的分数。

分数相差不大,可以保留模型。

虽然机器学习建模的实际过程比这要复杂一点,但我希望这篇文章确实对需要采取的不同步骤进行了很好的高层次描述。记得你可以跟着 一起把 的完整笔记本拿过来。希望你喜欢这篇文章。感谢阅读,不要犹豫,继续关注更多!

如何从 OpenStreetMap 下载数据集?

原文:https://towardsdatascience.com/beginner-guide-to-download-the-openstreetmap-gis-data-24bbbba22a38?source=collection_archive---------9-----------------------

面向所有人的开源 GIS 数据

插图作者:金彩云

为什么选择 OpenStreetMap?

它是免费的。💸

有许多可用的地图提供商,如谷歌、OS Survey、Mapbox、等等。但是数据是有版权的,达到限额后你要为你使用的东西付费。而 OpenStreetMap(OSM) 对每个人都是免费的,没有任何隐性费用。它是在开放数据公共开放数据库许可 (ODbL)下许可的。每个人都可以自愿贡献数据,每个人都可以免费使用这些数据!

获取原始数据!📂

大多数商业地图提供商不会让您访问地图背后的数据。使用 OpenStreetMap ,您可以完全访问数据库,并且可以提取所需位置的原始 GIS 数据。

全球数据覆盖🌍

世界各地成千上万的贡献者不断更新数据,使 OpenStreetMap 成为覆盖世界各地的最新 GIS 数据库之一。

从 OpenStreetMap 获取 GIS 数据

有几个在线工具可以从 OpenStreetMap 数据库下载 GIS 或地图数据。在这些工具中,您可以根据所需的输出数据格式、大小和要求的边界区域来选择它们。

案例 1:如果您需要一个带有指定边界框的小型 GIS 数据集。

在这种情况下,您可以直接从主OpenStreetMap网站获取数据,非常快速简单,虽然输出数据格式和大小有限。它允许您在中导出 GIS 数据。osm 格式,面积限制为 0.25 度( )平方(例如 1 x0.25 或 0.5x0.5 等),其中 1 约为 69 英里或 111 公里。如果您的项目需要更大的数据,请使用其他可用的工具。

从 https://www.openstreetmap.org/导出 OSM 数据

要提取数据,你只需浏览到 OpenStreetMap 网站,像任何其他网络地图一样使用搜索、平移、缩放工具找到你想要数据的区域。然后,使用顶部工具条菜单上的导出工具,在导出数据前确认边界框区域。就是这样!

如果在某处保存了边界框区域,还可以使用以下结构直接构造对 OpenStreetMap API 的 HTTP 调用,以下载 OSM 数据:

https://api.openstreetmap.org/api/0.6/map?bbox=**<min long>**, **<min lat>**, **<max long>**, **<max lat>**

无论哪种方式,都会得到中所选区域的数据。osm 格式。如果想要其他数据格式,请使用其他工具。

情况 2:如果您需要一个具有指定边界框的较大 GIS 数据集。

现在,假设您的项目需要更大的数据,您可以使用 BBBike Extract 服务提取指定边界框区域的 GIS 数据。该 web 应用服务允许您提取和下载多种格式的 OSM 数据,包括 OSMPBFGarminShapefilemapsforgeOsmAndSVGGeoJSONSQL 等。每个请求的最大请求大小为 512 MB,处理大约需要 2-7 分钟。

BBBike 摘录 Web 界面

要使用这项服务,你只需要在地图界面中平移或缩放到你想要的区域,并绘制出你需要的区域的边界框区域。然后,点击提取按钮,等待您的结果,您可以在https://download.bbbike.org/osm/extract/看到您的数据提取状态

案例 3:如果您需要特定行政区域的 GIS 数据集。

如果您需要世界上任何特定行政区域的 GIS 数据, GeoFabrik 下载服务器将是您的正确选择。它提供每天更新的现成 GIS 数据,并允许您下载不同级别的数据,包括洲、国家、州和更小的级别。该工具为您提供了中的数据。面向全球的 osm 格式和面向小型数据集的 ESRI 形状文件格式。访问该网站后,您会在页面的左下角找到可用数据的表格列表。您可以选择直接从各大洲下载 .osm.pbf.osm.bz2 格式的数据。

GeoFabrik 下载服务器中的可用区域列表

或者如果你只需要特定的子区域,比如德国拜仁州某个地区的数据,你可以通过子区域菜单欧洲 > 德国 > 拜仁简单选择。更深层次的数据可以在下载。osmESRI shapefile 格式。

GeoFabrik 下载服务器中的子区域区域数据

或者,如果您想要使用 GeoJSON 格式的数据,您可以使用 OSM 跨线提取 工具以相同的方式提取数据,但其数据覆盖范围较小。

案例 4:如果你需要一个完整的 OSM 数据集。

如果您的项目需要一个完整的 OSM 数据集并使用数据库,请随时前往 行星 OSM 服务,您可以找到并下载整个 OSM 数据集。它有一个压缩的 XML 文件(超过 88GB)和一个定制的 PBF 格式文件(超过 50GB)。你可以点击 查看用于处理这些 OSM 文件类型 的工具列表。此外,历史 OSM 数据集也可用于此源。更多关于 OSM 星球的数据和网络可用性的信息可以在 这里 找到。

案例 5:如果您想要查询部分 OSM 数据集。

您可以看看 立交桥 API 来查询您需要的部分 OSM 地图数据。如何使用立交桥 API 的教程在 这里 有。你可以在 天桥 Turbo 上试试,作为直接通过 web 查询 OSM 数据的界面。

如果您已经在使用 QGIS 软件,您可以尝试使用 QuickOSM 插件来轻松查询您需要的特定数据集。在后端,该插件使用 trans 过场 API 下载查询到的 OSM 数据,并将数据转换为 QGIS 矢量图层。假设您的机器上已经安装了 QGIS 的更新版本,让我们来看看如何安装和使用 QuickOSM 插件的基本指南:

如何使用 QuickOSM 插件 QGIS 软件的基本指南

  1. 打开 QGIS 软件后,在插件菜单中找到名为 QuickOSM 的插件。
  2. 安装插件!!
  3. 安装完成后,你会在 Vector 菜单栏中找到这个工具。
  4. 查询你需要的数据。例如,上图显示了对斯图加特地区行政边界的查询。然后,等待插件下载完数据。如果你愿意,你也可以在查询标签中使用天桥 API。
  5. 搞定了。数据图层被添加到 QGIS 中。请注意,您应该将项目坐标系设置为 WGS 84/伪墨卡托(EPSG:3857)以使用 OSM 数据集。

请注意,您还可以使用任何其他选项来下载 GIS 数据,因为 QGIS 默认支持 OSM 矢量文件。

案例六:还有什么?🤔

如果你熟悉 Python3 或 Docker,想为你的项目自动化一些流程,可以使用 OpenMapTilesdownload-osm工具下载指定位置或整个星球的 osm 数据。如果你热爱 Java,请查看一下 渗透 repo,这是一个用于处理开放街道地图数据的命令行 Java 应用程序。

作者消息:

大概就是这样。有多种工具可用于从 OSM 提取或下载 GIS 数据。我希望这篇文章能帮助你找到适合你的项目的合适的工具或方法。如果你有任何问题,请随时给我发信息。

关于我&查看我所有的博客内容:链接

平安健康!
感谢阅读。👋😄

深度学习和 CNN 的初学者速成班

原文:https://towardsdatascience.com/beginners-crash-course-to-deep-learning-and-cnns-a32f35234038?source=collection_archive---------26-----------------------

没有复杂数学的生动解释。

注:这是我关于深度学习和卷积神经网络的视频总结。如果你感兴趣,可以随时观看,了解更多信息!

本文中的所有资产和图像都是由我创建的

深度学习极其迷人。从识别和分类图像,到甚至产生梦一样的幻觉,深度学习都做到了。

当我了解到这个话题时,我不断受到极其复杂的数学方程和无数充满缩写词的术语的轰炸,听起来像是深度学习的口袋妖怪等价物。然而,剥去所有这些,深度学习实际上变得直观了。欢迎来到我的深度学习和卷积神经网络的“动画”指南!

图像分类

我们将通过使用一个蜱的黑白图像来简化事情,其中一层代表一个专用的黑白通道。黑色用-1 表示,而白色用正 1 表示。

分笔成交点的数字表示

现在,如果我们想对图像本身进行分类,我们需要首先对输入进行一些处理。

卷积步骤

这里的主要目的是从输入图像中提取关键特征。

为了检测特征,我们需要一个叫做过滤器的东西。过滤器只是一种模式的数字表示。从这里,我们可以看到,这定义了蜱的茎的模式。

滤波器的数值表示

从左上角开始,这个过滤器试图找到与它所具有的特征相匹配的特征。请注意,这个过滤器在任何时间点都只关心一个小区域。这个区域被称为感受野

为了找到匹配,过滤器对它正在查看的图像部分执行一系列数学运算。

过滤器对图像的一部分执行的数学运算

首先,对于每个对应的图像和过滤器像素,将这些值相乘。然后,将它们相加给出一个结果。然后将该值除以过滤器中的像素总数,得到平均值。计算结果随后存储在特征图中的一个像素上。

整个图像的卷积过程

当滤波器逐步移动并在每个点执行操作时,我们对整个图像重复这个过程。滤波器的这种滑动运动概括了卷积的全部思想。过滤器在每一步移动的距离称为步长,在本例中为 1。

此时,您可能想知道:功能图的意义是什么?特征图实际上是我们的过滤器的特征与图像匹配程度的空间表示。理解上面的值的直观方式是,1 表示完全匹配,而-1 表示完全不匹配。中间的任何剩余值仅仅表示部分匹配。

我们可以使用不同的过滤器来帮助检测其他特征。可以相应地定制每个滤波器的大小和我们想要在这个卷积步骤中使用的滤波器的数量。

至此,我们的第一个卷积层就完成了。

整流线性单位

校正线性单位—标准化过程

现在,我将添加一个层来将我们的特征图中的所有负值变成零,这是一种纠正特征图的归一化的形式。这被称为 ReLU 层,代表整流线性单元。

最大池化

步长为 2 的 2px x 2px 区域的池化过程

此外,我们可能还会添加一个层来做一些精简,以帮助提高计算速度。一种方法是从一个区域中取出最重要的值(也就是最大值)并记录下来。这就是所谓的最大池层。在这种情况下,我的 max-pooling 层汇集了一个 2px 乘 2px 的区域,并设置为步长为 2,一次移动两个像素并记录值。

我们像汉堡一样重复和堆叠上述层,以形成卷积神经网络的肉,增加了有助于图像分类的特征的复杂性。

全连接层

最后,我们添加一个完全连接的层来解释结果。这基本上是你通常看到的代表神经网络的通用神经元和突触模型。

为了直观地理解它,这只是网络决定某个特征的重要性的地方。越重要,“权重”越重——用粗线表示——意味着神经元之间的联系越强。

全连接层介绍和图像展平演示

第一层神经元代表在一系列卷积、ReLU 和汇集循环之后创建的特征图的每个单独像素,像这样被展平成一维。该像素的值可以被视为神经元的信号强度,值越高表示信号越强。因此,随着连接越来越强,这组神经元发出的信号的更大比例可以通过。

最后一层神经元的激活

这最后一层神经元将告诉我们它在预测某个对象时有多自信。这些神经元的激活是基于它接收到的信号的强度。更高的激活意味着来自先前神经元的累积信号更强。

因为我们要在两类物体之间做出决定,所以我们会有两个输出神经元——一个用于滴答,一个用于十字。激活 1 表示将图像分类为它所对应的任何类别的百分之百的置信度,而 0 表示完全拒绝。如果你愿意,你可以在它们之间堆叠更多的神经元层,使你的模型更加动态。

学习过程

直觉的、非数学的解释

训练模型的想法就像你训练宠物变戏法一样。如果宠物玩得好,你就奖励它们一份礼物。嗯,对于机器来说,它们的“待遇”是以成本函数的形式定义的。如果他们表现得更好,成本函数的值就会更低,这意味着他们的方向是正确的,反之亦然。神经网络想要尽可能地最小化这个成本。

为了训练神经网络,我们需要称为训练集的数据。训练集包含一组图像,在我们的例子中是勾号和叉号,它们都标有正确的答案。每当我们向网络提供一幅图像时,它就会通过所有层,根据它认为的图像生成一个响应。根据输出,网络会对自己进行评估,并确定它与正确答案的差距。

然后,网络调整权重,以试图通过找到正确的组合来提高其准确性,从而将自己导向正确的方向。这是通过反向传播和梯度下降完成的,这涉及到一点微积分,在这里将不深入讨论。

最小化成本函数的图形表示

然而,从图形上来说,它试图编辑成本函数,以便最终达到局部最小值。它学习的速率可以通过改变它的学习速率来修改。

然后,我们使用一个验证集,这是一组神经网络看不到的图像,来检查它在训练阶段后的性能。这就好比让神经网络考试,看它考得怎么样。

然后,如果需要的话,我们进一步训练该模型,以获得可能的最佳结果。现在,你已经对卷积神经网络和深度学习有了直观的了解!

我确实希望这篇文章能帮助你更好地理解深度学习和 CNN。感谢您的阅读!

自然语言处理中数据清理和特征提取初学者指南

原文:https://towardsdatascience.com/beginners-guide-for-data-cleaning-and-feature-extraction-in-nlp-756f311d8083?source=collection_archive---------24-----------------------

来源:莱弗吉尼亚州途径:摄影记者

本文将解释使用神经语言处理(NLP)进行文本分析的数据清理和未来提取的步骤。

在网上,有很多很棒的文字清理指南。一些指南在文本清理之后进行特征提取,而一些指南在文本清理之前进行特征提取。这两种方法都很好。然而,这里有一个很少被关注的问题:在数据清理过程中,我们丢失了一些可能的特征(变量)。在数据清洗之前,我们需要进行特征提取。另一方面,有些特征只有在数据清理后提取时才有意义。因此,我们还需要在数据清洗后进行特征提取。本研究关注这一点这是本研究的独特之处。

为了解决上述问题,本研究依次遵循三个步骤:

  1. 特征提取—第一轮
  2. 数据清理
  3. 特征提取—第二轮

这篇研究文章是采用 NLP 方法的亚马逊综述分析的一部分。这里是主研究代码的 Colab 笔记本的 my GitHub repo ,以及本次研究的 代码

关于我使用的数据的简要信息:本项目使用的数据是从 Kaggle 下载的。是斯坦福网络分析项目上传的。原始数据来自 J. McAuley 和 J. Leskovec (2013)对“从业余爱好者到行家:通过在线评论对用户专业知识的演变进行建模”的研究。这个数据集由来自亚马逊的美食评论组成。该数据包括了从 1999 年到 2012 年的所有 568,454 篇评论。评论包括产品和用户信息、评级和纯文本评论。

特征提取—第一轮

在这一部分中,将提取数据清洗后不可能获得的特征。

  1. 停用词的数量:停用词是搜索引擎已经被编程忽略的常用词(例如“the”、“A”、“an”、“in”),无论是在索引用于搜索的条目时还是在作为搜索查询的结果检索它们时。在 Python 的 nltk 包中,有 127 个英文停用词默认。通过应用停用词,这 127 个词被忽略。在删除停用词之前,让我们将“停用词数量”作为一个变量。
df['stopwords'] = df['Text'].apply(lambda x: len([x for x in x.split() if x in stop]))df[['Text','stopwords']].head()

2.标点符号的数量:数据清洗后无法获得的另一个特征是因为发音会被删除。

def count_punct(text):
    count = sum([1 for char in text if char in string.punctuation])
    return count#Apply the defined function on the text data
df['punctuation'] = df['Text'].apply(lambda x: count_punct(x))#Let's check the dataset
df[['Text','punctuation']].head()

3.标签字符的数量:我们可以从文本数据中提取的一个更有趣的特征是标签或提及的数量。在数据清理期间,标签将被删除,我们将无法访问这些信息。因此,让我们在仍然可以访问它的时候提取这个特性。

df['hastags'] = df['Text'].apply(lambda x: len([x for x in x.split() if x.startswith('#')]))df[['Text','hastags']].head()

4.数字字符的数量:拥有评论中出现的数字字符的数量可能是有用的。

df['numerics'] = df['Text'].apply(lambda x: len([x for x in x.split() if x.isdigit()]))df[['Text','numerics']].head()

5.大写单词的数量:愤怒、愤怒等情绪经常通过大写单词来表达,这使得这成为识别这些单词的必要操作。在数据清理过程中,所有字母将被转换成小写。

df['upper'] = df['Text'].apply(lambda x: len([x for x in x.split() if x.isupper()]))df[['Text','upper']].head()

现在,我们完成了只能在数据清理之前获得的特征。我们准备清除数据。

文字清理技巧

在对数据应用 NLP 技术之前,首先需要清理数据并为分析准备数据。如果这个过程做得不正确,它可能会完全破坏分析部分。以下是应用于数据的步骤:

  1. 将所有文本转换成小写:第一个预处理步骤是将评论转换成小写。这避免了相同单词的多个副本。例如,在计算字数时,如果我们忽略这种转换,则“狗”和“狗”将被视为不同的单词。
df['Text'] = df['Text'].apply(lambda x: " ".join(x.lower() for x in x.split()))df['Text'].head()

2) 目前,NLP 方法还没有一个有意义的方法来分析标点符号。因此,它们被从文本数据中删除。通过这一步,这些字符被删除:[!" #$% & '()*+,-。/:;= >?@[]^_`{|}~]

df['Text'] = df['Text'].apply(lambda x: " ".join(x.lower() for x in df['Text'] = df['Text'].str.replace('[^\w\s]','')
df['Text'].head()

3) 停用词的移除:通过这一步,我移除了 nltk 包中所有默认的英文停用词。

from nltk.corpus import stopwords
stop = stopwords.words('english')df['Text'] = df['Text'].apply(lambda x: " ".join(x for x in x.split() if x not in stop))df['Text'].sample(10)

添加自己的停用词 :此时,你可能想添加自己的停用词。我这样做主要是在检查了最常用的单词之后。我们可以这样检查最常用的单词:

import pandas as pd
freq = pd.Series(' '.join(df['Text']).split()).value_counts()[:20]
freq

最常见的 20 个单词

从这几个词中,我想去掉' br ',' get ',' also ',因为它们没有太大意义。让我们将它们添加到停用词列表中:

# Adding common words from our document to stop_wordsadd_words = ["br", "get", "also"]
stop_words = set(stopwords.words("english"))
stop_added = stop_words.union(add_words)df['Text'] = df['Text'].apply(lambda x: " ".join(x for x in x.split() if x not in stop_added))df['Text'].sample(10)

注意:在其他指南中,您可能会遇到 TF-IDF 方法。TF-IDF 是从文本数据中去除没有语义价值的单词的另一种方法。如果你用的是 TF-IDF,就不需要应用停用词(但是两个都应用也无妨)。

4) 移除 URL:URL 是被移除的数据中的另一个噪音。

def remove_url(text): 
    url = re.compile(r'https?://\S+|www\.\S+')
    return url.sub(r'', text)# remove all urls from df
import re
import string
df['Text'] = df['Text'].apply(lambda x: remove_url(x))

5) 去除 html HTML 标签: HTML 在互联网上被广泛使用。但是 HTML 标签本身在处理文本时并没有什么帮助。因此,所有以 url 开头的文本都将被删除。

def remove_html(text):
    html=re.compile(r'<.*?>')
    return html.sub(r'',text)# remove all html tags from df
df['Text'] = df['Text'].apply(lambda x: remove_html(x))

6) 删除表情符号:表情符号可以是与客户满意度相关的一些情绪的指示器。不幸的是,我们需要在我们的文本分析中删除表情符号,因为目前还不能用 NLP 分析表情符号。

# Reference : https://gist.github.com/slowkow/7a7f61f495e3dbb7e3d767f97bd7304bdef remove_emoji(text): 
    emoji_pattern = re.compile("["
        u"\U0001F600-\U0001F64F"  # emoticons
        u"\U0001F300-\U0001F5FF"  # symbols & pictographs
        u"\U0001F680-\U0001F6FF"  # transport & map symbols
        u"\U0001F1E0-\U0001F1FF"  # flags
        u"\U00002702-\U000027B0"
        u"\U000024C2-\U0001F251"
        "]+", flags=re.UNICODE)
    return emoji_pattern.sub(r'', text)#Example
remove_emoji("Omg another Earthquake 😔😔")

# remove all emojis from df
df['Text'] = df['Text'].apply(lambda x: remove_emoji(x))

7) 移除表情符号:表情符号和表情符号有什么区别?

:-)是表情符号

😜是一个→表情符号。

!pip install emot #This may be required for the Colab notebookfrom emot.emo_unicode import UNICODE_EMO, EMOTICONS# Function for removing emoticons
def remove_emoticons(text):
    emoticon_pattern = re.compile(u'(' + u'|'.join(k for k in   EMOTICONS) + u')')
    return emoticon_pattern.sub(r'', text)#Example
remove_emoticons("Hello :-)")

df['Text'] = df['Text'].apply(lambda x: remove_emoticons(x))

8) 拼写纠正:亚马逊评论上,拼写错误多如牛毛。产品评论有时充满了匆忙发送的评论,有时几乎无法辨认。

在这方面,拼写纠正是一个有用的预处理步骤,因为这也将有助于我们减少单词的多个副本。例如,“分析”和“分析”将被视为不同的词,即使它们在同一意义上使用。

from textblob import TextBlob
df['Text'][:5].apply(lambda x: str(TextBlob(x).correct()))

9.词条释义: 词条释义是将一个单词转换成其基本形式的过程。词汇化考虑上下文,将单词转换成有意义的基本形式。例如:

“关怀”->“词化”->“关怀”

Python NLTK 提供了 WordNet 词条整理器,它使用 WordNet 数据库来查找单词的词条。

import nltk
from nltk.stem import WordNetLemmatizer 

# Init the Wordnet Lemmatizer
lemmatizer = WordNetLemmatizer()df['Text'] = df['Text'].apply(lambda x: lemmatizer(x))

关于词汇化的更详细的背景,可以查看 Datacamp 。

在这里,我将停止清理数据。但是,作为一名研究人员,您可能需要根据您的数据进行更多的文本清理。例如,您可能希望使用:

⚫对文本数据进行词干分析

⚫拼写纠正的替代方法:孤立词纠正和上下文相关纠正方法

⚫不同的包使用不同数量的停用词。你可以试试其他的 NLP 包。

特征提取-第二轮

一些特征将在文本清理后提取,因为它们在此步骤获得更有意义。例如,如果我们在数据清理之前提取这个特征,字符的数量会受到 URL 链接的严重影响。此时,我们必须尝试提取尽可能多的特征,因为额外的特征有机会在文本分析期间提供有用的信息。我们不必担心这些功能将来是否真的有用。在最坏的情况下,我们不使用它们。

  1. 字数:此功能告知评论中有多少字
df['word_count'] = df['Text'].apply(lambda x: len(str(x).split(" ")))df[['Text','word_count']].head()

2.字数:评论中包含多少个字母。

df['char_count'] = df['Text'].str.len() ## this also includes spacesdf[['Text','char_count']].head()

3.平均单词长度:评论中单词的平均字母数。

def avg_word(sentence):
    words = sentence.split()
    return (sum(len(word) for word in words)/(len(words)+0.000001))df['avg_word'] = df['Text'].apply(lambda x: avg_word(x)).round(1)
df[['Text','avg_word']].head()

让我们检查提取的要素在数据框中的样子:

df.sample(5)

结论

这项研究解释了文本清洗的步骤。此外,本指南的独特之处在于,在文本清理之前和文本清理之后,通过两轮 : 来完成特征提取。我们需要记住,对于实际的研究来说,文本清理是一个递归过程。一旦我们发现异常,我们会回来通过解决异常进行更多的清理。

*特别感谢我的朋友塔比瑟·斯蒂克尔校对了这篇文章。

使用 Streamlit 制作交互式鸢尾花分类应用程序的初学者指南

原文:https://towardsdatascience.com/beginners-guide-lets-make-an-interactive-iris-flower-classification-app-using-streamlit-42e1026d2167?source=collection_archive---------23-----------------------

使用 Streamlit 的虹膜分类应用程序

学习使用 Streamlit 制作互动、美观的机器学习应用程序:)

您将学到的内容:

  1. 关于 Streamlit 的简介
  2. 安装程序
  3. 使用 Streamlit 的基本示例
  4. 如何保存机器学习模型?
  5. 鸢尾花分类 app
  6. 分步代码讲解+视频演示:)

大家好:)

最近,我在当地社区参加了一个关于Streamlit的网络研讨会,我想,让我们制作一个关于它的教程,并与开源社区分享:)

作为一个初学者,我相信我们都希望尽快使用机器学习来制作很酷的东西!

Streamlit 的开发者为我们创造了一个非常简单的方法:)

在浪费时间之前,让我们开始吧。

照片由 Streamlit 拍摄

什么是 Streamlit?

Streamlit 是一个开源框架,用于创建一个交互式的、漂亮的可视化应用程序。全部用 python!

Streamlit 提供了许多有用的特性,对数据驱动项目的可视化非常有帮助。

为什么我应该使用 Streamlit?

  • 创建交互式用户界面的简单易行的方法
  • 不需要开发经验
  • 在数据驱动的项目中使用不同的功能很有趣:)
  • 全面的文档

使用 Streamlit 的 Face-GAN explorer

这个 Streamlit 应用程序使用关的 TL-GAN[6]演示了 NVIDIA 名人脸 GAN[5]模型。

安装程序

针对 Linux 的

你只需要在你的终端写下下面的命令来安装 Streamlit

pip install streamlit

仅此而已:)

对于 Windows

您可以找到 windows 的安装说明:

为 windows 安装 streamlit

现在让我们探索 Streamlit

绘图内容

在下面几行代码中键入,并将其另存为。py 扩展

**import** **streamlit** **as** **st** 
x = 4
st.write(x, 'squared is', x * x)

以下是使用 Streamlit 运行 python 脚本的方式:

打开一个终端,并确保你是在同一个工作目录下保存文件。

键入以下命令,然后按 enter 键:

streamlit run filename.py

输出:

这是您将在默认 web 浏览器中看到的内容

好了,现在让我们通过在代码中包含 slider 小部件来增加它的交互性:

x = st.slider('x')  # 👈 this is a widget
#st.write(x, 'squared is', x * x)

输出:

在 Streamlit 中使用 Slider Widget

****注意:每当你修改代码的时候,你就可以在你的项目中看到的快速变化

好了,现在让我们回到我们的主要目标!

图片由 Pixabay 上的汉斯本拍摄

虹膜分类应用程序

问题陈述:根据鸢尾花的特征对其进行分类。

虹膜特征:萼片,花瓣,长度和宽度

这个分类问题也被称为监督机器学习的 Hello World

首先,让我们探索虹膜数据集:

from sklearn.datasets import load_irisiris= load_iris()# Store features matrix in X
X= iris.data#Store target vector in 
y= iris.target

功能

# Names of features/columns in iris dataset
print(iris.feature_names)Output : ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

目标/虹膜种类

# Names of target/output in iris dataset
print(iris.target_names)Output : ['setosa' 'versicolor' 'virginica']

鸢尾花的种类

虹膜数据集的尺寸/大小

# size of feature matrix
print(iris.data.shape)Output: (150, 4)# size of target vector
print(iris.target.shape)Output : (150,)

因此,我们有 150 行/观察值和 4 列/特征。

下一步是研究机器学习算法:)

作为开始,我们将使用 K 最近邻。

KNN 就像是:

告诉我谁是你的朋友,我会告诉你你是什么人

照片由 CC BY-SA 3.0 授权的agor 153拍摄

以下是 KNN 的步骤:

给出新数据:

  1. 计算新数据和数据集中每个观察值/行之间的距离
  2. 获得与新数据最接近的 k 个观察值****

最近:最小距离的观测值(升序)

3.获取 k 个观察值的输出标签,并基于这些最具代表性/最流行的输出标签对个新数据进行分类

让我们使用 Scikit 学习库来应用 KNN 吧!

以下是使用 scikit learn 应用机器学习模型的 4 个基本步骤:

****第一步:导入机器学习模型

#Import the classifier
from sklearn.neighbors import KNeighborsClassifier

****第二步:实例化模型

knn = KNeighborsClassifier()

****第三步:用数据拟合模型

knn.fit(X, y)Output : KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=None, n_neighbors=5, p=2,weights='uniform')

在这里,我们可以看到 KNN 分类器中许多不同类型的参数,但我们将使用 n_neighbors:)

****第四步:预测

#Predicting output of new data
knn.predict([[3.2, 5.4, 4.1, 2.5]])// Random valuesOutput : array([1]) # 1 -> versicolor (Iris flower specie)

让我们改变 K 值并探究结果

对于 K = 1

# instantiate the model 
knn = KNeighborsClassifier(n_neighbors=1)# fit the model with dataknn.fit(X, y)# predict the response for new observationsknn.predict([[3, 5, 4, 2]])Output : array([2]) 2 -> virginica (Iris flower specie)

对于 K = 5

# instantiate the model 
knn = KNeighborsClassifier(n_neighbors=5)# fit the model with dataknn.fit(X, y)# predict the response for new observationsknn.predict([[3, 5, 4, 2]])Output : array([1]) // 1 -> versicolor (Iris flower specie)

当 k = 1 时,KNN 预言了维吉尼亚和 k = 5 时,KNN 预言了云芝。****

这就产生了一个问题:

如何估计 我的模型 在样本外数据上的可能表现?

答案在于评估程序!

首先,我们将使用培训/测试分割评估方法:

训练/测试分割

  • 将数据集分成两块****训练集测试集****
  • 训练设备上安装/训练模型
  • 测试装置上测试模型

注:思路是在训练集上训练/拟合模型,在没有训练模型的测试集上评估!

**#  split X and y into training and testing sets
from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=4)**

使用 train_test_split 我们可以实现这一点,在这里您可以看到一些参数。

x:数据集/特征矩阵

y:鸢尾物种标签/输出向量

test_size:你想给测试集多少比例的数据集这里 0.4 表示 40%给测试集,可能 60%给训练集

random_state:这里传递一个固定的值意味着每当你多次运行代码时,它将把相同的数据索引分成训练集和测试集。

**# print the shapes of the new X objects
print(X_train.shape)
print(X_test.shape)Output : 
(90, 4)
(60, 4)# print the shapes of the new y objects
print(y_train.shape)
print(y_test.shape)Output :
(90,)
(60,)**

我们得到了(60%)训练集的 90 个观察值和(40%)测试集的 40 个观察值。

如果你想知道我们为什么使用培训/测试分割,请查看下面的文章

**** [## 如何评价和改进 Knn 分类器第 3 部分

初学者指南,学习在 knn 分类器中评估和选择最佳参数

medium.com](https://medium.com/@jalalmansoori/how-to-evaluate-and-improve-knn-classifier-part-3-62d72fd17eec)

让我们开始使用训练/测试分割来查看模型性能。

对于 K=1

knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print(metrics.accuracy_score(y_test, y_pred))Output:
0.95

对于 K=5

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
y_pred = knn.predict(X_test)
print(metrics.accuracy_score(y_test, y_pred))Output:
0.9666666666666667

因此,对于 k=1,我们得到(95%的测试精度),对于 k=5,我们得到(大约 97%的测试精度)。

注: 检验精度最好是对样本外数据进行估计。

有趣的部分来了,我们能进一步提高测试精度吗?

图米苏在 Pixabay 上的照片

如何选择 knn 分类器中的最佳参数?

如上所述,我们将使用 n _ neighbour 参数:)

我们来玩吧:

# try K=1 through K=30 and record testing accuracy
k_range = list(range(1, 31))
scores = []
for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
    scores.append(metrics.accuracy_score(y_test, y_pred))

在上面的代码中,我们实现了一种非常直观的方法,即为了提高测试精度,我们可以针对特定范围的 K 值运行 knn 分类器,并将测试精度结果存储在一个列表中,然后最终获得测试精度最高的 K 值。

下面是 matplotlib 库制作的可视化绘图

# import Matplotlib (scientific plotting library)
import matplotlib.pyplot as plt# allow plots to appear within the notebook
%matplotlib inline# plot the relationship between K and testing accuracy
plt.plot(k_range, scores)
plt.xlabel('Value of K for KNN')
plt.ylabel('Testing Accuracy')

K 值与测试精度的关系图

在这个图中,我们可以看到测试精度在(10–15)K 值之间相当好,所以让我们只选择 K=12 来完成 knn 分类器。

让我们完成并保存 Knn 分类器。

如何最终确定 Knn 分类器对新数据进行预测?

这就是机器学习大师的创始人杰森·布朗利所说的:

在进行预测之前,必须训练一个最终模型。

您可能已经使用 k-fold 交叉验证或数据的训练/测试拆分来训练模型。这样做是为了让您对模型在样本外数据(如新数据)上的技巧有一个估计。

这些模型已经达到了它们的目的,现在可以丢弃了。

现在,您必须根据所有可用数据训练最终模型。

如何保存机器学习模型?

from sklearn.datasets import load_irisiris= load_iris()# Store features matrix in X
X= iris.data#Store target vector in yy= iris.target# Finalizing KNN Classifier after evaluation and choosing best 
# parameter#Importing KNN Classifier
from sklearn.neighbors import KNeighborsClassifier# instantiate the model with the best known parameters
knn = KNeighborsClassifier(n_neighbors=12)# train the model with X and y (not X_train and y_train)
knn_clf=knn.fit(X, y)# Saving knn_clfimport joblib# Save the model as a pickle in a file
joblib.dump(knn_clf, "Knn_Classifier.pkl")

因此,使用 joblib 我们保存了最终的训练模型,现在我们可以在我们的虹膜分类应用程序中使用它:)

使用 streamlit 的最终版本虹膜分类应用程序

这是我们要做的:

使用 Streamlit 的鸢尾花卉种类分类应用程序

第一步

import streamlit as st
import pandas as pd
import joblib
from PIL import Image#Loading Our final trained Knn model 
model= open("Knn_Classifier.pkl", "rb")
knn_clf=joblib.load(model)st.title("Iris flower species Classification App")#Loading imagessetosa= Image.open('setosa.png')
versicolor= Image.open('versicolor.png')
virginica = Image.open('virginica.png')

在上面的代码中:

  • 我们导入了一些有用的库
  • 加载我们的 Knn 分类器和虹膜花图像

注意:你可以访问本教程中使用的所有代码和下面源代码标题下的 Iris 图片!

第二步

st.sidebar.title("Features")#Intializing
parameter_list=['Sepal length (cm)','Sepal Width (cm)','Petal length (cm)','Petal Width (cm)']
parameter_input_values=[]
parameter_default_values=['5.2','3.2','4.2','1.2']values=[]

在上面的代码中,我们用随机值初始化了鸢尾花的特征,如萼片、花瓣、长度等

显示特征

#Display
for parameter, parameter_df in zip(parameter_list, parameter_default_values):

 values= st.sidebar.slider(label=parameter, key=parameter,value=float(parameter_df), min_value=0.0, max_value=8.0, step=0.1)
 parameter_input_values.append(values)

input_variables=pd.DataFrame([parameter_input_values],columns=parameter_list,dtype=float)
st.write('\n\n')

在 streamlit slider 小部件中显示 Iris Flower 特征的代码

这里我们使用了 for 循环来高效地显示鸢尾花的特征!

第三步

if st.button("Click Here to Classify"):
 prediction = knn_clf.predict(input_variables)st.image(setosa) if prediction == 0 else st.image(versicolor)  if prediction == 1 else st.image(virginica)

如果满足 3 个条件中的任何一个,则显示图像

最后,与其写文字,不如展示一张鸢尾花物种的图片:)

最后,在您的终端中键入以下命令

streamlit run iris_app.py

恭喜你用 streamlit 制作了 hello world 的机器学习 app:)

由拍摄的照片在 Pixabay 上

视频演示

使用 streamlit 演示的虹膜分类应用程序

源代码:

你可以找到所有的代码+模型+虹膜图像在这里

非常感谢您抽出时间

学习、创造、分享和重复,不要忘记学习是有趣的!

结论

在本教程中,您使用 streamlit 制作了第一个机器学习应用程序。祝你未来的项目好运:)

接触

Gmail-> jalalmansoori19@gmail.com

github->https://github.com/jalalmansoori19

参考

  1. https://www.coursera.org/learn/machine-learning
  2. https://www.streamlit.io/
  3. 使用 scikit-learn 在 Python 中进行机器学习— YouTube
  4. https://github.com/justmarkham/scikit-learn-videos
  5. T.Karras、T. Aila、S. Laine 和 J. Lehtinen,为提高质量、稳定性和变化而逐步种植甘蔗 (2018),ICLR。**
  6. 南关,【使用新型 TL-GAN 模型控制图像合成和编辑】 (2018),洞察数据科学博客。

图像分类初学者指南:VGG-19、Resnet 50 和带 TensorFlow 的 InceptionResnet

原文:https://towardsdatascience.com/beginners-guide-on-image-classification-vgg-19-resnet-50-and-inceptionresnetv2-with-tensorflow-4909c6478941?source=collection_archive---------20-----------------------

本文用迁移学习示例说明了一个图像分类任务,对 120 个狗品种的 20,000 多张照片进行了分类。

柯基和它的朋友。信用:阿尔万需要

我还记得我第一次听说深度学习以及听到这个术语时的激动,认为它是一个神秘的黑盒子和全能的模型。

对于初学者来说,图像分类是一项简单而又有意义的任务,可以帮助他们了解深度学习,并习惯它的符号和概念。在这个项目中,我选择使用迁移学习,这是深度学习领域中最简单的方法。

这个项目使用的代码可以在我的 GitHub 库中找到。

#数据

本项目使用的数据可在 Kaggle 获得,也可在斯坦福找到。你可以在提供的第二个链接中找到它的原始论文和基线结果。

所有 120 个品种的标签分布

该数据集由 120 种狗的 20 多万张照片组成。我们的目标类别是什么?它们在 120 个品种中分布均匀吗?左图显示,类别相当平衡,一些类别的图片略多,而大多数类别至少有 150 张照片。

我们还想看看数据集中的一些随机照片。

从数据集中随机选取狗的照片及其品种

我们观察到,尽管品种不同,有些狗有相似的特征。例如,第一排的梗看起来和我很像。我想知道这对于计算机来说是不是太难了。

#数据预处理

对于图像处理主题来说,数据预处理是一个很深的主题,但我们在这里不会深入探讨。该项目使用迁移学习模型的标准预处理,结合一些数据扩充,如旋转、水平翻转、放大等。

#转移学习

在深入研究项目所用的模型之前,我们想先谈谈迁移学习。简单地说,迁移学习就是利用他人预先训练好的模型来完成你的任务,它可以是不同的任务,但应该是相关的。文献已经证明,深度学习模型在一定程度上是可以移植的。

我探索了两种迁移学习的方法:简单地使用预训练的模型作为特征提取或重新训练(微调)模型的一部分。你们中的一些人可能会接触到第一种方法而没有意识到。比如在 NLP 任务中用 Word2Vec 做编码器,其实就是用迁移学习做特征提取的一种方式。通过保持模型的原始重量,可以容易且直接地应用它。相反,微调方法需要一些试错实验。如果任务非常不同,您可以考虑对模型进行至少 50%或更多的微调。如果您的任务非常相似,比方说最初模型用于对汽车进行分类,现在您希望对卡车进行分类,您可以考虑微调最后几层或原始模型的 30%。所需的微调量需要花费时间和精力,这取决于任务的性质。

对于计算机视觉任务,有许多已建立的模型,对于这个项目,我们用我们的例子回顾了其中的三个。

  • VGG-19

VGG-19 是我们探索的第一个型号,也是我们审查的型号中最老的一个。VGG-19 是 VGG-16 的改进型。它是一个 19 层的卷积神经网络模型。它是通过将卷积堆叠在一起而构建的,但是由于一个称为梯度递减的问题,该模型的深度受到限制。这个问题使得深度卷积网络难以训练。该模型在 ImageNet 上进行训练,用于对 1000 种类型的对象进行分类,其余被审查的模型也是如此。

我们探索了 VGG-19 的特征提取和微调。我们得到的最好结果是简单地使用 VGG-19 作为特征提取。在我们情况下,微调和重新训练对 VGG-19 并不奏效。

  • Resnet50

Resnet 模型是为解决梯度递减问题而提出的。其思想是跳过连接,将残差传递给下一层,这样模型就可以继续训练。有了 Resnet 模型,CNN 模型可以越来越深入。

Resnet 模型有许多变体,我们在这里选择 Resnet50 是因为它在 Kaggle 的教程中使用过,并且为我们所熟悉。通过 Resnet 50 获得的最佳结果是重新训练所有参数的近 40%。

  • InceptionResnetV2

InceptionResnet 是对 Resnet 的进一步改进,结合了称为 Inception 的技术。点击此处阅读更多关于该车型的信息。

我还做了一个简单的例子来比较这三种不同的架构。彩色块代表模型的层。

视觉模型比较

人们会注意到,在这三个模型中,我们对其中的两个进行了微调和重新培训。当我们试图重新训练 30%的模型时,VGG-19 表现很差。原因可能是 VGG-19 作为深度学习网络相对“肤浅”。用少量数据输入一次重新训练太多参数会损害模型性能,因为模型没有足够的输入来学习。

#结果和讨论

我们的最佳模型实现的性能—验证数据

作为一个基准,你可以在这里阅读关于预训练的模特表演。左边的表格显示了我们的模型在看不见的数据上实现的性能。我们可以看到,模型可以保留基准性能。对于那些我们已经重新训练和微调的,它比基线表现得更好,这并不奇怪,因为我们的任务在本质上比原来的任务更简单(类别更少)。

我还想分享一些训练模型时的诊断图。

Resnet 损失 50

显示的损耗图来自 Resnet50 型号。我们观察到,在这里验证损失总是低于训练损失。它显示出惊人的概括预测的能力,这是迁移学习模型中一个非常独特的现象。这是由于模型中预先存储的知识。然而,这也表明该模型不能提高列车组的性能,因此很难进一步调整该模型。这是我开始考虑新模型而不是坚持 Resnet50 架构的地方。

来自 InceptionResnetV2 的损失

显示的第二个损失图使用来自我们的 InceptionResnet 模型的数据,在 20 个时期后进行训练。与培训损失相比,验证损失开始时较低。这是与上面的模型类似的行为。这里的验证损失相对稳定,培训损失继续下降。这表明我们在训练集中的改进倾向于过度拟合,不能推广到看不见的数据。为了进一步改进,我们可以探索在模型上添加更多的正则化。

真相:真实的品种;我的模型给出的三个预测

让我们来看看预测。我们的模型在第一次猜测时基本上是正确的,如果我们考虑前 2 个预测,它实际上是所有正确的分类。考虑到任务的难度,我认为这是相当不错的表现。

然而,当我们深入研究该模型造成的更多错误时,仍然有很大的改进空间,我们希望迅速讨论进一步改进的方法。

真相:真实的品种;我的模型给出的三个预测

作为分类模型,我们的模型缺乏辨别狗的大小的能力,例如,它是小型、中型还是大型狗。这是非常重要的,当试图了解狗的品种,因为有许多狗有相似的面部特征和体型,但只有大小不同。下图显示模型很难区分梗类。为了使我们的模型学习对象大小,人们可能想要实现对象识别模型,而不是简单的分类。

蓝黑还是白金?

最重要的是,该模型在正确识别颜色方面也存在问题。这就像一件蓝黑色的衣服在不同的环境光照下改变颜色的经典例子(如下所示)。因此,我们可能要考虑在预处理步骤中增加颜色失真增强,例如,随机化亮度、对比度、饱和度等。

最后,我们还观察到,模型与狗的细微差异,即不同的皮毛长度作斗争。模型可能需要更好的分辨率输入来更好地学习细节。如果我们能够获得更多的数据输入,这将有助于提高模型的性能。

#结尾

这是我们在 CNN 的第一个使用迁移学习的项目。接下来我会写关于使用 CNN 模型来预测图像掩蔽。

敬请关注,在家注意安全!😃

使用 Dash、Plotly 和 Bootstrap 构建多页面应用程序的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-building-a-multi-page-dashboard-using-dash-5d06dbfc7599?source=collection_archive---------2-----------------------

我从一个完全初学者的角度,一步一步地介绍了使用新冠肺炎数据构建多页仪表板的过程。

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

当你因为你的国家处于部分封锁状态而整天被困在家里,并且你意识到你已经看不到节目和玩不到游戏的时候,你会做什么?没错,您从事的是像这样的热门项目,在这里您可以自学如何使用开源库构建仪表板。当然,我是开玩笑的,我很确定有很多事情比试图构建一个仪表板更有趣,也更少令人沮丧,但是如果你和我一样,这篇文章记录了我所学到的一切,希望可以作为任何想尝试使用 Python 构建仪表板的人的良好指南。

你可以在这里访问仪表板(只需给它大约 30 秒的加载时间),所有用于构建仪表板的文件都可以在 GitHub 上找到。

该应用使用了两个数据集,全球页面使用来自欧盟开放数据门户的新冠肺炎数据,新加坡页面使用该数据集。我稍微清理了一下这两个数据集,最终的数据文件是上传到我的 GitHub 存储库中的。

3 周(老实说,我都不记得花了多长时间)的血汗钱和眼泪的最终结果。但是,哇,最终产品肯定是非常令人满意的。

只是让你了解一下我的背景,在此之前,我从未使用过 Dash 或 Plotly,也不了解 HTML 和 CSS。我有使用 Pandas 的经验,但除此之外,我认为很明显,在使用 Python 进行 web 开发方面,我还是个初学者。听起来很难,对吧?但是,还是接受了# challengeaccepted

Dash 到底是什么?

Dash 是一个开源库,它有助于使用 Python 构建交互式 web 应用程序。它包含 Plotly,可用于可视化数据。换句话说,不需要任何 JavaScript 知识,你所需要的只是 Python,这使得事情变得容易得多,也更加用户友好。顺便说一下, Dash 文档和用户指南是一个很好的学习起点。

你可以使用 Bootstrap 来设计你的 Dash 应用,这是一个用于 web 开发的开源 CSS 框架。这意味着您的应用程序可能非常美观,而不必经历从头构建 CSS 样式表的麻烦。

让我们从小处着手——构建一个单页应用程序

直接进入多页面应用程序的想法听起来很复杂,令人望而生畏,所以让我们从构建组件开始,并将它们放入单页面应用程序中。我将以该应用的新加坡页面为例。

1.安装集成开发环境(IDE)

我以前只在数据分析项目中使用 Python,在这些项目中我总是求助于 Jupyter Notebook。对于 web 开发,您需要安装一个 IDE(或者从终端运行所有东西,老实说这不是一个好主意),在那里您可以编写和运行您的脚本。我最终选择了 PyCharm ,并从这个视频中学会了如何设置。

这不是必须的,但是有人告诉我,为你的项目创建一个虚拟环境是一个好习惯,这样你就可以将所有的依赖项从主环境中分离出来。请注意,您必须在虚拟环境中安装所有需要的依赖项,即使您之前已经在主环境中安装了它们。

一般来说,你需要的包括:dash,plotly,pandas,dash-bootstrap-components(如果你使用 bootstrap 进行造型)。

2.了解仪表板特征

我想快速浏览一下 Dash 的三个特性。

布局

布局告诉 Dash 你希望你的页面是什么样子。我将使用我的新加坡页面代码中的一个例子来解释这些事情。

这是我的新加坡. py 文件,可以在应用程序文件夹中找到

这段代码表明我的页面结构如下。

第 1 行:文本行,“新加坡新冠肺炎一瞥”

第 2 行:文本行,“显示新加坡新冠肺炎疫情不同阶段的趋势”

第 3 行:另一行文本,“最新更新”

第 4 行:单选按钮,让用户在选项“压缩表”和“全表”之间进行选择

第 5 行:一个数据表

你在代码片段中看到的其他东西都是样式元素,比如字体、颜色和间距。最终产品看起来像这样:

这不太难吧?太好了,让我们进入下一个专题!

组件

组件是让你的应用程序具有交互性的东西。实际上,我在上一节提到过一个:单选按钮。我的单选按钮根据用户的偏好决定是显示精简的数据表(列数较少)还是完整的数据表(列数较多)。你可以在这里找到仪表板组件的完整列表。

回调

简单地说,回调赋予组件生命。回到单选按钮的例子,我必须编写一个回调函数,以便 Dash 知道是显示更少的列(精简表)还是更多的列(完整表)。

这个片段也来自我的 Singapore.py 文件,可以在 apps 文件夹中找到

这个回调更新两个输出:我的数据表的数据和列,这取决于来自用户选择的单选按钮的输入。

Dash 回调中一个更有趣的特性是,您可以在一个图形中使用 hoverData (鼠标悬停的数据点)作为另一个图形的输入。

这是来自应用程序的新加坡页面

在这种情况下,我使用鼠标悬停在新加坡的新冠肺炎病例作为下两个条形图的输入,这两个条形图显示了本地和输入病例的细分,以及它们是否是来自外籍工人宿舍的病例。

3.设计 Dash 应用程序

当涉及到 Dash 应用程序的样式时,有几个选项。你可以使用外部样式表,如这个或者点击 Bootstrap。使用 Bootstrap 的一个好处是,他们有一个内置的导航栏功能,你可以使用!或者,您也可以构建自己的样式表(或者修改一个外部样式表)。你所要做的就是创建一个名为“assets”的文件夹,并将你的 CSS 文件保存到该文件夹中。哦,是的,如果你打算在你的应用程序中包含图片,也把它们保存到资产文件夹中。

4.组装单页应用程序

有了它,我们就可以组装一个单页应用程序,并在本地运行它,以确保一切正常运行。请注意,这里的代码与您在 singapore.py 文件中看到的略有不同,因为这是针对单页应用程序的。新加坡. py 文件中注释掉了这些差异。

我想指出的是,出于某种原因,我必须在代码的最后一行插入 host='127.0.0.1 ',以便让代码运行。否则,我最终只会得到一条错误消息(我花了几个小时搜索解决方案,但最终没有找到一个对我有用的)。

升级到多页面应用程序

既然我们已经完成了构建单页应用程序的基础工作,我们可以开始研究多页应用程序了——毕竟,多页应用程序只是一个包含多个单页应用程序的应用程序,但是有一些额外的调整。我想包括的附加页面是应用程序的全球页面和主页。有两种方法来构建多页面应用,我将采用将每个页面保存为单独文件的方法。

下面提供了我的可以在本地运行的多页应用程序的结构概述。在下一部分,我将介绍如何部署多页面应用程序。

让我们现在浏览一些文件。

1.应用程序文件夹

这是一个文件夹,您可以在其中包含应用程序每个页面的单独文件。请注意,如果您之前将文件作为单页应用程序运行,您将需要进行一些更改,否则您将会遇到一系列错误。我已经注释掉了每个文件中需要更改的部分。

您还需要创建一个名为 init 的空文件。py 在这个文件夹里。

2.app.py 文件

app.py 文件应该如下所示:

3.index.py 文件

最重要的文件之一,因为这是链接所有单个页面的文件!我还在这个文件中为我的应用程序添加了一个导航栏,这样就可以很容易地在页面间导航。

请注意,上面的代码与我的存储库中的代码略有不同,因为此时我们仍在本地测试我们的应用程序。

在 Heroku 上部署多页面应用程序

现在,我们已经成功地构建了一个在本地运行良好的多页面应用程序,让我们尝试将其部署到网上,以便与他人共享!我会用 Heroku。

我很大程度上遵循了由 Dash 和这个视频提供的说明,但是做了一些改变,因为我之前已经为我的项目创建了一个文件夹和一个虚拟环境。这些是我采取的步骤,但是请注意,如果您之前没有为您的项目创建文件夹或虚拟环境,那么您的情况会有所不同。

1.创建一个 Heroku 帐户

前往 Heroku ,创建一个免费帐户,并确保通过点击他们将发送到您电子邮件的链接来激活您的帐户。

2.在 PyCharm 中打开您的项目,并单击 Terminal 选项卡

我们首先需要初始化一个空的 git 存储库,然后我们需要再安装一个依赖项 gunicorn,以便部署我们的应用程序。

3.添加一个. gitignore 文件、Procfile 和 requirements.txt 文件

的。gitignore 文件应该如下所示

Procfile 应该如下所示

注意,index 指的是文件 index.py,server 指的是该文件中的变量 server。这就引出了我的下一个观点,您必须在 index.py 文件中添加以下代码行,以便在 Heroku 上成功部署应用程序。

requirements.txt 文件给出了您的应用程序需要的依赖项列表。它可以使用下面的代码自动创建。

4.安装 Heroku 命令行界面

如果您使用的是 Mac,您可以通过在“终端”中键入以下内容来使用 Homebrew 安装它(但要确保之前已经安装了 home brew ): brew tap heroku/brew & & brew install heroku

如果没有,你可以越过这里的来安装它。

5.部署到 Heroku

你完了!您可以在https://dash-app.herokuapp.com查看您的应用,其中 dash-app 是您为应用选择的名称。

简单说明一下,如果你想在 Heroku 默认的 Python 3.6 上运行你的应用程序,你可以删除 runtime.txt 文件。

6.更新你的应用

只要在 PyCharm 终端(您打开项目的地方)中输入上述代码,就可以对您的应用程序进行任何更改,无论是更新数据还是更改应用程序中的功能。

这标志着我第一次尝试用 Dash 构建仪表板的结束,这绝对是一次让我学到很多东西的旅程。希望这篇文章对对此感兴趣但不知从何下手的人有所帮助。

免责声明:我没有任何网页开发的背景,所以非常欢迎所有的建议和评论!

建造新加坡式人工智能聊天机器人的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-building-a-singlish-ai-chatbot-7ecff8255ee?source=collection_archive---------29-----------------------

人工智能文本生成是 NLP 中最令人兴奋的领域之一,但对初学者来说也是一个令人望而生畏的领域。这篇文章旨在通过将几个现有教程合并和改编为一个实用的端到端演练,并为一个可在交互式应用程序中使用的对话聊天机器人提供笔记本和样本数据,来加快新手的学习过程。

对于非新加坡人来说,“模糊如一个 sotong”这样的新加坡式英语短语可能会令人困惑。变形金刚模型能理解吗?照片:蔡展汉

自动文本生成无疑是近年来自然语言处理中最令人兴奋的领域之一。但由于对技术知识和资源的高要求,这也是一个对新来者来说相对困难的领域。

虽然市面上并不缺少有用的笔记本和教程,但是将各种线索整合在一起可能会很耗时。为了帮助新来者加快学习过程,我已经整合了一个简单的端到端项目来创建一个简单的人工智能对话聊天机器人,你可以在一个交互式应用程序中运行。

我选择围绕聊天机器人来构建文本生成项目,因为我们对对话的反应更直观,并且可以很容易地判断自动生成的文本是否有任何好处。聊天机器人也无处不在,我们大多数人都可以很好地了解预期的基线性能,而不必咨询手册或专家。如果是坏的,你会马上知道,而不必检查分数或指标。

项目中的工作流是根据初学者的实际问题构建的:如何开始数据提取和准备,需要什么来微调预训练的 transformer 模型,以及如何在应用程序中测试/使用机器人。

正如下面一个测试运行的截图所示,最终产品并不是人们所说的“完美的”。但是作为第一个实验,结果已经足够好了(在我看来),凸显了通过迁移学习生成人工智能文本的可能性和局限性。

新加坡式聊天机器人在 Colab 上的测试截图。

数据、回购和要求

如果上面的对话样本让你感到困惑,那么,你可能没有去过新加坡,或者听说过“新加坡式英语”,或者新加坡口语。这是几种语言和当地俚语的大杂烩,可能会让非新加坡人感到困惑。换句话说,这是测试 DialoGPT 模型局限性的一个不错的方法。

用于微调模型的数据来自当地一所大学的新加坡学生收集的短信。虽然“新加坡式英语”的书面和口头形式可能有很大的不同,但出于实际原因,我们将把它放在一边。

在我的 repo 中有数据集(用于训练的原始版本和干净版本)和四个相关的笔记本。笔记本根据以下任务进行拆分:

  • 笔记本 3.0 :数据准备
  • 笔记本 3.1 :在 Colab (Pro)上微调预训练的 DialoGPT-medium 模型
  • 笔记本 3.2 :在交互式 Dash 应用上测试模型性能
  • 笔记本 3.3 :使用 aitextgen 生成文本的 CPU 替代方案

就资源需求而言,如果你对 DialoGPT-small 模型而不是更大的版本进行微调,你可以在免费的 Google/Colab 帐户上运行这个项目。如果您使用更健壮的数据集,也许微调 DialoGPT-small 模型就足够了。

但我发现,我对较小型号进行微调的结果并不理想,而且为了避免突破免费谷歌账户的 15Gb 存储限制而不断进行的内务处理是对生产力的一种消耗。

如果你预见到自己将来会尝试更多/更大的变形金刚模型,我会推荐你升级到 Colab Pro,并增加你的谷歌账户的存储空间。这让我可以快速迭代,而不必在家里设置物理 eGPU。

为了简洁起见,我不会在这篇文章中讨论技术细节。我仍在边走边学,关于这个话题的的文章要好得多。大部分代码都是从以前作者的作品中摘录或改编的,它们在笔记本中也得到承认。

步骤 1:数据准备

该项目的第一个也是最大的问题是,你是否能为你的用例找到一个合适的数据集。用例越具体(比如说,一个特雷弗·诺亚聊天机器人),就越难找到合适的训练数据。从一开始就应该考虑伦理问题:即使你可以接触到文字记录,用真人来模拟聊天机器人合适吗?潜在的误用可能性有多大?

这个项目中使用的匿名短信数据集是公共空间中为数不多的“新加坡式”语料库之一,也是我发现的唯一一个足够大的数据集。 notebook3.0 的前半部分包含了从深度嵌套的 json 文件中提取 SMS 所需的步骤。如果您使用不同的数据集,请跳过此步骤。

第二部分讨论了在 DialoGPT 模型中必须准备好的训练和验证数据集的具体方法。基本上,对于每条短信,你必须创建 x 条以前的短信作为“上下文”:

点击这里查看另一个例子如何在构建 Rick Sanchez 机器人时准备数据。

我选择了之前的七个回答,但你可以上下调整,看看这对聊天机器人的性能有没有影响。如果这对你来说不仅仅是一个实验,我怀疑这是你将花费大量时间调整数据集以清理响应/上下文的地方。不幸的是,我还没有遇到一个好的教程,告诉我如何最好地构造或调整定制数据集来微调 DialoGPT 模型。

将响应上下文数据集分成训练集和验证集之后,就可以进行微调了。

步骤 2:微调对话框

微调过程中涉及到大量的代码,但由于像内森·库珀和 T2 这样的人的早期工作,训练循环可以原样使用,而新用户不必进行重大更改。当你有更多的时间时,你可以更详细地研究这些代码。记事本 3.1 中需要注意的关键单元格如下:

这是您需要根据您的数据集和设置进行更改的地方。例如,您可以坚持使用中型 DialoGPT 型号或向下调节至小型型号。

如果您遇到 GPU 内存不足的问题,您将不得不减少批量大小(正如我在上面的单元格中所做的那样,减少到 1)。如果你的 Google Drive 中没有太多剩余的存储空间,你必须相应地调整 logging_steps 和 save_steps 的间隔(在各个检查点保存的文件可能会在一瞬间吃掉存储空间)。

微调过程可能需要 40 分钟到大约 2 小时,具体取决于您设置的参数。请注意,即使在 Colab Pro 上也有使用限制。例如,由于 GPU 内存限制,我无法微调 DialoGPT-large 模型。Colab Pro 笔记本电脑可以运行长达 24 小时,但我还没有用更多的时间来测试。

在微调过程结束时需要注意的一个指标是困惑分数——衡量模型在选择下一个令牌时有多确定。分数越低越好,因为这意味着模型的不确定性越小。

通过微调 DialoGPT-medium 模型,我得到了 1.6134 的困惑分数,与使用 DialoGPT-small 模型时 6.3 到 5.7 的分数相比,这是一个显著的改进。你要跑几次才能算出可接受的分数。

你可以在笔记本的末端开始与机器人聊天(假设一切运行正常),但我更喜欢将微调后的模型加载到应用程序中。感谢陆星汉 @ 剧情,为此有了一个笔记本。

第三步:在 DASH 应用程序中测试你微调过的模型

Plotly repo 包含在本地机器上运行聊天机器人应用程序的代码,如果你希望这样做的话,但出于实际原因,我选择在 Colab 上运行 notebook3.2 (微调模型已经存在)。该代码直接从陆星汉的演示中摘录,对于那些可能想进一步试验机器人输出的人,在结尾做了一些小的改动:

“温度”允许你控制回应的创造性(或疯狂/厚颜无耻)程度。您可以通过降低 max_length(最大令牌数:1,024;默认值:256 个令牌)。您可以在这里的“使用交互脚本”一节中找到一个完整的参数列表。

这是我和聊天机器人成功对话的截图。突出显示的单元格是我的条目:

微调过的 pytorch 模型太大了(1.44Gb),无法部署在任何免费的主机帐户上,所以(目前)你没有办法在 web 应用程序上尝试这个特殊的新加坡式聊天机器人。

我的观点是:“新加坡式”聊天机器人还没有准备好进入黄金时段。它有时会给出令人惊讶的好的回应,但在几次交流之后就无法继续努力了。正如你在上面的截图中所看到的,事情在接近尾声时变得不稳定。有了更丰富的数据集和足够的计算来训练一个 DialoGPT-large 模型,响应可能会变得更好。

但是作为一个实验,我不得不说性能一点也不差。

额外的一步:CPU 替代自动文本生成

如果您不想使用 Colab 和/或将数据和微调限制在本地机器上,那么有很多替代方法。我将重点介绍我一直在试验的一个 Python 库——aitextgen——它为纯 CPU 训练提供了一个选项。

笔记本 3.3 概述了一个在本项目中使用相同 SMS 数据集的简单示例。我之前曾尝试用 aitextgen 处理其他数据集,包括新加坡政治演讲的 YouTube 文本。不幸的是,到目前为止我还没有得到非常满意的结果。

我可能没用对。你可能会有更好的运气。一个 itextgen 也可以在 Colab 上运行。

希望这篇文章和附带的笔记本能帮助你快速开始你自己的人工智能聊天机器人实验。更难的是弄清楚如何提高它的性能,或者确保它对公众使用是安全的。

还有一些相关的技术问题需要探索,例如为部署而精简模型,或者更高级的交互式应用设计,可以在聊天机器人中带来更多功能。如果你对以上话题有什么建议,或者发现了这篇文章中的错误,请联系我:

推特:蔡钦汉

领英:www.linkedin.com/in/chuachinhon

使用 Python 中的 Keras 构建人工神经网络的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-building-artificial-neural-networks-using-keras-in-python-bdc4989dab00?source=collection_archive---------19-----------------------

初学者的深度学习

创建网络架构、训练、验证和保存模型并使用它进行推理的提示和技巧。

图片由 Gerd Altmann 从 Pixabay 拍摄

为什么是 Keras,而不是 Tensorflow?

如果你在问“我应该用 keras 还是 tensorflow?”,你问错问题了。

当我第一次开始我的深度学习之旅时,我一直认为这两者是完全独立的实体。好吧,截至2017 年年中,他们不是! Keras,一个神经网络 API,现在已经完全集成在 TensorFlow 中。那是什么意思?

这意味着您可以在使用高级 Keras API 或低级 TensorFlow API 之间进行选择。高级-API在一个命令中提供更多的功能,并且更易于使用(与低级 API 相比),这使得它们甚至对于非技术人员也是可用的。低级 API允许高级程序员在非常精细的级别上操作模块内的功能,从而允许为新颖的解决方案定制实现。

注意:出于本教程的目的,我们将只使用 Keras!

让我们直接进入编码

我们首先在机器上安装 Keras。正如我之前所说,Keras 集成在 TensorFlow 中,因此您所要做的就是在您的终端(Mac OS)中pip install tensorflow访问 Jupyter 笔记本中的 Keras。

资料组

我们将使用贷款申请数据集。它有两个预测特征,一个连续变量- age和一个分类变量- area(农村与城市),以及一个二元结果变量application_outcome,可以取值 0(批准)或 1(拒绝)。

import pandas as pddf = pd.read_csv('loan.csv')[['age', 'area', 'application_outcome']]
df.head()

我们数据集中的样本。

预处理数据

为了避免过度拟合,我们将使用MinMaxScaler在 0 和 1 之间缩放age,并使用Sklearn工具包中的LabelEncoderareaapplication_outcome特征进行标签编码。我们这样做是为了将所有输入要素放在同一个比例上。

from sklearn.preprocessing import LabelEncoder, MinMaxScaler
from itertools import chain# Sacling the Age column
scaler = MinMaxScaler(feature_range = (0,1))a = scaler.fit_transform(df.age.values.reshape(-1, 1))
x1 = list(chain(*a))# Encoding the Area, Application Outcome columns
le = LabelEncoder()x2 = le.fit_transform(df.area.values)
y = le.fit_transform(df.application_outcome) # Updating the df
df.age = x1
df.area = x2
df.application_outcome = ydf.head()

来自我们的缩放的数据集的样本

如果您阅读了 Keras 文档,它要求输入数据是 NumPy 数组类型。这就是我们现在要做的!

scaled_train_samples = df[['age', 'area']].values
train_labels = df.application_outcome.valuestype(scaled_train_samples) *# numpy.ndarray*

生成模型架构

建立 Keras 模型有两种方式:顺序(最基本的一种)和泛函(复杂网络用)。

我们将创建一个序列模型,它是一个线性层叠。也就是说,顺序 API 允许你逐层创建模型。在大多数情况下,它非常适合开发深度学习模型。

# Model architecturemodel_m = Sequential([
    Dense(units = 8, input_shape= (2,), activation = 'relu'),
    Dense(units = 16, activation = 'relu'),
    Dense(units = 2, activation = 'softmax') 
])

在这里,第一密集层实际上是第二层整体(因为实际的第一层将是我们从原始数据中输入的层)但是第一“隐藏”层。它有 8 个单元/神经元/节点,8 个是任意选择的!

input_shape参数是您必须根据您的数据集分配的。直观地说,就是网络应该期望的输入数据的形状。我喜欢把它想成— “我正在馈入神经网络的一个 单个 行数据是什么形状?”。

在我们的例子中,输入的一行看起来像[0.914, 0]。即它是一维的。因此,input_shape参数看起来像一个元组(2,),其中 2 指的是数据集中的要素数量(agearea)。因此,输入层需要一个包含 2 个输入元素的一维数组。它将产生 8 个输出作为回报。

如果我们正在处理,比如说黑白 2×3 像素图像(我们将在下一篇关于卷积神经网络的教程中研究,我们将会看到输入的一行(或向量表示单个图像)看起来像[[0 , 1, 0] , [0 , 0, 1],其中 0 表示像素是亮的,1 表示像素是暗的。即,它是二维的。随后,input_shape参数将等于(2,3)。

注意:在我们的例子中,我们的输入形状只有一个维度,所以您不一定需要以元组的形式给出它。相反,你可以给 *input_dim* 作为标量数。因此,在我们的模型中,我们的输入层有两个元素,我们可以使用这两个中的任何一个:

  • *input_shape=(2,)* -当你只有一个维度时,逗号是必要的
  • *input_dim = 2*

围绕输入形状参数的一个普遍误解是,它必须包括我们输入到神经网络的输入样本总数(在我们的例子中是 10,000)。

训练数据中的行数是网络输入形状的而不是部分,因为训练过程每批向网络提供一个样本(或者更准确地说,每批的 batch_size 样本)。

第二个“隐藏”层是另一个密集层,具有与第一个隐藏层相同的激活功能,即“relu”。激活函数确保传递的值位于可调的预期范围内。整流线性单元(或 relu)功能返回直接作为输入提供的值,如果输入为 0.0 或更小,则返回值 0.0。

你可能想知道为什么我们没有为这个层指定input_shape参数。毕竟,Keras 需要知道它们输入的形状,以便能够创建它们的权重。事实是,

无需为第二(或后续)隐藏层指定input_shape参数,因为它会根据架构(即每层的单元和特性)自动计算输入节点的最佳数量。

最后,我们的顺序模型中的第三个或最后一个隐藏层是另一个具有 softmax 激活功能的密集层。softmax 函数返回两个类的输出概率— approved(输出= 0)和rejected(输出= 1)。

模型摘要如下所示:

model_m.summary()

我们的顺序模型的总结

让我们看看如何计算每一层的参数总数,即Param #。请记住,在每一层中,我们还有一个偏置神经元(除了在模型架构中预先指定的神经元之外)。因此,在第一个隐藏层中,我们有 3 个输入神经元(2 个来自输入数据特征的神经元+ 1 个偏置神经元)和 8 个输出神经元。因此,总共需要训练 83 = 24 个参数。类似地,在第二隐藏层中,我们现在有 9 个输入神经元(8 个来自第一隐藏层加上 1 个偏置神经元)和 16 个输出神经元,总共 169 = 144 个可训练参数。最后,最后一层将具有 17*2=34 个可训练参数。

为培训准备模型

model_m.compile(optimizer= Adam(learning_rate = 0.0001), 
              loss = 'sparse_categorical_crossentropy', 
              metrics = ['accuracy'] 
             )

在我们开始用实际数据训练我们的模型之前,我们必须用某些参数compile模型。在这里,我们将使用亚当optimizer

优化器的可用选择包括 SGD、Adadelta、Adagrad 等。

loss参数指定应该在每次迭代中监控交叉熵损失。metrics参数表示我们希望根据精确度来判断我们的模型。

训练和验证模型

# training the model
model_m.fit(x = scaled_train_samples_mult, 
          y = train_labels, 
          batch_size= 10, 
          epochs = 30, 
          validation_split= 0.1, 
          shuffle = True,
          verbose = 2 
         )

xy参数非常直观——分别是预测变量和结果变量的 NumPy 数组。batch_size指定一个批次中包含多少个样本。epochs=30表示模型将在所有数据上训练 30 次。verbose = 2表示它被设置为输出消息中最详细的级别。

我们正在使用 0.1 validation_split动态创建一个验证集,即在每个时期保留 10%的训练数据,并将其排除在训练之外。这有助于检查我们模型的可推广性,因为通过获取训练集的子集,模型仅在训练数据上学习而在验证数据上进行测试。

请记住,验证拆分发生在训练集被打乱之前,即在验证集被取出后,只有训练集被打乱。如果在数据集的末尾有所有被拒绝的贷款申请,这可能意味着您的验证集有对类的错误描述。所以你必须自己洗牌,而不是依靠 keras 来帮你!

这是前五个纪元的样子:

这是最后五个纪元的样子:

如您所见,在第一个时期,我们从验证集的高损失(0.66)和低准确度(0.57)开始。渐渐地,我们能够减少损失(0.24)并提高最后一个时期验证集的准确性(0.93)。

对测试集进行推理

我们以类似于训练集的方式对之前未见过的测试集进行预处理,并将其保存在scaled_test_samples中。相应的标签存储在test_labels中。

predictions = model.predict(x = scaled_test_samples, 
                            batch_size= 10,
                            verbose=0)

确保选择与培训过程中使用的batch_size完全相同的产品。

由于我们的最后一个隐藏层有一个 softmax 激活函数,predictions包括两个类的输出概率(左边是类 0 的概率(即批准的),右边是类 1 的概率(即拒绝的)。

当最终层具有 softmax 激活时,来自 ANN 的预测。

从这里开始有几种方法。您可以选择一个任意的阈值,比如 0.7,并且只有当类别 0(即批准)的概率超过 0.7 时,您才应该选择批准贷款申请。或者,您可以选择概率最高的类作为最终预测。例如,根据上面的截图,该模型预测贷款将有 2%的概率被批准,但有 97%的概率被拒绝。因此,最后的推论应该是,此人的贷款被拒绝。我们将采取后者。

# get index of the prediction with the highest probrounded_pred = np.argmax(predictions, axis = 1)
rounded_pred

为测试集所做的预测

保存和加载 Keras 模型

为了保存 来自已训练模型的所有内容:

model.save('models/LoanOutcome_model.h7')

我们基本上保存了我们训练模型
1 的所有内容。架构(神经元的层数等)
2。学习的重量
3。训练配置(optimizers,loss)
4。优化器的状态(便于重新训练)

要加载我们刚刚保存的模型:

from tensorflow.keras.models import load_model
new_model = load_model('models/LoanOutcome_model.h7')

为了只保存 的架构:

json_string = model.to_json()

从先前存储的架构中重建新模型:

from tensorflow.keras.models import model_from_json
model_architecture = model_from_json(json_string)

只保存重量:

model.save_weights('weights/LoanOutcome_weights.h7')

要将权重用于其他模型架构:

model2 = Sequential([
    Dense(units=16, input_shape=(1,), activation='relu'),
    Dense(units=32, activation='relu'),
    Dense(units=2, activation='softmax')
])# retrieving the saved weights
model2.load_weights('weights/LoanOutcome_weights.h7')

现在我们有了。我们已经成功地建立了我们的第一个人工神经网络,并对其进行了训练、验证和测试,还成功地将其保存下来以备将来使用。在下一篇文章的中,我们将通过卷积神经网络(CNN)来处理图像分类任务。

在那之前:)

[## 使用 TensorFlow 的 Keras API 在 Python 中构建卷积神经网络的初学者指南

解释具有 MaxPool2D、Conv2D 和 Dense 图层的端到端二值图像分类模型。

towardsdatascience.com](/beginners-guide-to-building-convolutional-neural-networks-using-tensorflow-s-keras-api-in-python-6e8035e28238) [## 在数据科学面试中解释你的 ML 项目的逐步指南。

在结尾有一个额外的样本脚本,让你谨慎地展示你的技术技能!

towardsdatascience.com](/step-by-step-guide-to-explaining-your-ml-project-during-a-data-science-interview-81dfaaa408bf) [## 使用 FLASK 将 H2o 模型部署为 API

模型训练、调优和创建简单 API 的端到端示例(没有技术术语)。

towardsdatascience.com](/deploying-h2o-models-as-apis-using-flask-42065a4fa567) [## 使用 Python 中的 Pandas 进行时间序列分析

对季节性、趋势、自相关等关键词的额外介绍。

towardsdatascience.com](/time-series-analysis-using-pandas-in-python-f726d87a97d8)

使用 TensorFlow 的 Keras API 在 Python 中构建卷积神经网络的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-building-convolutional-neural-networks-using-tensorflow-s-keras-api-in-python-6e8035e28238?source=collection_archive---------12-----------------------

初学者的深度学习

解释具有 MaxPool2D、Conv2D 和 Dense 图层的端到端二值图像分类模型。

来自 Pixabay 的皮特·林弗斯的图片

欢迎来到神经网络系列的第 2 部分!在第 1 部分的中,我们使用 Keras API 研究了一个人工神经网络(ann)。我们讨论了顺序网络架构、激活函数、隐藏层、神经元等。最后用一个端到端的例子来预测贷款申请是被批准还是被拒绝。

在本教程中,我们将学习如何使用 Keras API 创建卷积神经网络(CNN)。为了让它更直观,我将解释这个网络的每一层是做什么的,并提供一些提示和技巧来简化你的深度学习之旅。我们在本教程中的目的是建立一个基本的 CNN,它可以对胸部 x 光图像进行分类,并确定它是正常的还是患有肺炎。鉴于新冠肺炎疫情,我认为这将成为一个有趣的项目,即使是你的数据科学采访!

我们开始吧!

什么时候应该使用卷积神经网络而不是人工神经网络?

当数据可以以空间方式表示时,比如说以 MxN 像素表示的图像,CNN 工作得最好。如果你的数据在把你的任何一个专栏互相洗牌后仍然有用,那么你就不能使用 CNN。

例如,如果您回忆一下第 1 部分中的贷款申请数据集,它有两列(或特性),即agearea,如果我交换这两列(在将它提供给我的网络之前),对我的数据集没有任何影响。因此,人工神经网络是这种数据集的首选。相反,如果我交换我的图像中的列(本质上是像素阵列),我肯定会弄乱我的实际图像。因此,使用人工神经网络是一大禁忌,你必须使用 CNN。

让我们直接进入编码...

我们首先在机器上安装 Keras。正如我在第 1 部分中讨论的,Keras 集成在 TensorFlow 中,所以您所要做的就是在您的终端(Mac OS)中使用pip install tensorflow来访问 Jupyter 笔记本中的 Keras。要检查 Tensorflow 的版本,请使用tf.__version__

导入库

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Activation, Dense, Flatten, BatchNormalization, Conv2D, MaxPool2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.metrics import categorical_crossentropy
from sklearn.metrics import confusion_matrix
from tensorflow.keras.preprocessing.image import ImageDataGeneratorimport numpy as np
import itertools
import os
import randomimport matplotlib.pyplot as plt
%matplotlib inline

资料组

我们将使用胸部 x 光图像 Kaggle 数据集。下载并解压缩后,您将看到胸部 x 光文件夹,其中包含整齐地组织到训练、有效和测试子文件夹中的图像。每个子文件夹包含两个子文件夹,一个用于normal胸部 x 射线,另一个用于指示pneumonia的 x 射线。

注意:确保 chest_xray 文件夹 和你的 Python Jupyter 笔记本在同一个目录下。

设置训练、验证和测试文件夹的路径:

train_path = "chest_xray/train"
test_path = "chest_xray/test"
valid_path = "chest_xray/val"

注意:如果您收集了自己的数据集&它没有整齐地组织到 train、valid 和 test 文件夹中,不必担心!只需确保(a)您已将所有图像(正常和肺炎)保存在一个名为“胸部 x 射线”的公共文件夹中,并且(b)图像名称包含两个词中的一个——正常或肺炎。在此基础上,使用下面的代码片段将图像组织成训练集、有效集和测试集。

# Organize data into train, valid, test directories
os.chdir('data/chest_xrays')
if os.path.isdir('train/normal') is False:
    os.makedirs('train/normal')
    os.makedirs('train/pneumonia')
    os.makedirs('valid/normal')
    os.makedirs('valid/pneumonia')
    os.makedirs('test/normal')
    os.makedirs('test/pneumonia')

    for i in random.sample(glob.glob('pneumonia*'), 500):
        shutil.move(i, 'train/pneumonia')      
    for i in random.sample(glob.glob('normal*'), 500):
        shutil.move(i, 'train/normal')
    for i in random.sample(glob.glob('pneumonia*'), 100):
        shutil.move(i, 'valid/pneumonia')        
    for i in random.sample(glob.glob('normal*'), 100):
        shutil.move(i, 'valid/normal')
    for i in random.sample(glob.glob('pneumonia*'), 50):
        shutil.move(i, 'test/pneumonia')      
    for i in random.sample(glob.glob('normal*'), 50):
        shutil.move(i, 'test/normal')

os.chdir('../../')

预处理图像数据

我们需要将数据转换成模型期望的格式。所以我们必须把我们的图像转换成 T2 的格式。简而言之,我们将使用ImageGenerator类中的flow_from_directory()函数从 train、test 和 valid 目录创建批处理。使用fit函数将这些批数据传递给顺序模型。(以前,在第 1 部分构建 ann 时,我们将 NumPy 数组传递给 fit 函数,但现在我们需要将批处理传递给 fit 函数)。

作为预处理的一部分(在创建批处理之前),我们将应用preprocessing_function = tf.keras.applications.vgg16.preprocess_input。这将按照图像传递到 vgg16 模型(2014 年赢得 ImageNet 竞赛的 CNN 模型)时处理图像的相同方式来处理我们的图像。

*# Creating train, test and valid batches from the respective directories*train_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=train_path, target_size=(224,224), classes=['pneumonia', 'normal'], batch_size=10)valid_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=valid_path, target_size=(224,224), classes=['pneumonia', 'normal'], batch_size=10)test_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=test_path, target_size=(224,224), classes=['pneumonia', 'normal'], batch_size=10, shuffle=False)

target_size指定我们希望图像调整到的高度和宽度。这很重要,因为我们的数据集中可能有不同大小的图像。

batch_size被设置为 10,并且 10 的选择是任意的。32 中使用的另一个常见批量值,但理想情况下,最佳值应该通过超参数调整找到(我们将在下一个教程中学习如何做到这一点)。

批量大小指定了在更新神经网络的权重之前 一次应该将多少训练样本传递给神经网络。

我们还为测试集只指定了shuffle = False,因为稍后当我们测试我们的模型时,我们想要访问未混淆的标签来绘制我们的混淆矩阵。默认情况下,shuffle 设置为 True。

注意:如果你在运行上面的代码时看到 *Found 0 images beloning to 2 classes* ,很可能你指向了错误的目录!解决这个问题,它应该工作正常!

可视化图像数据:

使用 TensorFlow 的文档中的绘图助手功能。

*# plot images in the form of a 1 by 10 grid and resize img to 20x20*
def plotImages(images_arr):
    fig, axes = plt.subplots(1, 10, figsize=(20,20))
    axes = axes.flatten()
    for img, ax in zip( images_arr, axes):
        ax.imshow(img.astype(np.uint8))
        ax.axis('off')
    plt.tight_layout()
    plt.show()

Newt,我们将使用 Python 函数next()从训练集中抓取一批图像和相应的标签。由于我们设置了batch_size = 10,我们将看到在imgs中有 10 个图像,在labels中有 10 个相应的标签。

imgs, labels = next(train_batches)plotImages(imgs)
print(labels)

注意: *imshow* 期望输入在 *[0, 1]* *[0, 255]* 的范围内,所以如果输入数组没有这个范围,它将削波输入。因此,我们在显示时显式地将图像转换为 *np.int8* 格式。

注意:图像可能看起来与你的目录中的有一点不同(可能有点失真),但那是因为我们对它执行了一些 vgg16 预处理步骤。

标签是指示图像是肺炎还是正常的一次性编码向量。A [1 0]代表肺炎,而[0 1]代表正常 x 光。

生成模型架构

回想一下,当我们在第 1 部分中构建一个用于预测贷款申请结果的人工神经网络时,我们介绍了一个序列模型。简而言之,顺序 API 允许你逐层创建模型。

model = Sequential([
    Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(224,224,3)),
    MaxPool2D(pool_size=(2, 2), strides=2),
    Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding = 'same'),
    MaxPool2D(pool_size=(2, 2), strides=2),
    Flatten(),
    Dense(units=2, activation='softmax')
])

****第一个隐藏层是标准卷积层Conv2D,有 32 个滤波器,每个滤波器的核大小为 3x3。请记住,每个过滤器都专用于识别图像的某些方面,比如过滤器 1 检测胸腔的垂直边界,过滤器 2 检测胸腔的对角线边界,等等...随着时间的推移,随着我们深入网络的卷积层,过滤器编码的模式将变得复杂。

注:32 的选择是任意的!

一个内核是一个由数字组成的小网格,你将它传递给你的整个图像,即你输入图像中的所有像素,并根据这些数字进行转换。

通过在内核中使用不同的数字,您可以执行不同类型的图像预处理(在图像识别期间),如对比度、模糊、锐化或边缘检测。一般来说,内核比映像小,3x3 是相当常见的选择!

Gif 展示了一个 3x3 内核如何通过整个图像。来源:https://www . machine learning uru . com//computer _ vision/basics/convolution/convolution _ layer . html

当内核到达图像的边缘时,它必须决定在输入图像中没有像素的地方做什么。现在,我们继续用零填充边缘,使用padding = 'same'实现。零填充意味着在图像外部提供一个零缓冲(如上面的 gif 图像所示)。这有助于确保卷积操作后输入图像的维度不会减少。

注意:根据内核大小和图像大小,你可能需要做两到三层厚的垫子。

从第 1 部分,您已经知道我们如何根据自己的数据集得出input_shape参数。基本上,它可以被认为是一个单个图像的形状,该图像被馈送到网络,在我们的例子中是 224x224x3(高度=宽度= 224,3 是颜色通道,更准确地说是 RGB 分量)。您可以通过使用给出元组(224,224,3)作为答案的imgs[0].shape检查imgs中随机元素(比如第一个元素)的形状来验证这是否正确。

最后,对于第一个隐藏层,我们有relu激活函数(在第一部分讨论过)。总的来说,激活函数确保传递的值在可调的预期范围内。整流线性单元(或 relu)函数返回直接作为输入提供的值,或者如果输入为 0.0 或更小,则返回值 0.0。

****第二个隐藏层是最大池层MaxPool2D,主要用于降低数据的维度。其方法是从过滤后的图像(来自卷积/RELU 层)中选择一个窗口大小(pool_size = 2x2),然后用该窗口中的最高值替换其中的 4 个像素。接下来,向右(或向下或向上)移动两步stride,用最高值替换这 4 个像素。等等,直到整个图像被覆盖。

MaxPooling 的例子。来源

****第三第四隐藏层又分别是Conv2DMaxPool2D

注意:第二个 *Conv2D* 图层有 *filters = 64* ,是第一个 *Conv2D* 图层滤镜数量的两倍(其中有 32 个滤镜)。当我们进入网络的较后的层时,这种功能的增加是一种常见的做法。

最后,我们flatten卷积层的输出,并通过units = 2(对应于输出类pneumonianormal)和softmax激活将其传递给Dense层。softmax 函数返回两个类的输出概率。(关于 softmax 激活的详细描述,请在此处阅读)。

模型摘要如下所示:

model.summary()

为培训准备模型

model.compile(optimizer=Adam(learning_rate=0.0001), loss='categorical_crossentropy', metrics=['accuracy'])

在我们开始用实际数据训练我们的模型之前,我们必须用某些参数compile模型。这里,我们将使用 Adam optimizerloss参数指定在每次迭代中应该监控分类交叉熵损失。metrics参数表示我们希望根据精确度来判断我们的模型。

训练和验证模型

注意:当下面的代码运行时,你可以很容易地去喝杯咖啡什么的。在 CPU 上,每个时期花费我大约 5 分钟,所以运行 10 个时期大约需要 50 分钟。

*# recall that we set batch_size = 10 during preprocessing* batch_size = 10 

model.fit(
    x = train_batches, 
    steps_per_epoch=train_batches.samples // batch_size, 
    epochs=10, 
    validation_data=valid_batches, 
    validation_steps=valid_batches.samples // batch_size,
    verbose=2)

如果你仔细观察,我们没有明确地为训练集声明标签(就像我们在第一部分中使用y参数为 ann 所做的那样),原因是它们已经包含在train_batches迭代器中。

steps_per_epoch是根据你的训练数据计算出来的。例如,如果我们的训练集中的样本数是 1000,批量大小是 20,那么通过除以 1000/20 = 50 来计算steps_per_epoch

更正式地说,

steps_per_epoch 它通常应等于 ceil(样本数/批量大小)

此外,既然我们正在通过validation_data = valid_batches,我们也需要通过validation_steps。它与steps_per_epoch参数完全一样,但主要是关于验证数据(而不是训练数据)。

这是模型训练的输出,根据输出消息将verbose设置为最高级别:

如您所见,由于训练集准确率为 100%,训练集损失几乎可以忽略不计,但验证集的准确率仅为 75%,因此肯定存在一些过度拟合。但是,嘿,即使有这样一个基本的模型架构和只有六个隐藏层,这一点也不差,首先!

如果你想达到更高的精度(~92%),使用更深的模型架构,就像这里描述的。

减少过度拟合的另一个很棒的方法是使用退出和批量正则化,我们将在下一个教程中讨论。

对测试集进行推理

*# making predictions* predictions = model.predict(x = test_batches, verbose=0)

直接使用 Scikit 学习文档中的绘图功能:

def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        print("Normalized confusion matrix")
    else:
        print('Confusion matrix, without normalization')print(cm)thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
        plt.text(j, i, cm[i, j],
            horizontalalignment="center",
            color="white" if cm[i, j] > thresh else "black")plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')

使用混淆矩阵可视化预测结果

*# confusion matrix*
cm = confusion_matrix(y_true=test_batches.classes, y_pred=np.argmax(predictions, axis=-1))plot_confusion_matrix(cm, classes = ['Pneumonia', 'Normal'])

这就是我们的第一个用于 Python 二进制图像分类的 CNN 模型。请参考第 1 部分,了解如何保存优化器的模型架构、权重和状态。在下一个教程中,我们将学习如何提高 CNN 和 ann 对测试数据的准确性。

在那之前:)

** [## 使用 Python 中的 Keras 构建人工神经网络的初学者指南

创建网络架构、训练、验证和保存模型并使用它进行推理的提示和技巧。

towardsdatascience.com](/beginners-guide-to-building-artificial-neural-networks-using-keras-in-python-bdc4989dab00) [## 在数据科学面试中解释你的 ML 项目的逐步指南。

在结尾有一个额外的样本脚本,让你谨慎地展示你的技术技能!

towardsdatascience.com](/step-by-step-guide-to-explaining-your-ml-project-during-a-data-science-interview-81dfaaa408bf) [## 使用 Python 中的 Pandas 进行时间序列分析

对季节性、趋势、自相关等关键词的额外介绍。

towardsdatascience.com](/time-series-analysis-using-pandas-in-python-f726d87a97d8)**

聚类技术完全指南

原文:https://towardsdatascience.com/beginners-guide-to-clustering-techniques-164d6ad5dbb?source=collection_archive---------49-----------------------

照片由 @plqml // felipe pelaquim 在 Unsplash 上拍摄

为了成为 Kaggle 上的大师,我从一个简单的数据挖掘算法开始发布笔记本。我要解释的第一个算法是聚类。

链接到 Kaggle 笔记本 。如果你喜欢这个帖子,请给我的 kaggle 笔记本投票。

介绍

聚类是一种无监督的学习技术,您可以获取整个数据集,并在数据集中找到“相似实体的组”。因此,数据集中没有标签。

这有助于将非常大的数据集组织成有意义的聚类,从而有助于采取行动。例如,将超过 100 万条记录的整个客户群划分为高价值客户、低价值客户等等。

聚类通常倾向于回答什么问题?

  • 网络上有哪些类型的页面?
  • 我的市场中有哪些类型的客户?
  • 社交网络上有哪些类型的人?
  • 我收件箱中的电子邮件类型
  • 基因的种类人类的基因组有哪些?

从聚类到分类

聚类是所有分类问题的基础。最初,假设我们在一个新的社交媒体平台上有大量未分组的用户。我们肯定知道,社交媒体中的用户数量不会等于群组数量,而且它将是合理有限的。尽管每个用户可能有细微的差别,但他们可以合理地分组。当我们知道这些用户属于哪个组时,这些分组的每一个聚类都成为类。

划分聚类

在开始聚类之前,如果我们假设数据将落入 x 个聚类中,然后将数据划分到这些数量的聚类中,这就称为分区聚类。在分区聚类中执行聚类之前,聚类的数量是已知的。k-Means 是一种流行的划分聚类技术,其中数据被划分为 k 个唯一的聚类。

k-均值聚类

  • 设数据点 X = {x1,x2,x3,… xn}为需要聚类成 K 个簇的 N 个数据点。
  • K 介于 1 和 N 之间,其中 if:
    • K = 1 那么整个数据就是单个聚类,整个数据的均值就是我们要寻找的聚类中心。
    • K =N,那么每个数据单独代表一个单独的聚类。
      通常 K 介于 1 和 n 之间

作为优化问题的公式

设 M = {m1,m2,m3,… mk}为 K 个聚类的聚类均值。每一个 m 都代表我们正在寻找的单个集群。
目标函数是我们为每个聚类找到这样的表示,它最好地逼近数据并且逼近的误差最小。

我们试图最小化的目标函数是每个数据点与其代表点之间距离的平方和。

使用 SKLearn 实现 k-Means

但是 5 个集群足够好吗?

如上所述,在这种情况下,我们需要准确地指定我们要寻找多少个集群。群集的数量很难直观地猜测。只有对数据了如指掌,才能凭直觉猜测。

集群数量的解决方案

我们使用不同数量的聚类运行 k-Means 算法,并通过绘制来自 sklearn 的惯性参数来绘制拟合优度,该参数给出了样本到其最近聚类中心的平方距离之和。

k 均值聚类的局限性

k-Means 聚类只能分离线性聚类边界,这意味着它将无法识别复杂得多的决策边界。

这可以通过在 sklearn 上制作 moons 数据集来解释,如下所示:

这个问题的答案可以在了解层次聚类中找到。

分层聚类

自然界是由等级制度组成的,就像食物链、组织结构、物种的生物分类等等。自底向上的层次聚类也称为聚集聚类。

聚集聚类中的关键超参数称为连锁。这是两个集群之间的距离。它类似于用于 k-均值聚类的聚类均值 M。它可以用多种方式表示:

  • 单链:两个簇之间最近的两个点之间的距离。
  • 完全连锁:两个集群之间两个最远点之间的距离。
  • 平均连锁:介于单一连锁和完全连锁之间。取所有点对之间的平均值。这对于噪声是鲁棒的。

使用 SKLearn 实现聚集聚类

对于同一个月球数据集,我们现在可以看到,通过聚集聚类,单个链接,我们可以得到很好的聚类。

谱聚类

处理相似度图,其中每个节点代表一个实体和边上的权重。考虑类似于一个图的结构,其中所有节点通过由权重构成的边连接到所有其他节点。如果我们想把它分成两个簇,显然我们想去掉权重最低的边。

使用 SKLearn 实现谱聚类

人造卫星将如下所示:

比较和对比不同的聚类技术

我对聚类技术的解释到此结束。我欢迎您的反馈和建议。

如果你觉得这个帖子有用,请在 kaggle 上投票支持我的笔记本!

参考文献:

https://sci kit-learn . org/stable/modules/generated/sk learn . cluster . k means . html # sk learn . cluster . k means
https://sci kit-learn . org/stable/auto _ examples/cluster/plot _ cluster _ iris . html # sphx-glr-auto-examples-cluster-plot-cluster-iris-py
https://grey atom . com/programs/learn-data-science-online-with

图片来自:

https://www . mygreatlearning . com/blog/clustering-algorithms-in-machine-learning/
https://commons . wikimedia . org/wiki/File:K-means _ convergence . gif
https://www . solver . com/XL miner/help/hierarchical-clustering-intro
https://towardsdatascience . com/spectral-clustering-ABA 2640 d5b

创建强大聊天机器人的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-creating-a-powerful-chatbot-48fc6b073e55?source=collection_archive---------10-----------------------

安迪·凯利在 Unsplash 上的照片

实践教程

有没有想过使用聊天机器人来帮助回答客户的标准问题?

您是否面临着太多来自客户的标准要求和问题,并且难以应对?您是否正在寻找一种方法来扩大您的客户服务,而不会产生太多的成本?

在我之前的故事中,我分享了我如何通过创建一个个人文本摘要器来总结文档,从而解决数据过载的问题。

在这个故事中,我将向您展示如何轻松创建一个强大的聊天机器人来处理您不断增长的客户请求和询问。我还将向您展示如何使用 Flask 将您的聊天机器人部署到 web 应用程序。

首先,为什么聊天机器人在这种时候特别重要,它是什么

新冠肺炎疫情重创了世界。由于封锁/移动控制,许多企业遭受了重大损失。为了度过这段艰难时期,许多人被迫将业务转移到网上。

在线企业主面临的一个主要的、常见的问题是必须对来自客户的大量问题和请求做出回应。对于那些人力资源有限的人来说,不可能及时处理所有的请求。

为了解决这个问题,许多企业主转向使用聊天机器人为他们的客户服务。

什么是聊天机器人: 聊天机器人是由人工智能驱动的智能软件,能够与人类对话,并执行类似人类的任务。聊天机器人存在于许多智能设备(例如 Siri (iOS)、谷歌助手(Android)、Cortana(微软)、Alexa(亚马逊))、网站和应用程序中。

为什么使用聊天机器人: 根据 HubSpot 进行的一项研究,71%的用户愿意使用快速响应的聊天应用程序来获得客户帮助,许多人这样做是因为他们希望他们的问题能够得到快速解决(当然也是高效的)。如果配置智能,聊天机器人确实可以通过允许人力资源专注于关键业务,同时保持相同水平的客户满意度,为企业释放巨大的价值。

如何创建聊天机器人?

我将把它分成三个主要部分,但是您可以直接进入您感兴趣的部分:

(a)使用 Jupyter notebook 构建聊天机器人

(b)在终端运行聊天机器人

(c)使用 Flask 将聊天机器人部署为网络应用

(a)使用 Jupyter notebook 构建聊天机器人

多亏了 Python 中的 ChatterBot 库,创建一个聊天机器人不再像过去那样是一项令人生畏的机器学习任务。

现在,让我们把手弄脏…

(1)安装聊天机器人库

我们将从安装 ChatterBot 库开始。终端的安装命令如下:

pip install chatterbot

ChatterBot 文本语料库(由大量结构化文本组成的语言资源)是在它自己的 Python 包中分发的,因此您需要单独安装它:

pip install chatterbot_corpus

如果您之前没有安装 spaCy (一个用于高级自然语言处理的开源库),那么请现在安装它,因为 ChatterBot 库需要 spaCy 库才能工作:

pip install spacy

安装完 spaCy 库后安装 spaCy 英文 ('en') 型号:

python -m spacy download en

(2)创建聊天机器人实例

在我们将整个聊天机器人打包成 Python 脚本之前,我们将使用 Jupyter Notebook 开发我们的聊天机器人。让我们从导入我们需要的模块开始:

from chatterbot import ChatBot

我们将创建一个聊天机器人实例,将我们的机器人命名为 Buddy ,并将 read_only 参数指定为 True ,因为我们只想让我们的聊天机器人从我们的训练数据中学习。

通过创建一个聊天机器人实例,将为您创建一个名为 db.sqlite3 的聊天机器人数据库。

bot = ChatBot('Buddy', read_only = True)

(3)训练聊天机器人

是时候训练我们的聊天机器人了……(什么,就这样?是的——这不是开玩笑!)

这种训练仅仅意味着将对话输入聊天机器人数据库。请参见下面的示例:

对话源(图片由作者提供)

一旦聊天机器人被输入“对话 1”和“对话 2”,聊天机器人就会以正确的顺序将这些对话存储在其“知识图”数据库中。

存储在数据库中的知识图表(图片由作者提供)

之后,你可以用上面的任何一种说法开始对话。

例如,你可以用陈述 6 开始对话(“你接受什么付款方式?”),聊天机器人将以声明 7(“我们接受借记卡和主要信用卡”)进行响应。

记住这个概念,让我们用“对话 1”和“对话 2”来训练我们的聊天机器人。

我们通过导入 ListTrainer 模块来实现,通过传递聊天机器人对象(好友)来实例化它,并调用 train() 方法来传递句子列表。

from chatterbot.trainers import ListTrainer
trainer = ListTrainer(bot)trainer.train([
    "Hi, can I help you",
    "Who are you?",
    "I am your virtual assistant. Ask me any questions...",
    "Where do you operate?",
    "We operate from Singapore",
    "What payment methods do you accept?",
    "We accept debit cards and major credit cards",
    "I would like to speak to your customer service agent",
    "please call +65 3333 3333\. Our operating hours are from 9am to 5pm, Monday to Friday"

])trainer.train([
    "What payment methods do you offer?",
    "We accept debit cards and major credit cards",
    "How to contact customer service agent",
    "please call +65 3333 3333\. Our operating hours are from 9am to 5pm, Monday to Friday"

])

聊天机器人测试

为了检查我们是否已经将我们的对话正确地输入到我们的聊天机器人中,让我们用一个简单的输入语句“支付方式”来测试一下。

response = bot.get_response ('payment method')
print(response)

聊天机器人给我们的回复是:

这种回应正是我们想要的。

我们将创建一个 while 循环到,使我们的聊天机器人能够连续响应我们的每个查询当我们收到用户的‘拜拜’或‘拜拜’声明时,我们将结束循环并停止程序。

name = input('Enter Your Name: ')print ('Welcome to Chatbot Service! Let me know how can I help you')while True:

    request = input(name+':')

    if request=="Bye" or request=='bye':
        print('Bot: Bye')
        break
    else:
        response=bot.get_response(request)
        print('Bot: ', response)

让我们试一试…

Jupyter 笔记本中的聊天机器人演示(GIF 由作者提供)

恭喜你!您刚刚创建了您的第一个工作聊天机器人!

语料数据训练

当然,你会希望你的聊天机器人能够在我们刚刚输入的对话之外进行更多的对话。)—这样的话,我们需要进一步训练我们的聊天机器人。

幸运的是,这个任务对我们来说已经简化了。通过使用包中可用的英语语料库数据,我们可以快速训练我们的聊天机器人以更“像人类”和更智能的方式与我们交流。

注: 如果您在运行语料库训练时遇到问题,请将此chatterbot _ corpus文件夹复制到错误信息中指定的文件目录。

只要运行下面的代码,你的聊天机器人就会被训练在以下范围内进行对话: AI、botprofile、计算机、对话、情感、食物、八卦、问候、健康、历史、幽默、文学、金钱、电影、政治、心理、科学、体育&琐事。

from chatterbot.trainers import ChatterBotCorpusTrainertrainer = ChatterBotCorpusTrainer(bot)trainer.train('chatterbot.corpus.english')

让我们测试一下我们的聊天机器人现在是否变得更聪明了…

语料库数据训练后的聊天机器人测试(GIF 作者)

是啊!它变得更聪明了——它现在可以给你讲笑话了…

预处理输入

ChatterBot 附带了几个内置的预处理器,允许我们在让 Bot 的逻辑适配器处理语句之前清理输入语句。

清理使得我们的输入语句更容易被聊天机器人阅读和分析。它从输入语句中删除了干扰文本分析的“干扰”——例如额外的空格、Unicode 字符和转义的 html 字符。

现在,我们将在 chatbot 实例中包含预处理程序,并使用下面的代码重新运行 chatbot 实例。

bot = ChatBot('Buddy',
             read_only = True,
             preprocessors=['chatterbot.preprocessors.clean_whitespace',                            'chatterbot.preprocessors.unescape_html',                          'chatterbot.preprocessors.convert_to_ascii'])

然后,重新运行聊天机器人,你可以看到我们对你是谁你是谁得到了相同的回应。

低信心应对

除此之外,我们还可以配置我们的聊天机器人,如果用户不理解输入内容,它会给出默认响应:

对不起,我不明白。我还在学习。请联系abc@xxx.com寻求进一步帮助

让我们将低置信度响应包含到我们的聊天机器人实例中,并重新运行聊天机器人实例。

bot = ChatBot('Buddy',
             logic_adapters = [
                 {
 **'import_path': 'chatterbot.logic.BestMatch',
                     'default_response': 'I am sorry, I do not understand. I am still learning. Please contact** [**abc@xxx.com**](mailto:abc@xxx.com) **for further assistance.',
                     'maximum_similarity_threshold': 0.90**
                 }
             ],
             read_only = True,
             preprocessors=['chatterbot.preprocessors.clean_whitespace',
'chatterbot.preprocessors.unescape_html',
'chatterbot.preprocessors.convert_to_ascii'])

然后,重新运行聊天机器人,让我们尝试从一个意外的输入中获得响应——当聊天机器人不理解一个语句时,它会用 default_response 进行回复。

聊天机器人响应意外输入(图片由作者提供)

恭喜你!您已经使用 Jupyter notebook 成功构建了一个聊天机器人。

这里是 的链接,我的 Github 为 Jupyter 笔记本上的这个。

(b)在终端运行聊天机器人

注: 如果您直接来到本节(跳过了 (a)使用 Jupyter notebook 构建聊天机器人),那么请确保您已经安装了该节中提到的所有必需的库和包,然后再继续在终端中运行聊天机器人。

我们将使用上面的 Jupyter 笔记本编写脚本,运行上面的步骤,并根据用户指定的对话文件执行聊天机器人训练,然后查看我们的聊天机器人的运行情况...!

运行……的完整脚本和指令

你可以在这里下载我的完整脚本,你可以马上用它来训练和运行你的聊天机器人!

  1. 创建一个 training_data 文件夹,将你想要训练的所有对话保存在文本文件中。chatbot_training.py 脚本将读取 training_data 文件夹中的所有文本文件。

文本文件中的对话应该每行输入一句话:

2.运行聊天机器人 _ 培训. py 。你将被要求选择是否要用英语语料库数据训练聊天机器人——选择 YN

选择Y——你的聊天机器人将被训练在以下范围内进行对话: AI、机器人简介、计算机、对话、情感、食物、八卦、问候、健康、历史、幽默、文学、金钱、电影、政治、心理学、科学、体育&琐事。

3.然后,运行聊天机器人. py 到启动聊天机器人。输入一些对话,测试它是否正确响应。

Tadaa…这就对了!您已经完成了聊天机器人训练,并在终端中运行它。

(c)使用 Flask 将聊天机器人部署为网络应用程序

注意: 如果您直接进入本节(跳过了 (a)使用 Jupyter notebook 构建聊天机器人),那么请确保您已经安装了该节中提到的所有必需的库和包,然后再继续使用 Flask 将聊天机器人部署到 web 应用程序。

我们将我们的聊天机器人部署到一个 web 应用程序,以便客户可以使用它。

要在 web 应用程序上运行我们的聊天机器人,我们需要为我们的应用程序找到一种接收输入数据和返回数据的方法。我们可以用任何我们想要的方式做到这一点——HTTP 请求、web 套接字等等。

在聊天机器人常见问题页面上有一些现有的例子告诉我们如何做。我将向您展示如何使用 Flask 部署 web 应用程序。

从 my Github 下载示例代码,编辑模板文件夹中的index.html文件和静态文件夹中的 style.css 文件。如果您只是想在 web 应用程序上测试聊天机器人,请让文件保持原样。

之后,让我们运行 web_app.py.

这将我们的聊天机器人部署到位于 http://127.0.0.1:5000/ 的本地服务器上

启动您的 web 浏览器,并转到上面的 URL 来启动您的聊天机器人。

结论、改进建议…接下来是什么?

(再次)祝贺你!您已经成功构建了第一个业务聊天机器人,并使用 Flask 将其部署到 web 应用程序中。我希望,聊天机器人在回答你训练过的一些标准商业问题方面做得很好。

为了进一步提高聊天机器人的性能,你可以做的一件事就是编辑一份你的客户到目前为止发布的常见问题列表,提供常见问题的答案,然后在你的聊天机器人上训练他们。

为什么有些聊天机器人不争气?一些聊天机器人失败了,仅仅是因为对企业提出的标准问题和要求没有得到充分的分析,结果聊天机器人没有得到所需的培训。训练和提高你的聊天机器人是一个持续的过程,就像人类学习新技能和知识一样。一旦学会了这些技能,它们就内置在聊天机器人中,聊天机器人不需要重新培训,除非你的业务增长。

接下来,您可以考虑将您的聊天机器人部署到您选择的平台即服务(PaaS)上,它可以完全从云中托管和运行您的 web 应用程序。你可以考虑的一个流行的免费 PaaS 是 Heroku 。

谢谢你读了这个故事!关注我的 medium 了解更多关于如何使用 DIY 机器学习来发展业务的技巧。