一种解决多元优化问题的实验设计方法
响应值未知时寻找最佳输入参数
在这篇文章中,我将描述我在未知响应值的多元优化问题中寻找最大值的经历。我在滑铁卢大学参加的实验设计研究生课程的期末项目中研究过这个问题
语境
通常,在科学和工程环境中,有时甚至在商业环境中,我们会遇到一些定量问题,我们知道输入值及其范围,并得到相应的输出(响应)值,但不知道它们之间的关系。当可以安全地假设该关系是线性的时,我们可以拟合多元线性回归模型并确定该关系,并使用它来找到响应变量的最佳值或确定其对输入变量的敏感度。在非线性设置中,机器学习技术可以用来为我们做曲线拟合工作。
另一方面,如果我们只知道每个输入变量可以变化的范围,但没有提供响应变量值,并要求我们找到将导致响应变量最佳值的组合,那么我们就面临着一个困难的挑战。为了最有效地达到最佳值,我们应该进行多少次实验,以什么样的顺序进行?根据我对这个问题的研究,这个简单的问题可能会变得很难回答。这是问题陈述:
问题陈述
与混凝土相比,沥青在铺路方面有一些优势,比如初期成本较低,噪音也较低。然而,缺点之一是它的强度较低。在这项研究中,我们必须优化沥青的成分,以最大限度地提高其强度(抗压强度——响应变量)。
我们有三个输入变量及其变化范围:
-
𝑥1(水灰比):0.28–0.4
-
𝑥2(粗骨料粒径):9.5-12.5 毫米
-
𝑥3(空隙率):15%-25%
我们的目标是找到最大化𝑦(抗压强度或简单的强度)的𝑥1,𝑥2 和𝑥3 的设置。
请注意简单优化问题和这个问题的区别:
在常规优化问题中,我们已知输入变量和相应输出值的组合,但我们只知道输入变量的范围,而不知道响应变量的信息。
让我们考虑一下业务背景:这里的实验意味着,选择水灰比、粗骨料尺寸和空隙率的特定组合,使用该组合制造沥青,然后在材料测试实验室中确定最终沥青的抗压强度。我们的预算有限,因此不能做我们想做的那么多实验。例如,我们可以用这些输入变量的各种组合做一千个实验,然后报告产生强度最大值的组合吗?我们可以,但这将非常昂贵(想想安装成本、员工工资、原材料、电力……)。此外,这种方法将被视为蛮力,应该只在紧急情况下或所有其他方法都失败时使用。
在这种情况下,有一种叫做“实验设计”的统计学分支可以帮助我们。我们的时间和资源有限,必须想出一个好的解决方案(如果不是最好的)来解决一个基于合理的数学原理的问题。我现在一步一步地描述实验设计方法。
实验设计法
首先,我在 0.0-5.0 的范围内调整了所有三个变量,以便于实验的设计。我这样做是为了确保不同输入变量的大小不会影响以后的回归系数。换句话说,如果变量 1 在 0-1 之间变化,变量 2 在 0-100 之间变化,对我们来说应该没有关系。
我们不知道 y 和(x1,x2,x3)之间关系的本质。它可能是一次函数,二次函数,或者其他我们不知道的函数。我们所知道的是输入变量可以变化的范围。该关系在变量空间的某些部分可以是近似线性的,而在其他部分可以是非线性的。
由于我们事先没有这些信息,所以从一个小的输入变量空间开始,在这个区域进行一些实验,然后根据我们在这个区域的发现移动到整个变量空间的其他区域是有意义的。这种实验方法被称为顺序策略。我们从小处着手,并在有希望的方向上增加赌注,而不是从大处着手(即,一次性承担整个可变空间)
实验设定 1
我做了第一组实验,所有三个(x1,x2,x3)值都在[0,1]区域。我们注意到,这些是换算值,输入参数的实际值可以通过再次将换算值转换为未换算值来找到。在这个区域,我进行了所谓的 2 +4 中心点实验。这包括从该区域仔细选择 12 种(x1,x2,x3)组合,并测试由这些组合制成的沥青的抗压强度。你可以在这里了解更多 2 +4 方法 。
你可能会问我,我是如何在这些实验中找到抗压强度的。我是从教授提供的基于 excel 的计算器中得到的!在现实世界中,材料科学家将在实验室进行这些实验,并确定这些值。别无选择!
所以实验组 1 的设计如下:
实验装置 1 的设计
因子及其范围:x1(0.00–1.00)、x2(0.00–1.00)和 x3(0.00–1.00)
2 (1 次重复)+ 4 个 CP,总共 12 次运行
动机:如前所述,我们现在不知道我们在参数图上的位置,我们是在包含最佳值的区域,还是在斜坡或山脊上。所以我们从参数空间的一个小区域的实验开始,拟合一个模型来检查,然后继续。
实验表如下所示。这样的表格可以在 Minitab 或 Python / R 中轻松生成:
2 +4 CP 设计(图片由作者提供)
我在 Minitab 中做了回归,但同样,它可以在任何标准软件包中完成。这 12 个实验的回归结果如下图所示:
2 + 4 CP 设计的回归结果(图片由作者提供)
正如我们所观察到的,由于 Ct Pt 变量具有相当高的 p 值(0.866),曲率在该区域并不显著。此外,交互术语如 x1x2、x1x3 等也不重要。因此,我去掉了中心点和这些相互作用项。再次运行回归后,结果如下:
去掉中心点和相互作用项后 2 + 4 CP 设计的回归结果(图片由作者提供)
下图显示了该模型的残差图:
y 变量相对于 x1 和 x2 的等值线图如下所示:
去掉中心点和交互项后的 2 + 4 CP 设计的等高线图(图片由作者提供)
强度相对于 x1 和 x2 的等高线图表明我们在一座山的斜坡上(图形山),并且我们应该在最陡的斜坡上上升以快速到达最佳点。
实验组 1 的结论
因此,实验组 1 的结论如下:
-
x1、x2 和 x3 是重要的,如 p 值所示,而相互作用项不重要,并且在该区域也没有曲率
-
x1 在该区域具有最大的影响,如与其他变量相比相对较高的斜率所示(0.4538)
-拟合似乎很好:高𝑅(调整后)=98.98%,残差无异常,如上面的残差图所示(残差无非正态性,无异方差)
-很明显,我们在一座山的斜坡上,我们需要沿着最陡的上坡路径在实验区域中移动。
最陡峭的上升路径
从线性回归模型中,我们发现 x1、x2 和 x3 的系数分别为 0.4538、0.1213 和 0.2628。我们使用这些系数来寻找最陡的上升路径。
我们从中心点(0.5,0.5,0.5)开始
影响最大的是 x1,其步长为 1
接下来是 x3 的效果,其步长大小为 1 x 0.2628/0.4538 = 0.579
接下来是 x2 的效果,其步长大小为 1 x 0.1213/0.4538 = 0.267
最陡爬坡路径如下表所示:
最陡上坡路径(图片由作者提供)
点(4.5,2.1,4)是目前为止最陡的上坡的最佳点。要么我们现在已经越过了山顶,要么我们已经越过了山脊。
为了确定函数在这一点的形状,我们以(4.5,2.1,4)为中心点做一组新的实验。
实验装置 2 的设计
实验二还是以(4.5,2.1,4)为中心的 2 + 4 CP 实验。
因子及其范围:x1(4.0–5.0)、x2(1.6–2.6)和 x3(3.5–4.5)
2 (1 次重复)+ 4CP,共 12 次运行
*动机:*我们想了解 y 在(4.5,2.1,4)附近如何变化。如果(4.5,2.1,4)恰好是一圈同心圆的中心点,那么我们已经到达了顶点。否则,我们需要做更多的工作来达到最佳值。
实验组 2: 2 +4 CP 设计(图片由作者提供)
这 12 个实验的回归结果如下图所示:
2 + 4 CP 设计的回归结果(图片由作者提供)
很明显,曲率效应现在很重要,除了 x1x2 之外的相互作用效应并不显著。我们再次看到 x1x3 和 x2x3 的影响并不显著,这表明 x3 可能不会与 x1 和 x2 相互作用,因此可以单独进行优化。*因此,向前看,我将 x3 作为固定值,并进行实验以找到 x1 和 x2 的最佳值。*一旦找到,x3 已被单独优化。
下面的回归拟合没有交互效应 x1x3 和 x2x3:
去掉中心点和相互作用项后+ 4 CP 设计的回归结果(图片由作者提供)
接下来,我通过用轴点和额外的中心点扩充 2 (1 次重复)+ 4 CP 模型来拟合响应面模型。由此产生的设计被称为中心复合设计,有 20 次实验运行,如下表所示:
以点(4.5,2.1,4)为中心的中心复合设计
CCD 帮助我们找到这个区域的函数方程。中心复合设计回归分析产生以下结果:
以(4.5,2.1,4)为中心的 CCD 实验设计的回归结果(图片由作者提供)
以 x1 和 x2 为变量的函数的等值线图如下所示:
以(4.5,2.1,4)为中心的 CCD 实验设计的等高线图—箭头显示 y 最大增加的大致方向(图片由作者提供)
实验组 2 的结论:
由于 x1 的系数为负,x2 的系数为正,所以当 x1 减小而 x2 增大时,y 有可能增大。这通过上面所示的以(4.5,2.1,4)为中心的等高线图得到了证实。这里似乎有一个山脊,我们的移动方向应该是箭头所指的山脊顶部。
实验集 3
我将下一组实验集中在点(4,2.5,4)上,该点位于前面等高线图中所示的箭头处。这是我下一个实验的下一个地点,我在下面描述了它:
实验装置 3 的设计
因子及其范围:x1(3.5–4.5),x2(2.0–3.0),x3 =4.0(固定)
动机:这里的目标是向山脊值递增的方向移动,并检查相邻区域的 y 值如何变化。考虑到响应函数的高度非线性特性,应采取小增量的步骤。
我从 2 (1 次重复)+ 4 CP 开始,并根据对显著曲率的检测改变为响应面设计(CCD),其运行如下所示:
以点(4,2.5,4)为中心的中心复合设计
该集合的回归分析结果如下所示。我删除了不重要的术语,并在此展示了仅包含重要术语的模型:
以(4,2.5,4)为中心的 CCD 回归结果(图片由作者提供)
该区域的等高线图如下所示:
以(4,2.5,4)为中心的 CCD 等高线图—箭头显示 y 最大增长的大致方向(图片由作者提供)
同样,该模式是朝着 x1 的较低值和 x2 的较高值增加的增加脊。因此,下一步是在相邻的 1 阶盒区域进行实验,即 x1 =[3–4]和 x2 =[2.5–3.5]。为了简洁起见,我展示了等高线图来指示接近的方向,而不是详细讨论接下来两个 CCD 实验的结果。这些实验在以下地区进行
4.x1 =[3–4]和 x2 =[2.5–3.5]
5.x1 =[2.5–3.5]和 x2 =[3–4]
6.x1 =[2–3]和 x2 =[3.5–4.5]
从所有这 3 个区域得出的一般结论是,响应面设计更合适,轮廓开始显示接近峰值的模式。这些区域的等高线绘制如下。
区域 4、5 和 6 的 CCD 等值线图——箭头显示了 y 最大增长的大致方向(图片由作者提供)
来自实验组 3 的结论(包括区域 4、5、6 中的 CCD 运行):
现在很清楚,我们可能正在接近一个峰值,下一个逻辑步骤是继续朝着减少 x1 和增加 x2 的方向前进,并移动到下一个区域。
实验集 4
这很可能是峰值区域,我在(2,4,5,4)中心做了一个 CCD
实验装置 4 的设计
因子和范围:x1(1.5–2.5),x2(4.0–5.0),x3 =4.0(固定)
实验四:以(2,4.5,4)为中心的 CCD(图片作者提供)
回归响应和等高线图如下所示:
以(2,4.5,4)为中心的 CCD 回归结果(图片由作者提供)
(2,4,5,4)周围区域的 CCD 等值线图—最佳值区域(图片由作者提供)
很明显,我们已经达到了一个峰值,y 的最大值出现在 x1 = 2 和 x2 = 4.5
现在很清楚,最佳值出现在 **x1 = 2 和 x2 = 4.5 处,**我们现在必须找到 y 值最高的 x3 的值。因为我们发现 x1、x3 和 x2、x3 之间没有交互作用,所以我们可以简单地运行 10 个实验,其中 x1 和 x2 的值为最佳值,x3 在 0.5 和 5.0 之间变化。
下表显示了 10 次试验:
实验确定 x3 的最佳设置(图片由作者提供)
基于这 10 次运行,很明显 y 的全局最优值出现在 x1 = 2、x2 = 4.5 和 x3 = 5(这些是编码值,但是可以通过简单的线性变换容易地解码),并且 y 的值是 9.52
实验顺序图
我所做的一系列实验如下图所示:
为确定最佳设置而执行的一系列实验(图片由作者提供)
驻点描述
我还使用简单的微积分在(2,4,5,4)周围的区域中解析地导出了静止点,以检查最优值集。
最佳点的描述(图片由作者提供)
回归方程给出了 y 的期望值,但也有与之相关的标准差。我是在最佳设置下计算的:
最佳参数设置下抗压强度标准偏差的计算
我们可以使用这个标准偏差来找到抗压强度的置信区间,该置信区间可以反过来用于确定我们可以接受的强度下限,比如 95%置信区间。
结论
简而言之,多元优化的实验设计方法是一种强大的方法,它使用小步前进的原则,并利用未知设计函数在搜索空间中探索最大收益的路径。它帮助我们通过采取这些智能步骤快速找到最佳值,而不是使用在计算和财务上非常昂贵的暴力方法。我用三个参数工作,这有助于可视化算法在做什么。然而,这种技术也可以适用于大规模的多元问题。
我希望我的帖子能引发你进一步探索实验设计的兴趣!
树集合层上的解释器
一种具有决策树优点的新型神经网络层。
由 Unsplash 上的 Pietro Jeng 拍摄
神经网络和决策树都在多个机器学习问题上表现出色。如果我们可以在一个模型中同时获得两者的优点,会怎么样?这就是谷歌研究团队试图在他们名为树集成层:可微性符合条件计算的论文中寻求的东西。
树支持条件计算,即它们能够通过少量节点路由每个样本。这可以带来性能上的好处,增强统计属性,并有助于可解释性。但是树的性能严重依赖于特征工程,因为它们缺乏表示学习的机制。这是神经网络的优势所在,特别是在图像和语音识别问题上,尽管缺乏对条件计算的支持。本文提出了神经网络的一层可加可微决策树,树集成层(TEL),。该层可以插入神经网络中的任何位置,并且可以通过标准的基于梯度的优化方法(例如 SGD)来训练。
可微分决策树
软路由,https://arxiv.org/abs/2002.07772
在经典的决策树中,每个样本在每个节点处被精确地指向一个方向(硬路由),这在损失函数中引入了不连续性。由于不能应用连续优化技术,所以采用贪婪方法来构建树。软树是执行软路由的决策树的变体,即以不同的比例将每个样本路由到左侧和右侧。在这种结构中,损失函数是可微的,并且可以使用基于梯度的优化方法。
但是我们如何对一个特定样本, x, 到达一个叶节点, l 的概率建模呢? 为了到达节点 l ,样本 x 必须访问其所有的祖先节点。并且在每个节点都会以一定的概率发送到左右两个子树。到达节点 l 的总概率是在每个节点移动到包含 l 的子树的联合概率。
样本 x 到达节点 l 的概率
r_i,l(x) 是在节点 i ,样本 x with 将向包含叶子 l 的子树移动的概率。逻辑函数是激活函数的一个普遍选择,但它并不精确地给出 0 或 1。这意味着需要计算所有节点,计算量随着树的深度呈指数增长。继连续和可微分激活函数被提出来解决这个问题:
平滑阶跃激活函数
选择 \gamma 控制硬路由到 0 或 1 的样本数。该函数非常接近逻辑函数。
平滑步长 vs 逻辑函数(1/(1+e^(-6t)):https://arxiv.org/abs/2002.07772
条件计算
为了优化 TEL,可以使用一阶优化方法,例如随机梯度下降(SGD)的变体。梯度的计算随着树的深度呈指数增长,这已经成为一个主要的瓶颈。通过利用上面定义的激活函数及其梯度中的稀疏性来开发有效的前向和后向传播。
**条件正向传递:**在计算梯度之前,需要在树上正向传递。这里,通过丢弃任何子树和随后的计算来利用稀疏性,其中激活函数被硬路由到 0。
**条件反向传递:**反向传递遍历树,用梯度更新每个节点。值得注意的重要观察是,对于值被硬路由到 0 或 1 的任何节点,梯度都是 0。因此,在后向过程中要访问的节点数量甚至低于前向过程中访问的节点数量。这是通过创建节点数量减少的分数树来实现的,从而加快计算速度。
来自论文的实验结果表明,TEL 实现了与梯度增强决策树(GBDT)和密集神经网络(DNN)层竞争的性能,同时导致显著更紧凑的模型。这篇论文非常有趣,因为它采用了一种新的方法将可解释性引入神经网络模型。DNN 中的每个隐藏层学习一个表示,将 TEL 层放在输出层之前肯定有助于理解该表示与输出的直接联系。
- Hazimeh,h .,Ponomareva,n .,Mol,p .,Tan,z .,& Mazumder,R. (2020 年 11 月)。树集合层:可微性满足条件计算。在机器学习国际会议(第 4138–4148 页)。PMLR。
使用经验测试解释回归的偏差-方差权衡
实证模拟可以增强有抱负的数据科学爱好者对统计概念的理解。
偏差-方差权衡是机器学习初学者的基本学习要求,以确保基于样本数据选择最合适的模型。关于这一主题的最常见的在线图表如图 1 所示,它显示了三种类型的误差:偏差、方差和总误差以及它们之间的关系。随着模型复杂性的增加,偏差减少,而方差增加,总误差呈抛物线形状。尽管许多专家对此进行了严谨的论述,但这些解释可以通过一定的实证实验来补充,以帮助学习者对这一概念获得令人满意的直观理解。这篇文章的目的是在计算机上使用随机数据计算偏差和方差。
在我们开始之前,为了一致性和更好的理解,注意某些定义和符号是有用的[1,2]:
**模型的类/族:**线性的、某次多项式的、或其它一些具有确定结构的非线性模型(如 ax2 + bx +c 属于模型的二次族)
**成员模型:**是模型的实例,参数固定。例如,典型的二次方程(3x2 + 7x + 1)就是二次方程族的一员。
**偏差:**是响应变量的观察值(真实值)与拟合响应的期望值之间的差值。它是模型的属性,而不是数据。
**方差:**描述模型的输出如何根据看不见的数据而变化。与偏差一样,偏差-方差概念中的方差也是模型的一个属性。
样本数据挑战
在现实世界中,计算与模型拟合相关的偏差-方差图具有挑战性,原因有两个。首先,我们从来没有超过一个数据集,这就是为什么自举采样变得流行。该技术从单个数据集随机生成许多数据集,这不仅有助于选择正确的模型系列,还可以识别该系列中最合适的模型成员。第二,我们常常把观察值当作真实总体的最具代表性的值。如果一个样本包含几个数据收集偏差[3]并且不具有代表性,那么重复重采样对减少原始样本中的误差作用不大;
虽然我们不能改变现实,但多亏了计算机,我们总是可以创造我们自己的现实,产生合成数据来理解统计概念,并根据经验对它们进行测试。让我们假设输入变量(为简单起见,考虑一个输入变量)和观察到的响应变量之间的关系(在现实世界中我们从来不知道)可以用下面的等式表示(参见 get_y 函数):
import numpy as np
import matplotlib.pyplot as plt
import pandas as pdfrom collections import defaultdictfrom sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeaturesdef get_y(x):
# yes I know, it is complicated; don't ask how I came up with it
y = np.sin(x) + 0.001*(x**4 + 4*x**3 - 20*x**2 + 400)
# adding noise
rand_err = [np.random.normal(0,0.1*abs(i)) for i in y.flatten()]
y = y + np.array(rand_err).reshape(samp_size, 1)
return ydef transform_x(x, order):
poly = PolynomialFeatures(order)
return poly.fit_transform(x)
第二个等式中的最后一项表示均值为零的正态分布噪声。我们首先随机生成一个样本大小为 50 的数据集 X (x_true),并计算相应的 Y 值(y_true + errors)(见图 1)。这代表了我们将用于比较的具有真实(或测试)值的基线数据集。
图 1 输入和输出变量之间的真实关系
现在,我们将其重采样 100 次,以获得总共 100 个样本,每个样本有 40 个数据点,响应变量中添加了随机噪声。我们拟合了次数从 1(线性回归)到 9 众多多项式回归模型。因为只使用了一个变量,所以不存在交互项。下面分享了代码片段
np.random.seed(24)y_pred = defaultdict(list)
y_pred_mean = defaultdict(list)
bias, variance = dict(), dict()range_of_error = dict()nsamp = 100
samp_size = 50# getting a baseline dataset (lets call it true dataset)
x_true = np.linspace(-7, 7, samp_size).reshape(samp_size, 1)
y_true = get_y(x_true)fit_models = ['PolyReg1', 'PolyReg2', 'PolyReg3', 'PolyReg4', 'PolyReg5',
'PolyReg6', 'PolyReg7', 'PolyReg8', 'PolyReg9']for name in fit_models:
# transforming true (test) input for the polynomial model
order = int(name[7:])
trans_x = transform_x(x_true, order = order)
for i in range(nsamp):
# bootstraping sampling with replacement
idx = np.random.choice(samp_size, samp_size)
x = x_true[idx]
y = get_y(x)
poly = PolynomialFeatures(order)
x = poly.fit_transform(x)
model = LinearRegression()
model.fit(x, y)
ytemp = model.predict(trans_x) # temporary variable
y_pred[name].append(ytemp.flatten())# to numpy array
y_pred[name] = np.array(y_pred[name])
y_pred_mean[name] = y_pred[name].mean(axis=0)# bias of the estimator
# E((f(x) - E(y_fit))**2)
# for each single point from all datasets
bias[name] = (y_true.flatten() - y_pred_mean[name])**2
# average over all data points
bias[name] = bias[name].mean()
range_of_error[name] = (y_true.flatten() - y_pred[name])**2
range_of_error[name] = range_of_error[name].mean(axis=1)
# for each point from over all datasets
# indirect formula
#variance[name] = ((y_fit_mean[name] - y_fit[name])**2).mean(axis=0)
# standard formula
variance[name] = y_pred[name].var(axis=0)
# average over all data points
variance[name] = variance[name].mean()
结果
图 2 显示了简单模型(线性回归)在解释训练数据时表达性较差,这需要更高阶的多项式来获得更好的性能。当我们从简单模型转向复杂模型时,在 6 阶多项式的误差再次增加之前,5 阶多项式似乎为模型提供了最佳“拟合”。虽然并不完美,但这是偏差-方差计算的传统表示。
图 2 偏差方差权衡;来源:图片由作者提供;注 : PolyRegK:第 k 阶多项式回归。为了更好地说明,这些值已针对所有模型的最大值进行了标准化。
然而,进一步的过度拟合实际上减少了误差、偏差以及方差,这似乎是一个双重下降的观察结果,这是数据科学界正在讨论的话题[4,5]。双下降现象表明,过拟合的缺点可能仅在模型复杂性达到一定水平时出现,并且极高水平的复杂性不一定会恶化模型性能。
图 3 显示了不同模型的分布。绿色曲线显示真实数据,而红色曲线描述模型对所有数据集的预期(平均)预测。灰色散点图显示了每个数据集的预测值。正如我们所见,高阶多项式的偏差较低(红色曲线接近绿色曲线),但对于某些多项式,分布(灰色分散区域)变得更宽。
图 3 不同模型相对于真实模型的性能
测试误差范围
我们还可以通过使用我们的合成数据集来检查每个模型的误差范围。从图 4 中可以看出,均方误差的范围是真实数据集(所有数据集通用)和每个数据集的拟合值之间的差异。虽然每个模型的平均值反映了图 1 的值,但它显示了测试误差如何从一个数据集变化到另一个数据集。红色和蓝色虚线显示,对于某些数据集,“差”拟合模型可能比更具表现力的模型具有更少的测试误差。没有足够的高质量样本,单一数据集可能导致模型选择不当,这强调了使用单一数据集的多个变量生成偏差-方差曲线的重要性。
请注意,箱线图中的方差(分布)可能看起来是相关的,但它在数学上不同于偏差-方差图中的方差。在这里,它是基于不同数据集的预测误差的分布,与偏差-方差权衡不同,方差描述偏差的分布,是模型的一个属性
图 4 均方误差范围;来源:图片由作者提供
结论
这篇文章的目的是帮助初学者,包括我自己,通过经验模拟对偏差-方差概念有一个更直观的理解。偏差-方差权衡是一个统计学术语,像统计学中的所有其他概念一样,适用于预测的“预期”结果,而这种结果不能仅由一个样本数据集产生。Bootstrapping 技术可用于重现给定数据集的变量,并反复拟合模型以计算预期预测值以及预测值与观测值的差异。
虽然我使用回归进行说明,但是这个概念也应该适用于分类问题。鼓励读者进一步探索最近关于偏差-方差误差曲线双下降的发现[4,5],其中随着模型复杂性的增加,偏差-方差权衡可能不再成立。
参考文献
[1]威廉·科恩,机器学习中的偏差-方差 (2008),机器学习,10–601 课堂讲座,CMU。
[2]A . Singh 和 Eric Xing,偏差方差权衡和模型选择 (2012),机器学习 10-701/15-781,CMU
https://en.wikipedia.org/wiki/Sampling_bias
[4] P. Nakkiran,G. Kaplun,Y. Bansal,T. Yang,B. Barak,I. Sutskever,Deep Double Descent(2019),OpenAI,
[5]安德鲁·杨,每个数据科学家都应该知道:偏向-方差权衡一般化是错误的 (2021),对数据科学而言
70 年空间探测数据的探索性分析
探索性数据分析
人类在太空最初 70 年的迷人见解和引人入胜的故事
美国宇航局在 Unsplash 拍摄的照片
简介
探索性数据分析是任何数据科学家工具集中的一项关键技能。用数据讲述故事的能力对于激励决策者、激发对某个话题、领域或主题的兴趣至关重要。毕竟,我们都喜欢好故事。
为了说明它的威力,我对 70 年的太空旅行数据进行了探索性分析。我想分享一些令人着迷的见解,这些见解一定会让你震惊和惊喜。有无数种方法来分析数据进行探索,但最终为了防止你迷失方向,你应该始终牢记你探索的目的。
在整篇文章中,我用宇航员这个词来指代任何去过太空的人
接近
为了让读者了解,我从数据中提取了一些见解,并以“前 10 名”、记录和显著成就的形式表达出来,从而构建了我的分析。
为了提供一些背景信息,我制作了一个太空任务的时间序列。我以此开始,来描绘一幅太空旅行在过去 70 年中是如何发展的画面。
尽管火箭、卫星和公司是太空探索的重要组成部分,但我的大部分分析还是集中在宇航员本身的成就上。来自这些数据的一些最令人着迷的见解与你可能认为人类不可能取得的成就有关。
重要的是要记住,人们通常会更好地与关于他们的故事联系起来;任何数据科学家在进行探索性数据分析时,如果他们希望讲述令人信服的故事,都应该记住这一点。
注意:所有的记录都与撰写这篇文章的时间有关。
数据
在我的探索中,我使用了两个数据集,它们都是公开的。一个是太空任务级别,另一个是宇航员级别。重要的是要记住,任何数据都不应该用大写字母“D”来表示,任何来自数据的见解都应该进行感官检查。通过这样做,我发现了一些数据质量问题。
宇航员:2020 年 1 月 15 日前参加过太空任务的所有宇航员。数据来源是 NASA、Roscosmos 和好玩的网站。数据集是任务宇航员级别的,包含每个宇航员的详细信息和特定任务的详细信息。它由 517 个独特的任务组成,假设一个单一的任务可以通过连接任务年份、任务名称和 ascend shuttle 来识别。
任务 :这是从网上抓取的任务级数据。它包括了自 1957 年开始以来的所有太空任务。详细介绍了任务的各个方面,如成本、火箭、发射时间、位置等。飞行任务数据包含 4,324 次飞行任务,其中 3,879 次是成功的。
宇航员数据中的任务总数与任务数据之间有很大的差异。对此的一个解释可能是因为任务数据中捕捉到的许多追踪都是无人驾驶的。
工具
我使用 Python 进行所有的数据探索。许多数据争论都是在 NumPy 和 Pandas 图书馆的帮助下进行的。
对于数据可视化,我使用了 Matplotlib 和 Seaborn。我不会在这篇文章中分享代码片段。但是,我会在 GitHub 中提供完整的端到端代码。
太空探索背景
作者图片
自 1957 年开始太空探索以来,太空任务的数量逐年上升,1971 年达到 119 次的高峰。它保持在每年 97 次以上,直到 1979 年下降到 49 次。直到 2018 年,它才再次恢复,当年达到了 117 次任务。是什么导致了这次下跌?
以下是一些可能性:
1971 年——联盟 11 号的机组人员在脱离空间站礼炮 1 号后遇难。
1975 年——美国和苏联联合进入太空,引发了太空竞赛的结束。
1986 年——挑战者号航天飞机发射 73 秒后发生灾难,机上 7 名机组人员全部遇难。
2018 年的复兴可能是由企业对太空探索兴趣的不断扩大所驱动的。像 SpaceX 和中国 CASC 这样的公司已经因其在该领域的成就而成为头条新闻。
仅在 2020 年 1 月,CASC 就完成了 19 次发射,SpaceX 完成了 14 次。
成为一名宇航员需要多久?
从选择(训练开始)到第一次任务的平均时间约为 6.3 年。75%的宇航员在最初选择的 8 年内完成了他们的第一次任务,特别是 25%的宇航员在 4 年内完成了任务。
作者图片
太空行走者
也许比月球漫步更酷,太空行走指的是在地球大气层以外的交通工具中度过的时间。它被记录为宇航员数据中的舱外时间。
作者图片
Anatoly Solovyev,现已退休的俄罗斯苏联宇航员,进行了 16 次太空行走,他保持着太空行走次数的记录。阿纳托利的舱外时间似乎存在一些数据质量问题。在一次任务中,他的时间记录大于他在所有任务中的总时间。这就是为什么不完全相信你得到的任何数据是至关重要的!
因此,我无法从他最长的太空行走或太空行走总时间的数据中得出任何见解。他的官方记录是 82 小时。
阿纳托利·索洛维耶夫来源
阿纳托利是一名军事指挥官;他最后一次任务是在 1997 年。一想到在太空行走时间最长的人是军人,就觉得很可怕。他在上面做什么?
太空长老
目前最年长的太空行走者是帕维尔·维诺格拉多夫,他在 60 岁时进行了太空行走,累计时间为 6.62 小时。如果你认为宇航员通常年轻健康(嗯,不到 60 岁),你并不孤单。
作者图片
首次执行任务的宇航员平均年龄为 39 岁,四分之一的宇航员年龄超过 43 岁。四分之一的宇航员在第一次任务中年龄不到 31 岁。这看起来不像是年轻人的游戏。
记录:最老的太空旅行者是小约翰·h·格伦,他离开地球大气层时 77 岁。
这张照片归功于美国国家航空航天局。
在轨道上穿梭
国际空间站是在轨道上执行任务最多的航天飞机。任务数在 125 左右。这是和平号空间站任务次数的两倍多,该空间站由苏联运营,于 2001 年解散。
作者图片
国际空间站是一个绕地球轨道运行的大型宇宙飞船。它绕行一周大约需要 90 分钟,速度大约为每小时 17500 英里。美国宇航局目前使用该飞行器来了解人们如何在太空中生活和工作。顾名思义,几个国家合作维护和使用空间站。相对而言,这就解释了为什么对它的访问如此之多。
空间站的体积相当于一栋五居室的房子(或两架波音 747 飞机)。
点击这里了解更多关于国际空间站的信息。
礼炮 7 号:礼炮 7 号有 13 次任务,最后一次是在 1985 年。空间站最终坠毁在地球上。
我们的数据表明,在所有在轨航天器任务中,有两次爆炸。事实上,这只是一次爆炸:1986 年的挑战者号灾难。field ascend 航天飞机存在一些数据质量问题,1985 年挑战者号一半的机组人员乘坐了不同的航天飞机。
图片由美国宇航局拍摄:号许可【1986 年挑战者号灾难
单次任务在太空停留时间最长
这个奖颁给了瓦列里·波利亚科夫,他在太空中度过了 10,000 个小时(相当于单程 14 个月)。他是前宇航员,这次旅行是在和平号空间站上进行的。
作者图片
使命的故事
美国在记录的太空任务总数中领先,大约有 283 次。这比俄罗斯、日本和加拿大的任务总和还要多,它们是下一个最有竞争力的国家。
失败:美国海军的任务失败率最高,在其 17 项任务中高达 82%。很有可能,虽然他们已经掌握了海洋,但他们完全超出了太空的深度。另一种可能是,他们对自己的表现要求更高。
作者图片:方格条代表任务数量,实线代表失败率
任务总数和失败率之间有微弱的负相关(-0.26)。进一步研究是什么驱动了成功的太空任务将会很有趣。
更多战绩
第一个进入太空的人:第一个进入太空的人是尤里·加加林,他是苏联空军飞行员,于 1961 年遨游太空。尤里实现这一飞跃时才 27 岁,在太空旅行者的年龄中,他排在倒数第 25 位。
图片由[RV 1864](https://www.flickr.com/photos/summer1978/18699907011/in/photolist-uurURR-dzCg8c-9ABkZi-f468mg-bAm8Z1-DNSjdt-4unfG4-2dNUS2s-XraPVr-288N7tE-9z6PY1-UBdyen-8VGDJD-9xMBK9-MZEvCN-dwERLu-srbeQu-in6ohs-f7bYPM-uHrLn-ajDGGA-2aZX5oA-czqSiy-a5qd97-26k7noA-27eWiD1-fME5Dm-a5nkrH-4ESQpE-2ixsEPw-2iHgMi7-2jw1UoA-tf8Emu-2jw32Bs-2jQwEdQ-GjnrDM- 8tfKrx-2jFxe5L-2jcpVqF-2jKXocg-AYuHHf-f4kV2u-potVBA-4VKdGR-ruwZrP-7xMx5q-9xKGte-f46CnM-3JZUPU-f46DjR)T2 授权:尤里·加加林
第一位进入太空的女性:瓦伦蒂娜·捷列什科娃是第一位也是最年轻的进入太空旅行的女性。1963 年,26 岁的她在东方 6 号上独自执行任务。
图片由詹姆斯·乔尔 授权拍摄:瓦伦蒂娜·捷列什科娃
Svetlana Svitskaya 是第二位进入太空的女性,也是第一位进行太空行走的女性。在 1984 年前往礼炮 7 号的任务中,她完成了 3.58 小时的行走。她当时 36 岁。
另一个值得一提的是 Kathryn D. Sullivan,她在同年进行了 3.45 小时的太空行走,成为第一位在太空行走的美国女性。
进一步分析
任务成本:看看任务成本的趋势会很有见地。有很多缺失的数据,并且该字段极其混乱,成本用字符串表示。即使在尝试将它们转换成 floats 之后,仍然有几个实例会产生异常。
为了进一步分析,我想生成一个每年任务平均费用的时间序列。由于所有的缺失值,只有一个样本的成本是可用的,因此我推断人口平均在 95%的置信区间。
预测模型:并不是所有的太空任务都是成功的。失败的原因大概有一些共性。也许可以用任务数据做一些预测模型,以了解是什么驱使任务成功或失败。我的数据中没有足够的特征来生成有用的模型。然而,也许我可以通过获得更多的任务数据来扩展分析。或者甚至利用数据集中的一些高基数字段进行特征工程。
最后的想法
我可以从许多不同的方向进行分析。然而,我把大部分分析集中在人身上,因为我相信这是最引人注目的故事的来源。
🚀我已经创建了一个活页夹,所以你可以用这个笔记本进行实验请点击这里查看这个笔记本!
https://www.linkedin.com/in/john-adeojo/
使用 Python 3 从 Twitter API v2 收集用于学术研究的推文的广泛指南
实践教程
从设置、访问端点到保存以 CSV 格式收集的推文的一步一步的过程。
目录:
- 介绍
- 开始的先决条件
- 不记名代币
- 创建标题
- 创建 URL
- 连接到端点
- 把所有的放在一起
- 将结果保存到 CSV
- 循环请求
1.介绍
2020 年底,Twitter 推出了全新构建的 Twitter API。Twitter API v2 提供了更多您可以提取和分析的特性和数据、新的端点和许多功能。
随着新 API 的引入,Twitter 也为学术界引入了一个新的强大的免费产品:学术研究产品 track 。
该路线允许免费访问完整存档搜索和其他 v2 端点,每月的推文量上限为 10,000,000 条!如果你想知道你是否有资格进入赛道,请查看这个链接。
我最近在卡耐基梅隆大学从事一个数据分析研究项目,利用本专题提供的能力,作为一名研究人员,它给你的力量是令人兴奋的!
然而,由于 API 的 v2 是相当新的,如果您在收集数据进行研究的过程中遇到问题,那么存在的资源会更少。
因此,在本文中,我将一步一步地介绍从设置、访问端点到保存以 CSV 格式收集的 tweets 以供将来分析使用的过程。
本文将使用仅适用于学术研究跟踪的端点(全存档搜索端点),但是本指南中的几乎所有内容都可以应用于适用于所有开发人员帐户的任何其他端点。
如果您没有访问完全存档搜索端点的权限,您仍然可以使用最近搜索端点来遵循本教程。
建议您在阅读本文时使用 Jupyter 笔记本,这样每个代码片段都可以在单独的单元格中运行。
2.启动的先决条件
首先,我们将为本指南导入一些基本的库:
为了能够向 Twitter API 发送您的第一个请求,您需要有一个开发人员帐户。如果你还没有,可以在这里申请一个! (别担心,这是免费的,你只需要提供一些你打算从事的研究的信息)
获得批准的开发者帐户了吗?太棒了!
你所需要做的就是创建一个项目,并通过开发者门户连接一个应用程序,我们就可以开始了!
- 转到开发者门户仪表板
- 使用您的开发者帐户登录
- 创建一个新项目,给它一个名字,一个基于你想要实现的目标的用例,以及一个描述。
新项目页面截图
4.假设这是你第一次使用,请选择“创建新应用”并为你的应用命名,以便创建新应用。
为你的应用程序选择一个名称
如果一切顺利,您应该能够看到包含您的密钥和令牌的页面,我们将使用其中一个来访问 API。
图片也取自 Twitter 开发团队创建的这个分步指南。
3.不记名令牌
如果你已经走到这一步,**恭喜你!**您有资格从 API 发送您的第一个请求:)
首先,我们将创建一个 auth() 函数,该函数将具有来自我们刚刚创建的应用程序的“不记名令牌”。
由于这个不记名令牌是敏感信息,你不应该与任何人分享它。如果你和一个团队一起工作,你不希望任何人能接触到它。
因此,我们将把令牌保存在一个“环境变量”中。
有很多方法可以做到这一点,你可以看看这两个选项:
环境变量。env 与 Python利用 Python 中的环境变量
在本文中,我们将在代码中运行这一行来设置一个 “TOKEN” 变量:
os.environ['TOKEN'] = '<ADD_BEARER_TOKEN>'
只需将 Twitter 上的******替换为您的不记名令牌,运行该函数后,删除这两行。如果这种方法有任何错误,请尝试上面列出的任何链接。
现在,我们将创建我们的 auth() 函数,它从环境中检索令牌。
4.创建标题
接下来,我们将定义一个函数,它将获取我们的承载令牌,传递它以进行授权,并返回我们将用来访问 API 的头。
5.创建 URL
现在我们可以访问 API 了,我们将为将要使用的端点和要传递的参数构建请求。
上面定义的函数包含两部分:
A.搜索 _url:
这是我们想要访问的端点的链接。
Twitter 的 API 有很多不同的端点,下面是在撰写本文时可以提前访问的端点列表:
撰写本文时存在的一些早期访问端点
您还可以在这个链接中找到关于每个端点的完整列表和更多信息。
对于这篇文章,因为它是针对可能试图从 Twitter 的新产品中受益的学术研究人员,我们将使用 全存档搜索端点 。
B.查询参数:
端点提供的参数,我们可以使用这些参数来定制我们想要发送的请求。
每个端点都有不同的参数,我们可以传递给它,当然,Twitter 的文档中有每个端点的 API 引用!
例如,对于我们在本文中使用的全存档搜索端点,您可以在这里的 API 参考页面的**“查询参数”**部分下找到查询参数列表。
完整归档端点 API 文档中的查询参数示例屏幕截图
我们可以将上面函数中的查询参数分解为三个部分:
该端点参数的简单分解
1.前 4 个参数是我们控制的参数
'query': keyword,
'start_time': start_date,
'end_time': end_date,
'max_results': max_results,
2.接下来的 4 个参数基本上是我们指示端点返回更多信息,这些信息是可选的,默认情况下不会返回。
'expansions': 'author_id,in_reply_to_user_id,geo.place_id',
'tweet.fields': 'id,text,author_id,in_reply_to_user_id,geo,conversation_id,created_at,lang,public_metrics,referenced_tweets,reply_settings,source',
'user.fields': 'id,name,username,created_at,description,public_metrics,verified',
'place.fields': 'full_name,id,country,country_code,geo,name,place_type',
3.最后,“next_token”参数用于获取下一页结果。参数中使用的值直接从 API 提供的响应中提取。如果存在比每个请求的上限更多的结果,我们将在本文中对此进行更多的讨论。
'next_token': {}
现在我们知道了 create_url 函数的作用,有几个重要的注意事项:
- 所需端点:
在全存档搜索端点的情况下,query参数是发出请求**所需* *的唯一参数。请务必查看您正在使用的端点的文档,以确认哪些参数必须存在,这样您就不会遇到问题。
- 查询参数:
查询参数是您放置想要搜索的关键字的地方。
查询可以简单到搜索包含单词“xbox”的 tweet,也可以复杂到(xbox europe)或(xbox usa),返回包含单词 xbox AND europe 或 xbox AND usa 的 tweet。
此外,可以使用搜索运算符定制查询。有很多选项可以帮助你缩小搜索结果的范围。我们有望在另一篇文章中更深入地讨论操作符。现在,你可以在这里找到构建查询操作符的完整列表。
带有操作符的简单查询示例: “xbox lang:en”
- 时间戳:
Twitter 用于时间戳的结束时间和开始时间格式是
YYYY-MM-DDTHH:MM:ssZ(ISO 8601/RFC 3339)
所以一定要把日期转换成这种格式。如果你不确定如何做,这是一个很好的时间戳转换器一定会有帮助。
- 成绩卷:
一个请求返回的搜索结果数量目前限制在 10 到 500 个结果之间。
现在你可能会问,我怎么能得到超过 500 个结果呢?这就是next_token和分页发挥作用的地方!
答案很简单:如果您的查询存在更多结果,Twitter 将返回一个唯一的 next_token ,您可以在下一次请求中使用它,它将为您提供新的结果。
如果您想要检索您的查询中存在的所有 tweet,您只需使用每次收到的新next_token不断发送请求,直到不存在 next_token 为止,这表明您已经检索了所有 tweet!
希望你不会感到太困惑!但是不要担心,当我们运行我们刚刚创建的所有函数时,就会很清楚了!
6.连接到端点
现在我们已经有了想要的 URL、头和参数,我们将创建一个函数将所有这些放在一起并连接到端点。
下面的函数将发送“GET”请求,如果一切都正确(响应代码 200),它将以“JSON”格式返回响应。
注意: next_token 默认设置为**【无】**,因为我们只关心它是否存在。
7.把所有的放在一起
现在我们已经有了所有需要的函数,让我们测试一下把它们放在一起创建我们的第一个请求!
在下一个单元格中,我们将设置我们的输入:
- 来自 API 的 bearer_token 和 headers。
- 我们将寻找包含单词“xbox”的英语推文。
- 我们将寻找 2021 年 3 月 1 日至 31 日之间的推文。
- 我们只想最多返回 15 条推文。
现在我们将创建 URL 并从 API 获得响应。
Twitter API 返回的响应以 JavaScript 对象符号“JSON”格式返回。
为了能够处理它并分解我们得到的响应,我们将使用我们之前导入的 python 的编码器和解码器。你可以在这里找到更多关于库的信息。
如果从以下代码返回的响应是 200 ,则请求成功。
url **=** create_url(keyword, start_time,end_time, max_results)json_response **=** connect_to_endpoint(url[0], headers, url[1])
让我们使用这个 JSON 库函数以可读的格式打印响应
print(json.dumps(json_response, indent=4, sort_keys=True))
现在让我们来分解返回的 JSON 响应,响应基本上是作为 Python 字典读取的,键要么包含数据,要么包含更多字典。最上面的两个键是:
A.数据:
字典列表,每个字典代表一条推文的数据。如何检索第一条推文创建时间的示例:
json_response['data'][0]['created_at']
B.元:
关于我们发送的请求的属性字典,我们通常只关心字典中的两个键, next_token 和 result_count 。
对两个键中数据的解释
例如,要检索 next_token,您可以编写:
json_response['meta']['result_count']
现在,我们有两个选项来保存结果,这取决于我们希望如何处理数据,我们可以将结果保存为我们收到的相同的 JSON 格式,或者保存为 CSV 格式。
要在 JSON 中保存结果,我们可以使用这两行代码轻松完成:
with open('data.json', 'w') as f:
json.dump(json_response, f)
8.将结果保存到 CSV
您可能会问自己,为什么我们要将结果保存为 CSV 格式?简而言之,与 JSON 对象相比,CSV 是一种广泛使用的格式,可以很容易地导入 Excel 电子表格、数据库或数据可视化软件。
现在,要将结果保存为 CSV 格式的表格,有两种方法,一种简单的方法和一种更加定制的方法。
嗯… 如果有一个通过 Python 库的简单方法,为什么我们需要自定义方法呢?
答案是:自定义函数将使我们将一些返回结果中嵌入的字典分解并精简到单独的列中,使我们的分析任务更容易。
例如,公共指标关键字:
"public_metrics": {
"like_count": 0,
"quote_count": 0,
"reply_count": 0,
"retweet_count": 0
},
该键返回另一个字典,简单的方法是将该字典保存在一个 CSV 列下,而在自定义方法中,我们可以在将数据保存到 CSV 之前将每个字典分成不同的列。
A.简单的方法是:
对于这种方法,我们将使用熊猫包
df = pd.DataFrame(response['json_response'])
df.to_csv('data.csv')
这是基于推特开发团队关于这个主题的博客文章的内容,我尝试了这个方法,它在简单的查询下运行得很好。
B.定制方法:
首先,我们将创建一个带有我们想要的列标题的 CSV 文件,我们将与我们的实际函数分开进行,这样以后它就不会干扰对请求的循环。
然后,我们将创建我们的 append_to_csv 函数,我们将把响应和期望的文件名输入到该函数中,并且该函数将把我们收集的所有数据附加到 csv 文件中。
现在,如果我们在最后一次调用中运行 append_to_csv()函数,我们应该有一个包含 15 条推特的文件(或者更少,这取决于您的查询)
append_to_csv(json_response, "data.csv")
9.循环请求
干得好!我们已经发送了第一个请求,并保存了第一个回复。
**现在,如果我们想保存更多的回复,该怎么办?**除了推特给我们的前 500 个结果之外,或者如果我们想在特定时期自动获得推特。为此,我们将使用循环和从 Twitter 接收的 next_token 变量。
让我们想想这个案例:
我们想收集 2020 年包含“新冠肺炎”一词的推特,分析人们在推特上谈论病毒时的情绪。可能有数百万条推特,我们每个月只能收集 1000 万条推特。
如果我们只是在 2020 年 1 月 1 日至 2020 年 12 月 31 日之间发送收集推特的请求,我们将很快达到上限,而不会在 12 个月内得到很好的分布。
因此,我们可以做的是,我们可以设定我们希望每月收集的推特数量的限制,这样,如果我们在某个月达到了特定的上限,我们就可以进入下一个月。
下面的代码就是一个例子,它将完全做到这一点!下面的代码块由两个循环组成:
- 我们希望覆盖的月/周/日内的 For 循环(取决于设置方式)
- 一个 While-loop,控制每个时间段我们希望收集的最大推特数量。
请注意,在调用之间添加了 time.sleep() ,以确保您不只是向 API 发送请求。
总结
在本文中,我们已经通过了一个广泛的逐步过程,使用 Python 从用于学术研究的 Twitter API v2 收集 Tweets。
我们已经涵盖了所需的先决条件,身份验证,创建请求和向搜索/所有端点发送请求,最后以不同的格式保存响应。
如果你喜欢这个,请随时通过 Twitter 和 LinkedIn 与你的朋友和同事分享!
请随时在 LinkedIn 上与我联系,或者在 T2 的 Twitter 上关注我!
置信区间的广泛指南和为什么你需要知道它
像数据科学家一样思考这个重要的统计概念
乔恩·泰森在 Unsplash 上的照片
介绍
几乎在商业中的任何角色,你都必须做出估计:
- 在市场营销中,你必须估计未来活动的投资回报率。
- 在供应链管理中,你必须预测(估计)你需要的库存量。
- 在产品开发中,置信区间对于确定产品的可靠规格非常重要。
现在,做出估计是一回事,但给出估计是另一回事和提供置信水平。
考虑以下情况…
- 陈述 A:我估计我们明年的销售额会达到 50 万美元。
- 陈述 B:我估计并且我有 95%的信心我们明年的销售额会在 450,000 美元到 550,000 美元之间。
两者有什么区别?
语句 B 为我们提供了更多的信息,因为它不仅为我们提供了一个统计数据,还告诉我们对这个统计数据有多大的“信心”。如果信心和信心水平的想法对你没有意义,不要担心,继续读下去。
目标
在本文中,我们将介绍什么是置信区间,为什么它们很重要,以及如何计算它们。
但是在深入置信区间之前,我们首先需要讲一个极其重要的概念,中心极限定理。
中心极限定理
中心极限定理非常强大——它指出样本均值的分布近似于正态分布。
作者创建的图像
举个例子,假设你从一个数据集中抽取一个样本,然后计算这个样本的平均值。一旦重复多次,你就可以把所有的样本均值和它们的频率绘制到一个图表上。不管初始分布是什么样的,最终总会是正态分布。
这真的很重要,因为这意味着我们可以利用假设正态分布的统计技术,比如置信区间。
那么什么是置信区间呢?
作者创建的图像
置信区间只是一个很可能包含感兴趣的参数(或统计数据)的数值范围。
例如,使用上面的图片,我们可以说样本均值是 100,或者我们可以说我们有 95%的把握样本均值在 90 和 110 之间。
另一方面,点估计是一个样本统计量,它提供了一个总体参数的单值估计(即平均值)。
误差幅度是点估计和置信区间终点之间的距离。
如前所述,使用置信区间而不是点估计(即平均值)的好处是因为它为我们提供了更多的信息。
一般来说,置信区间越宽,你越有信心真实参数在区间内。
均值的置信区间
由于中心极限定理,我们知道采样平均值的采样分布是正态分布,因此我们知道以下内容:
- 平均值等于μ
- 样本平均值等于 x̅
- 标准偏差等于σ/√n
作者创建的图像
因此,如果我们想要找到 95%的置信区间,知道经验法则,我们的误差幅度将是标准偏差的两倍——这是因为大约 95%的数据位于 2 个标准偏差内。
均值的置信区间
然后我们可以退一步,把它概括为一个方程。Z 分数简单地由我们希望我们置信区间有多“自信”来确定。
现在你可能在想,“在这之前,我们怎么知道σ呢?”这是个好问题。一般来说,如果你不知道μ,你可能也不会知道σ。也就是说,数学上可以证明,你可以用样本标准差作为替代。
因此,等式看起来像这样:
因为我们依赖中心极限定理来成立,所以有几个条件也需要成立。第一,样本必须是随机的,第二,样本大小(n)必须大于或等于 30。
比例的置信区间
现在,如果你想找到人口比例——也就是说,人口中具有某种特征的人/事物与人口总规模的比率。
在这种情况下,等式有一点改变:
- 您现在要寻找的不是平均值(μ),而是人口比例§
- 样本比例被表示为 p̂
- 标准偏差现在是= sqrt[p̂(1—p̂]/n]
这导致以下等式:
比例的置信区间
感谢阅读!
如果你坚持到了最后,那太好了!你应该知道什么是置信区间,它为什么有用,以及如何计算它。在进行估计时,置信区间是非常有用的,我强烈建议你除了进行点估计之外,还要使用置信区间。
如果你喜欢这样的文章,一定要给我一个关注介质。一如既往,我祝你在努力中好运!
不确定接下来要读什么?我为你挑选了另一篇文章:
</10-statistical-concepts-you-should-know-for-data-science-interviews-373f417e7d11>
又一个!
特伦斯·申
量子优势的例证
实践中的 Deutsch-Jozsa 量子算法
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
关于量子计算的帖子通常以它将如何改变世界的轶事开始。据说它可以在几秒钟内完成经典计算机需要几千年才能完成的任务。
作者图片
然后,我们开始调查。首先,我们了解量子比特(量子比特)与经典比特有何不同。它们处于叠加状态。叠加是状态 0 和 1 的复合(如在复数中)线性组合。许多人喜欢量子位不是 0 或 1,而是同时是 0 和 1 的概念。尽管这个概念不正确——或者至少不精确——但它生动地说明了量子算法的优势。经典计算机按顺序处理任务,一次一个,而量子计算机一次完成所有步骤。
在之前的一篇文章中,我们研究了大卫·多伊奇的算法。这种量子算法通过只查看一次来分类函数是恒定的(总是返回相同的结果)还是平衡的(给定不同的输入返回不同的结果)。相比之下,经典算法需要查看函数两次。
量子算法同时评估一个输入的不同方面的能力是惊人的。但是我们使用的例子似乎过于简单和解释。它不提供任何实用价值。因此,我们现在来看一个更实际的例子。
让我们假设有人给你一枚硬币,要你赌正面或反面。有人带着赌博的意图直接接近你?这听起来很可疑,不是吗?
作者图片
在你同意玩之前,你首先要确定硬币没有被操纵。假设有两种选择。要么,硬币是公平的,一半的情况下落在两边。或者,硬币被骗了,总是落在同一边。判断硬币是否公平的唯一可靠方法是扔硬币,看它落在哪一边。
假设我们测试硬币四次。一枚公平的硬币会落在两边两次。那么,你需要多久抛一次硬币才能发现呢?如果你只扔一次,它要么正面朝上,要么反面朝上。这根本没告诉你什么。如果你再扔一次,它落在另一边,你就完了。那么,你知道这是一枚公平的硬币。但是如果硬币再次落在同一边呢?一枚公平的硬币可能有四分之二落在一边。要肯定地说一枚硬币被骗了,你至少需要抛三次(当我们假设在样本量为 4 的情况下是公平的)。
从数学上讲,当硬币在第 n 次投掷时是公平的,我们需要投掷硬币2^(n/2–1)+1次。对于 n=4,这些是2^(4/2–1)+1=3投掷。对于 n=8,这些是 2^(8/2–1)+1=7 投掷,对于 n=10,这些是 2^(10/2–1)+1=15 投掷,等等。这个数字呈指数增长。
在最坏的情况下,我们可能会重复得到相同的结果,而不知道硬币是否仍然公平。这将需要指数数量的查询——至少如果我们以传统方式进行。
有了量子计算,我们可以一次性解决这个问题。相反,我们对每一种可能的投掷组合使用一个量子位。为了简单起见,假设我们只扔硬币三次。假设 1 代表正面,0 代表反面。因此,有八种可能的输入:(0,0,0)、(0,0,1)、(0,1,0)、(0,1,1)、(1,0,0)、(1,0,1)、(1,1,0)、(1,1,0)、(1,1,1)。
在我们的量子电路中,我们考虑的每一次投掷使用一个量子位,外加一个辅助量子位。因此,我们使用四个量子位。
我们从导入所需的库和指定量子电路开始。该电路包含一个表示投掷的量子寄存器、一个包含辅助量子位的量子寄存器和一个接收测量值的经典寄存器。
算法的主要部分是量子预言。如果这是你第一次听说量子计算领域的先知,不要担心。不是魔术,也不涉及神力。量子预言只不过是转换门的占位符。甲骨文就像你在经典编程中可能知道的开关盒控制结构。你有一个变量,先知。并为它可能具有的每个可能值指定行为。
作者图片
在我们的例子中,神谕代表了硬币的行为。一枚被骗的硬币要么只产生 0,要么只产生 1。
Qiskit 在|0⟩.初始化一个量子位在这种状态下,我们总是将一个量子位测量为 0。所以,当我们什么都不做的时候,我们已经有了代表一枚被骗硬币的神谕,这枚硬币总是反面朝上。
无论如何,我们把“无所事事”包装成一个函数。这个函数为我们创建了一个定制的转换门。为了清楚我们做了什么,我们在所有代表投掷的量子位元上应用 I-gate。I 门是身份门,保持量子位不变。
下图以图形方式描绘了tails_oracle
。
作者图片
当我们运行一个仅由这个 oracle 组成的电路时,它输出状态000
——代表三次尾朝上。
作者图片
“非门”将一个量子位从|0⟩态翻转到|1⟩.态因此,我们可以通过对所有量子位应用非门来创建一个代表被骗硬币的预言。
下图描述了这个 oracle。
作者图片
这个神谕总是产生州名111
——代表三次平视的州名。
代表公平硬币的神谕有点棘手。不过,它也不太复杂。对于三个量子位,我们可以说它至少正面朝上一次,反面朝上一次。函数balanced_oracle
采用额外的config
参数。这应该是一个表示抛硬币结果的位串。我们将非门应用于代表正面掷硬币的量子位。
此外,我们添加受控非门,每次投掷作为控制量子位,辅助量子位作为目标量子位。
下图描绘了配置110
的平衡 oracle 代表头对头尾。
作者图片
这个预言导致我们在config
位串中指定的状态。在我们的例子中,它是110
。它也适用于所有其他输入。请注意,量子位从右向左读取。
作者图片
显然,三个 CNOT 门并没有影响。这似乎是合理的,因为只有当控制量子位处于|1⟩.态时,CNOT-gate 才像非门一样作用于目标量子位我们所有量子位都在|0⟩.状态参见这篇文章以获得 CNOT 门更详细的视图。
问题出现了:“如果 CNOT 门不重要,我们为什么要把它放在首位?
答案就是我们的量子算法。到目前为止,我们只为不同的情况创建了神谕。我们看到神谕正确地代表了硬币的行为。
所以,让我们实现我们的算法,识别硬币是常数(欺骗)还是平衡(公平)。
我们从一系列的哈达玛门开始,将量子位带入|+⟩态,将辅助量子位带入|-⟩.态在这些状态下,一个量子位元被测量为 0 或 1 的机率各为 50%。|+⟩州和|-⟩州的区别在于量子位相位(参见这篇文章了解更多关于量子位相位的信息)。
然后,我们应用神谕。最后,我们在量子位元上加上另一个哈达玛门,让它们从叠加态回到基态。
下图显示了电路,包括一个神谕。
作者图片
所以。让我们看看这个电路的工作情况。我们从持续反面硬币的神谕开始。
作者图片
它结束于状态000
。
接下来,我们用heads_oracle
运行算法。
作者图片
它也在000
州结束。
最后,我们用平衡甲骨文运行电路(你可以用任何位串运行它)。
作者图片
对于平衡输入的预言,电路结束于状态111
。您提供哪个位串作为输入并不重要。
“但这是怎么做到的?”
当预言不变时,我们要么应用 I 门,要么应用非门。但是由于我们的算法将量子位放入|+⟩状态,我们没有改变任何东西。当我们在|+⟩态的量子位元上应用非门时,它会停留在那个状态。当我们在电路末端使用哈达玛门时,它们会将量子位从|+⟩态转换回|0⟩.态我们有简单的 HIH 序列。
但是当我们应用balanced_oracle
时,我们额外应用了 CNOT-盖茨。虽然如果量子位处于基态(如|0⟩),这些都无关紧要,但如果量子位处于叠加态,它们就有关系了。然后,CNOT 门将目标量子位的相位应用于控制量子位。我们使用辅助量子位作为我们电路中的目标量子位,我们把它放入|-⟩.状态因此,当我们应用 CNOT 门时,我们将这个相位“复制”到其他量子位上。
结果,这些量子位也被转换到|-⟩态。最后的哈达玛门将|-⟩的量子位变成了|1⟩.我们称这种效应为相位反冲。
结论
开发了这个算法。它是 Deutsch 算法的推广,只使用两个量子位。
这个算法是量子算法比经典算法指数级更快的第一个例子之一。
此外,一个算法使用了相当多的量子特定技术,如叠加、预言和相位反冲。而且,当你一步一步地学习这些技术时,你会对量子算法在实践中的工作有很好的感觉。
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
在这里免费获得前三章。
使用 TensorFlow 的深入 EfficientNet 教程—如何在自定义数据集上使用 EfficientNet。
使用 Tensorflow 在具有挑战性的 Kaggle 数据集上训练效率网
桑德·韦特林在 Unsplash 拍摄的照片
卷积神经网络(ConvNets)通常在固定的资源预算下开发,然后如果有更多的资源可用,则按比例增加以获得更好的准确性。在本文中,我们系统地研究了模型缩放,发现仔细平衡网络深度、宽度和分辨率可以获得更好的性能。基于这一观察,我们提出了一种新的缩放方法,该方法使用简单而高效的复合系数来统一缩放深度/宽度/分辨率的所有维度。我们证明了这种方法在扩展 MobileNets 和 ResNet 上的有效性。
来源: arxiv
EfficientNet 是目前最先进的图像分类网络中相当强大的一个。我可以看到它在 Kaggle 的图像分类比赛中被大量使用,AUC 为 0.90 以上,我想我应该把我们的教程放在这里,因为网上没有那么多。
我将不会讨论 EfficientNet 的理论部分,因为有大量的在线资源,相反,我将讨论编码部分。你可以使用 efficientNet-pytorch ,然而,我通常发现 TensorFlow 更快更容易使用。
我们将在此使用的数据集是来自 Kaggle 竞赛 VinBigData 的胸部 x 光数据集。我们将使用 512x512 图像的调整版本,因为原始图像非常大(2k+)。你可以在这里找到调整后的版本。无论如何,本教程的主要目的是让你在自定义数据集上使用它。
除了图像之外,我们还有一个数据帧,用于指定每个图像的 class_id:
包装和进口
你想做的第一件事就是跑
!pip install tensorflow-gpu
这将允许您在 GPU 上训练您的模型(如果您有一个)。接下来要导入几个包:
from tensorflow.keras.applications import * #Efficient Net included here
from tensorflow.keras import models
from tensorflow.keras import layers
from keras.preprocessing.image import ImageDataGenerator
import os
import shutil
import pandas as pd
from sklearn import model_selection
from tqdm import tqdm
from tensorflow.keras import optimizers
import tensorflow as tf#Use this to check if the GPU is configured correctly
from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
设置效率网络:
为了更进一步,我们使用神经架构搜索来设计一个新的基线网络,并将其放大以获得一系列模型,称为 EfficientNets,它比以前的 ConvNets 实现了更好的准确性和效率。特别是,我们的 EfficientNet-B7 在 ImageNet 上实现了最先进的 84.3%的顶级准确性,同时在推理上比现有的最佳 ConvNet 小 8.4 倍,快 6.1 倍。我们的 EfficientNets 也能很好地进行迁移,并在 CIFAR-100 (91.7%)、Flowers (98.8%)和其他 3 个迁移学习数据集上实现了最先进的准确性,并且参数数量级更少。源代码在 https://github . com/tensor flow/TPU/tree/master/models/official/efficient net
来源: arxiv
好了,接下来我们需要做的是建立一个有效的网络,并安装预先训练好的砝码
# Options: EfficientNetB0, EfficientNetB1, EfficientNetB2, EfficientNetB3, ... up to 7
# Higher the number, the more complex the model is. and the larger resolutions it can handle, but the more GPU memory it will need# loading pretrained conv base model#input_shape is (height, width, number of channels) for images
conv_base = EfficientNetB6(weights="imagenet", include_top=False, input_shape=input_shape)
Weights="imagenet "允许我们进行迁移学习,但如果您愿意,可以将其设置为 None(您可能不应该这样做)。include_top=False 允许我们轻松地将最终图层更改为自定义数据集。
安装模型后,我们希望做一点配置,使它适合我们的自定义数据集:
model = models.Sequential()
model.add(conv_base)
model.add(layers.GlobalMaxPooling2D(name="gap")) #avoid overfitting
model.add(layers.Dropout(dropout_rate=0.2, name="dropout_out")) # Set NUMBER_OF_CLASSES to the number of your final predictions.
model.add(layers.Dense(NUMBER_OF_CLASSES, activation="softmax", name="fc_out"))
conv_base.trainable = False
准备数据集:
模型准备好了。现在我们需要准备数据集。我们将使用 flow_from_directory 和 Keras 的 ImageDataGenerator 。此方法需要培训和验证目录。在每个目录中,每个类都应该有一个单独的目录,该目录下有相应的图像。
首先,让我们为培训和验证下的每个类创建一个目录。
TRAIN_IMAGES_PATH = './vinbigdata/images/train' #12000
VAL_IMAGES_PATH = './vinbigdata/images/val' #3000
External_DIR = '../input/vinbigdata-512-image-dataset/vinbigdata/train' # 15000
os.makedirs(TRAIN_IMAGES_PATH, exist_ok = True)
os.makedirs(VAL_IMAGES_PATH, exist_ok = True)classes = [ 'Aortic enlargement',
'No Finding']# Create directories for each class.for class_id in [x for x in range(len(classes))]:
os.makedirs(os.path.join(TRAIN_IMAGES_PATH, str(class_id)), exist_ok = True)
os.makedirs(os.path.join(VAL_IMAGES_PATH, str(class_id)), exist_ok = True)
接下来要做的是将每个图像复制到其正确的目录中:
Input_dir = '/kaggle/input/vinbigdata-512-image-dataset/vinbigdata/train'def preproccess_data(df, images_path):
for column, row in tqdm(df.iterrows(), total=len(df)):
class_id = row['class_id']
shutil.copy(os.path.join(Input_dir, f"{row['image_id']}.png"), os.path.join(images_path, str(class_id)))df = pd.read_csv('../input/vinbigdata-512-image-dataset/vinbigdata/train.csv')
df.head()#Split the dataset into 80% training and 20% validation
df_train, df_valid = model_selection.train_test_split(df, test_size=0.2, random_state=42, shuffle=True)#run the function on each of them
preproccess_data(df_train, TRAIN_IMAGES_PATH)
preproccess_data(df_valid, VAL_IMAGES_PATH)
现在,您可以检查数据集目录,所有图像都应该复制到它们正确的子目录中。下一步是将数据集传递给生成器,然后开始训练:
# I love the ImageDataGenerator class, it allows us to specifiy whatever augmentations we want so easily...
train_datagen = ImageDataGenerator(
rescale=1.0 / 255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode="nearest",
)# Note that the validation data should not be augmented!#and a very important step is to normalise the images through rescaling
test_datagen = ImageDataGenerator(rescale=1.0 / 255)train_generator = train_datagen.flow_from_directory(
# This is the target directory
TRAIN_IMAGES_PATH,
# All images will be resized to target height and width.
target_size=(height, width),
batch_size=batch_size,
# Since we use categorical_crossentropy loss, we need categorical labels
class_mode="categorical",
)
validation_generator = test_datagen.flow_from_directory(
VAL_IMAGES_PATH,
target_size=(height, width),
batch_size=batch_size,
class_mode="categorical",
)
model.compile(
loss="categorical_crossentropy",
optimizer=optimizers.RMSprop(lr=2e-5),
metrics=["acc"],
)
如果一切按计划进行,您应该会得到与此类似的消息:
Found X images belonging to x classes.
Found Y images belonging to x classes.
训练模型:
history = model.fit_generator(
train_generator,
steps_per_epoch=NUMBER_OF_TRAINING_IMAGES // batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=NUMBER_OF_VALIDATION_IMAGES // batch_size,
verbose=1,
use_multiprocessing=True,
workers=4,
)
预测
y_pred = model.predict(X_test)
score = model.evaluate(X_test, y_test,verbose=1)
评估:
# Import the modules from `sklearn.metrics`
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score# Confusion matrix confusion_matrix(y_test, y_pred)
precision_score(y_test, y_pred)
recall_score(y_test, y_pred)
f1_score(y_test,y_pred)
下一步是进一步评估模型,有很多资源可以做这件事,因为你可能会对探索大量不同的指标感兴趣,使用 Keras 应该很容易。
对本教程的一些可能的改进是通过创建几个折叠,然后组合最终的预测来使用交叉验证。此外,您可以使用更高级的数据增强技术,如混合、分割和抖动。
易访问数据可视化的不完整指南
做得更好的实用技巧。
作者的原创艺术
从最直接的意义上来说,可访问的可视化旨在让读者访问视觉呈现的信息。最常见的是,易访问性问题是指色盲或失明。然而,实际上,可访问性超越了特定的永久性残疾,涵盖了可用性优化的所有方面——适用于所有人。
记住残疾不是少数人的固定状态是很有用的。相反,残疾是一系列的经历,既有永久性的,也有暂时性的。例如,你可能会患上白内障,或者摔断手臂。偏头痛可能会让你蜷缩在黑暗的房间里,或者一个不眠之夜可能会模糊你的理解力。
坦率地说,让可视化变得普及是困难的。许多可视化工具不支持可访问设计,那些支持的工具学习起来会很混乱。即使有了可以想象到的最好的工具,可访问性也会使艺术超过科学,对一个人来说完美的设计对另一个人来说可能是不可用的。
因此,下面的指南肯定是不完整的。毫无疑问,我错过了或过于简化了重要的事情。可能是我笨拙地冒犯了你。但是,如果完美是遥不可及的,我希望这个指南至少提供了一些可以实现的想法,如何变得更好。
文本、标题和题注
如果不强调可视化文本元素的重要性,我们就不能谈论访问信息。没有文字,只有形状。所以请注意,并确保你使用的文本是有目的的。
标题应该告诉你可以用图形回答什么问题,但不一定要写成问题。例如,“2020 年供应商销售的单位数量”回答了问题去年每个供应商销售了多少单位?
图例应清楚地标识视觉映射和图形元素,并在连续数据中直接标出有意义的界标。尽量使用事物的实际单词,而不是变量名。
轴标签应该是简单明了的、水平的(如果可能的话)和描述性的。例如,“时间(2004–2009)”比“x”更有用。
标题应该给出任何可能影响图表解释的内容。帮助读者理解他们所看到的。例如,“这些数据是通过网络调查收集的,该调查使用客户的存档地址进行管理。将该图解读为,“在应用上花费较少时间的用户倾向于在扩展和附件上花费较少的钱,其中一个显著的异常值在不到 5 秒钟内花费了 24k 美元*。”*
色盲友好
有 3 种主要类型的色觉缺陷。红绿色觉缺失包括偏色或偏色,使绿色显得更红;和 protanomaly 或 protanopia,使红色显得更绿。
蓝黄色觉缺陷包括三色异常使蓝色呈现绿色,黄色呈现红色;以及使蓝色呈现绿色、紫色呈现红色、黄色呈现粉红色的 tritanopia 。
最后,完全色觉缺失包括色盲、色盲或**单色。**这种情况非常罕见,通常伴有其他视觉障碍。
Coolors 调色板工具的快照
不管出于什么原因,如果你只是用颜色来区分可视化中的元素,有很多模拟器可以帮助你选择可区分的颜色。我个人使用上图所示的酷派工具来检查我的调色板。
有时会有一种误解,认为你不应该在可视化中使用红色或绿色;这样做会立即使它们失去可用性。这并不完全正确,忽视两种最具文化相关性、高联想色彩是不必要的严重。
取而代之的是,试着让红色略带橙色,绿色略带蓝色。对于色觉正常的人来说,这个小小的变化不会有太大的影响。然而,对于那些难以区分红色和绿色的人来说,这些小调整可以极大地提高区分度。
作者图解
您还可以检查调色板中的颜色是否可以区分为黑色和白色。如果您需要打印没有颜色的可视化效果,这将会很方便,并且可以帮助总体色觉较低的用户。
亮度对比度
亮度对比度是两种颜色的亮度(或明度)之比。这个比例影响着物体被区分的程度。亮度对比通常是针对文本和背景来讨论的,但是同样的原理也适用于图形元素。您可以使用 WebAim 对比度检查器来验证您使用的是足够高对比度的颜色。
作者图解
杂项设计提示和技巧
即使对于那些能看到的用户来说,也有一些设计技巧可以让图形看起来更舒服。一个简单的技巧是在堆叠的条和点周围添加一个细的白色边框。这使得区分形状变得更加容易,并且减少了交叉点处无意的视觉效果。
作者图解
您还可以对齐图例,使其与最接近的可视元素的结构和顺序相匹配。这确保了读者确切地知道哪个元素具有什么值,并最大限度地减少来回扫视的时间。
作者图解
使用直接标注是避免使用图例的好方法。使用图例本身没有错,但是直接的标签可能会让你的读者更容易将一个视觉元素与一个值联系起来。在某些视觉元素远离图例的情况下,您可以选择同时使用图例和直接标签。
作者图解
最后,你可以改变纹理线和点的形状。这使得颜色不再是唯一的信息载体。在可视化中,我们称之为冗余编码或双重编码,这意味着数据用多个可视属性表示。我建议用颜色更浅的虚线连接起来,这样线条就能保持连接。同样,确保选择明显不同的形状。
作者图解
数据导出
使数据可访问的最直接的工具之一是简单的数据导出。即使 visual 与屏幕阅读器不兼容,导出也可以允许屏幕阅读器用户浏览数据。
然而,在进行数据导出时,重要的是要记住您是从可视化中提供值*。*这意味着提供预处理值,人们可以从视觉上合理地推断出这些值,而不是原始的、未清理的、未聚集的数据集。
键盘导航和屏幕阅读器
有人可能会使用键盘导航有各种各样的原因。例如,盲人用户或那些运动受限的用户可能更喜欢使用键盘而不是鼠标来导航。其他用户可能喜欢键盘导航的效率。无论哪种方式,这都是可能的,因为网页的 HTML 结构表明了所选内容的类型及其在页面上的位置。
当你为网页制作可视化效果时,确保使用标准的 HTML 结构,并带有键盘友好的标志。你可以在 WebAIM 网站,这里是上阅读更多关于如何做到这一点的信息。
屏幕阅读器获取嵌入网页 HTML 中的信息,并大声朗读出来。关于可视化,这是我们上面提到的文本元素中最常见的。不幸的是,并不是所有的可视化工具和平台都能很好地与屏幕阅读器一起工作;例如,这个页面不支持交互式媒体。在这种情况下,您需要使用 alt-text 来描述静态可视化。
<button aria-label= “publish article”>Publish</button>
<img src="graph.png" alt="Bar chart of ice cream preferences by nationality. 70% of Americans preferred sourdough ice cream.">
数据发音
进入可访问可视化的新领域,在*数据语音化领域有一些有趣的工作正在进行。*图表库 HighCharts 是这一领域的先驱。顾名思义,发音将数据映射到声音,而不是视觉元素。聆听可视化可以告诉用户趋势和异常值。也许作为一个独立的工具并不精确,但是 sonification 是对屏幕阅读器体验的一个很好的补充。也很好玩!
一个艺术的数据发音的例子,来自我们在 NASA 的朋友。这项工作是关于蟹状星云的。
数据物理化
最后,数据物理化是用物理介质表示数据的实践。这意味着除了颜色等视觉属性之外,纹理、温度、重量和大小都可以作为触觉编码。这是一个仍在研究中的领域,但却像成堆的岩石一样古老。这里有一个致力于数据物理化的维基你可以在这里找到。
没有别的办法:让数据可视化变得可访问需要额外的工作。有工具约束、知识约束和个人偏好。但是,这并不意味着我们不能在制作更容易访问的可视化方面做得更好。为了填补上面我可能遗漏的空白,我加入了社区中其他人的一些文章。欢迎在评论中分享其他资源!
https://medium.com/nightingale/data-visualization-accessibility-where-are-we-now-and-whats-next-b2c9eeac4e8b https://medium.com/nightingale/accessibility-is-at-the-heart-of-data-visualization-64a38d6c505b
Google Colab:如何从 Github、Kaggle 和本地机器上传大型图像数据集
在 Google Colab Jupyter 笔记本上访问大型数据集,用于训练深度学习模型
约书亚·索蒂诺在 Unsplash 上拍摄的照片
∘ 了解 Colab 的文件系统
∘ 1。从 Github
∘ 2 这样的网站上传数据。从你的本地机器上传数据到 Google Drive,然后到 Colab
∘ 3。从卡格尔∘
上传数据集结论
Google Colab 是来自 Google 的免费 Jupyter 笔记本环境,其运行时托管在云上的虚拟机上。
有了 Colab,你不必担心你的计算机的内存或软件包安装。你可以获得免费的 GPU 和 TPU 运行时,笔记本电脑预装了机器和深度学习模块,如 Scikit-learn 和 Tensorflow。也就是说,所有项目都需要数据集,如果你不是使用 Tensorflow 内置数据集或 Colab 样本数据集的T21,你将需要遵循一些简单的步骤来访问这些数据。
了解 Colab 的文件系统
您创建的 Colab 笔记本保存在您的 Google drive 文件夹中。然而,在运行时(当笔记本电脑处于活动状态时),它会根据您的喜好,从云中分配一个基于 Linux 的文件系统或 CPU、GPU 或 TPU 处理器。点击笔记本左侧的文件夹(矩形)图标,可以查看笔记本的 当前工作目录 。
按作者分类的 Colab 当前工作目录
Colab 提供了一个包含数据集的sample-data
文件夹,您可以随意使用,或者使用上传图标(在“搜索”图标旁边)上传您的数据集。请注意,一旦运行时断开连接,您将失去对虚拟文件系统的访问,并且所有上传的数据都将被删除。但是,笔记本文件保存在 Google drive 上。
在sample_data
文件夹上面有两个点的文件夹图标显示了 Colab 的文件系统中的其他核心目录,比如/root, /home, and /tmp
。
作者在 Colab 上的文件系统
您可以在“文件”面板的左下角查看您分配的磁盘空间。
作者的 Colab 的磁盘存储
在本教程中,我们将探索从三种介质上传图像数据集到 Colab 文件系统的方法,以便笔记本可以访问它们进行建模。我选择将上传的文件保存在/tmp
中,但是你也可以保存在当前工作目录中。Kaggle 的狗与猫数据集将用于演示。
1.从 Github 等网站上传数据
要将数据从网站直接下载到 Google Colab,你需要一个直接指向 zip 文件夹的 URL(网页地址链接)。
- 从 Github 下载
Github 是一个平台,开发者可以在这里托管他们的代码,并在项目上合作。项目存储在存储库中,默认情况下,存储库是公共的,这意味着任何人都可以查看或下载内容到他们的本地机器上并开始使用它。
第一步是搜索包含数据集的存储库。这里的是由 laxmimerit 制作的 Github repo,其中包含了猫与狗各自文件夹中的 25,000 张训练和测试图像。
要使用此流程,您必须拥有一个免费的 Github 帐户并已登录。
导航到包含数据集的 Github repo 。在回购的 主页 上,找到绿色的“代码”按钮。
作者图片
点击“代码”按钮右侧的箭头。这将显示一个下拉列表。
右键单击“下载 Zip”
右键单击“下载 zip”上的,并单击“复制链接位置”。注意:这将下载回购中的所有文件,但我们将在 Google Colab 上提取内容时筛选出不需要的文件。
导航到 Google Colab,打开一个新的笔记本,输入并运行下面两行代码,导入我们需要的内置 python 库。
下面的代码是我们粘贴链接的地方(第二行)。整个代码块下载文件,解压文件,并将内容提取到/tmp
文件夹中。
wgetUnix 命令 : wget <link>
下载网页内容并保存到 当前工作目录 (注意!
因为这是一个由系统命令行执行的 shell 命令。另外,链接必须以.zip
结尾。在上面的代码中,我们提供了(可选)一个下载目录(/tmp
),以及下载的 zip 文件的期望名称(cats-and-dogs.zip
)。我们使用— -no-check-certificate
来忽略 SSL 证书过期的网站上可能出现的 SSL 证书错误。
现在我们的 zip 内容已经提取到了/tmp
文件夹中,我们需要数据集相对于我们正在处理的 Jupyter 笔记本的路径。如下图所示,单击文件夹图标(箭头 1),然后单击文件系统(2)以显示虚拟系统的所有文件夹。
作者图片
向下滚动并找到所有图像文件夹所在的/tmp
文件夹。
作者图片
您可以使用os.listdir(path)
返回文件夹内容的一个 python 列表,您可以将它保存在一个变量中用于建模。下面的代码显示了 train 和 test 文件夹中猫和狗的图像数量。
- 从其他网站上传数据
其他网站,比如广受欢迎的 UCI 知识库,对于加载用于机器学习的数据集也很方便。一个简单的谷歌搜索把我带到了微软的这个网页,在那里你可以找到狗和猫数据集的下载链接。
当您点击“下载”按钮时,“取消”询问是“打开”还是“保存”文件的弹出消息。
网页现在显示一个链接,“点击这里手动下载”。右键点击,然后点击“复制链接位置”。
作者图片
打开一个新的 Google Colab 笔记本,按照上面 Github 链接描述的相同步骤操作。
2.从你的本地机器上传数据到 Google Drive,然后到 Colab
如果数据集保存在您的本地机器上,Google Colab(运行在云上的一个单独的虚拟机上)将无法直接访问它。因此,我们需要首先将它上传到 Google Drive,然后在构建模型时将其加载到 Colab 的运行时。
****注意:如果数据集很小(比如一个.csv
文件),你可以在运行时直接从本地机器上传到 Colab 的文件系统。然而,我们的图像数据集很大(543 Mb),我花了 14 分钟将 zip 文件上传到 Google Drive。在驱动器上,我现在可以打开一个 Colab 笔记本并将其加载到运行时,这将花费大约一分钟的时间(在下面的代码中演示)。但是,如果您要将它直接上传到 Colab 的文件系统,假设上传需要 14 分钟,一旦运行时断开连接,您必须再次上传相同的时间。
在将数据集上传到 Google Drive 之前,建议它是一个单独的 zip 文件(或类似的归档文件),因为驱动器必须为每个文件分配单独的 id 和属性,这可能需要很长时间。
一旦数据集保存在你的本地机器上(我从这里的下载到 Kaggle 上的,打开你的 Google Drive ,点击左上角的“新建”按钮。从下拉列表中,点击“文件上传”,然后浏览到您系统上的 zip 文件,然后“打开”它。
由作者将文件上传到驱动器
右下角将出现一个进度条,指示上传过程完成。
作者的 Google Drive“上传完成”
现在打开一个新的 Colab 笔记本。第一个代码块挂载Google Drive,这样 Colab 的文件系统就可以访问它。
Colab 将提供一个链接,授权其访问您的 Google 帐户的驱动器。
作者将 Google Drive 安装到 Colab
点击此链接(上面的箭头 1),选择您的电子邮件地址,然后在底部点击“允许”。接下来,从弹出窗口中复制代码并粘贴到 Colab 的文本框中(箭头 2),最后将显示这条消息:Mounted at /content/drive
。
现在,当我们查看屏幕左侧的文件时,我们会看到已安装的驱动器。
按作者安装 Google Drive 文件夹
接下来是将数据集读入 Colab 的文件系统。我们将解压文件夹,并使用下面的代码将其内容提取到/tmp
文件夹中。
现在你可以从文件系统中查看到 Colab 的/tmp/train
文件夹的路径。
作者的 Colab 文件系统
使用os.listdir(path)
方法返回数据文件夹中的内容列表。下面的代码返回了train
文件夹的大小(图片的数量)。
3.从 Kaggle 上传数据集
Kaggle 是一个数据科学家和机器学习从业者互动、学习、竞争和分享代码的网站。它提供了一个公共数据平台,拥有数以千计的公共数据集,这些数据集要么来自过去或正在进行的 Kaggle 比赛,要么由希望分享其数据集的社区成员上传。
2013 年,Kaggle 上的一场机器学习比赛中使用了猫 vs 狗数据集。我们将把这个数据集直接从 Kaggle 下载到 Colab 的文件系统中。以下步骤非常重要,因为从 Kaggle 下载数据集需要身份验证和权限。
第一步:从 Kaggle 下载配置文件
Kaggle 提供了一种与其 API 交互的方式。您需要一个免费的 Kaggle 帐户并登录。
点击你主页右上角的头像。从下拉菜单中选择“帐户”。
作者图片
在“帐户”页面上,向下滚动到“API”部分,然后单击“创建新的 API 令牌”。
作者图片
系统会提示您下载一个文件 kaggle.json。选择将它保存到您的本地机器上。这是包含您的凭据的配置文件,您将使用它直接从 Colab 访问 Kaggle 数据集。
注意:**您在此文件上的凭证将在几天后过期,当您试图下载数据集时,将在 Colab 笔记本中得到一个401: Unauthorised
错误。删除旧的 kaggle.json 文件,回到这一步。
第二步:上传配置文件到 Colab 笔记本
现在有了一个新的 kaggle.json 文件,你可以把它留在你的本地机器上(下面的步骤二 a ,或者保存(上传)到 Google Drive 上(后面的步骤二 b )。
步骤二(a) :如果文件还在你的本地机器上,你可以使用上传图标,或者使用 Colab 的files.upload()
将它上传到 Colab 的当前工作目录。如果您的项目使用同一台计算机,此选项会更简单。如果使用代码(不是上传图标),在新笔记本中运行下面的代码,浏览到下载的 kaggle.json 文件,然后‘打开’它。
该文件将出现在您的工作目录中。
作者上传的文件
第二步(b) :第二个选项是将 kaggle.json 文件保存(上传)到 Google Drive。打开一个新的 Colab 笔记本,按照简单的步骤将硬盘安装到 Colab 的虚拟系统中(如下所示)。有了这个选项,你可以从另一台机器上运行笔记本,因为 Google Drive 和 Colab 都托管在云上。
在 Google Drive 上,创建一个新文件夹,命名为 Kaggle。双击打开该文件夹,并上传ka ggle . JSON 文件。
由作者将 kaggle.json 文件上传到驱动器
接下来,打开一个 Colab 笔记本,运行下面的代码,将驱动器挂载到 Colab 的文件系统中。
一旦成功,运行下面的代码将 kaggle.json 从驱动器复制到我们当前的工作目录,这个目录是/content
( !pwd
返回当前目录)。
刷新文件部分,在当前目录中找到 kaggle.json。
第三步:将操作系统环境指向配置文件的位置
现在,我们将使用os.environ
方法来显示包含认证细节的 kaggle.json 文件的位置。记得导入为此所需的文件。
第四步:从 Kaggle 中复制数据集的 API 命令
**Kaggle 上的每个数据集都有一个相应的 API 命令,您可以在命令行上运行该命令来下载它。**注意:如果数据集是为一个竞赛准备的,请转到该竞赛的页面并‘阅读并接受规则’,这样您就可以提交数据了;否则你会在 Colab 上得到一个403-forbidden
错误。
对于我们的狗对猫数据集,打开比赛页面并点击“数据”选项卡。向下滚动并找到 API 命令(下面以黑色突出显示)。
由作者复制竞赛 API 命令
对于其他数据集(非竞赛),单击“新建笔记本”按钮旁边的 3 个点,然后单击“复制 API 命令”。
按作者复制其他数据集 API
步骤 5:在 Colab 上运行这个 API 命令来下载数据
回到我们的 Colab 笔记本,将这个 API 命令粘贴到一个新的块中。记得包括!
符号,它告诉 python 这是一个命令行脚本。
如果一切正常,将会显示下载确认。我得到了下面的结果。
按作者下载确认
现在,从左侧的文件窗格中,您可以看到所有已下载的文件夹。
按作者下载的文件
第六步:提取文件
现在我们可以提取 train.zip 文件中的文件并保存到/tmp
(或者当前目录/content
)。
运行下面的代码以返回解压缩文件夹中的文件数量。
结论
在本教程中,我们探讨了如何将图像数据集从 Github 和 Kaggle 等网站以及您的本地机器上传到 Google Colab 的文件系统中。现在你已经将数据存储起来,你可以训练一个深度学习模型,比如 CNN,并尝试正确地对新图像进行分类。对于更大的图像数据集,这篇文章给出了替代方案。
我希望你喜欢这篇文章。每当我发表新的文章时,想要收到更多这样的文章,请在这里订阅。如果你还不是一个媒体成员,并且愿意支持我作为一个作家,跟随这个链接,我将赚取一小笔佣金。感谢您的阅读!
斯坦福人工智能在医疗保健系列课程(医疗保健专业人工智能)的初步评价
为什么在医疗保健环境中实施人工智能和机器学习如此具有挑战性
作者图片
开始之前,请注意以下几点:
- 虽然我被培养成科学家,但我不是医学博士。这意味着我在 Coursera 上选修了这门非 AMA 学分的课程作为证书。
- 根据打字错误和录音信号的数量等。我希望是第一批尝试这个系列课程的人之一。
- 课程系列的链接可以在这里找到:https://www.coursera.org/specializations/ai-healthcare
格式:
课程系列的形式是一系列人们站在原地从屏幕上阅读的视频。有两个拍摄角度,但附加的视觉效果很少,所以跟随拍摄是一个真正的听力技巧练习。所提供的学习指南提供了所有相同的视觉效果和朗读文本,因此这些课程可能很容易在播客模式下进行(只需听,然后阅读学习指南)。
作业是自我检讨(帮助你思考你是否学到了什么)和测验(无限重试的多项选择)。有些问题假设你听了例题或做了一些关于题目的课外阅读。
序列:
该系列的第一门课程是 医疗保健介绍 。对于那些不把“中介”作为健康保险公司的标准术语的人来说,这是一门非常有用的课程,介绍了医疗保健市场词汇。所使用的示例有助于更好地理解为什么医疗保健数据如此分散且看起来毫无关联。
该系列的第二门课程是 **临床数据介绍。**虽然本课程涵盖了一些标准的机器学习数据问题,但它也强调了时间的重要性,并建议所有数据都包括一个时间范围,因为程序之前和之后的测试结果可能意味着非常不同的事情。建议是将所有特征排列在一个时间线中,以允许更好的推断。另一个见解是,鉴于医疗保险报销的变化和医疗程序的进步,数据窗口可能缺少分析、建模和预测。讨论的数据来源是电子健康记录(EHR),健康保险索赔数据和公共数据来源。
该系列的第三门课程是 面向医疗保健的人工智能和机器学习基础。 虽然本课程涵盖了从决策树到 CNN、RNNs 的标准机器学习方法,但它带来了结果-行动-配对的重要性。这个 OAP 概念提出了这样一个问题:“有人能够或愿意根据模型的结果采取行动吗?”在医疗保健行业,如果数据不可操作,它可能会很有趣,但可能不是特别有用。高度准确但其数据不能被采取行动的模型可能不如可能触发可采取行动的行为的较不准确的模型有用。
该系列的第四门课程是 **医疗保健中人工智能应用的评估。**本课程涵盖偏差的可能性、部署比例模型的挑战以及在给定人口统计范围的情况下,研究项目和可用于多个医疗机构的模型之间的适用性差异。这个单元还涵盖了医疗保健中人工智能的联邦指南和批准过程。涉众广泛参与部署,可操作的数据以问题“有时间采取行动吗?”。
注:以上所有单元均可自定进度,并在指定日期前开始和完成。
该系列的最后(第四)门课程是医疗保健顶点 中的 AI。本单元采用同伴评估的方式,在这种方式下,您可以根据提供的 3 分制评分标准对其他课程参与者进行评分。到目前为止,这些问题并不需要医学知识,但是随着我们的进展,我会学到更多。
到目前为止课程的收获:
整个课程假设科学词汇的合理水平。受过医学训练的人可能不需要去寻找铁蛋白和新冠肺炎之间的潜在关系。我做到了。
对统计学的基本理解是有帮助的,虽然所涵盖的机器学习主题对于完成任何机器学习课程基础的人来说都是熟悉的,但例子中提到的偏见和缺乏可解释性的应用和风险,尤其是医疗保健,可能会令人大开眼界。
由于不完整的人口统计或历史数据(主要是白人或男性)导致的偏见风险可能非常高,并且在主要不是白人和男性的医疗保健地区阻碍了有用模型的实施。
美国的医疗保健系统如此复杂,如果患者的私人数据被暴露,对患者的惩罚是如此之高,以至于人工智能的成功实施存在许多障碍。有一种感觉是,美国和欧盟对数据的保护比中国更强,可能会在医疗保健的人工智能“竞赛”中输给中国研究人员。人们只能希望美国能够找到一种方法,为患者提供隐私保障和积极的激励措施,以分享他们的医疗保健数据,这似乎是前进的方向。
概要:
虽然在枯燥的演示格式下,本课程要求比其他在线学习经验更高水平的注意力和听力技能,但它概述了数据、建模、偏见和实施方面的挑战,因此值得花时间学习本课程。
虽然这些课程被安排成一系列,但在很大程度上,它们可以根据兴趣相互独立地进行。
如果你对在医疗保健环境中成功实施人工智能或机器学习所面临的挑战感兴趣,这是一个有趣的概述。如果你不是听觉型学习者,你可能会发现你会更成功地下载和复习学习指南,观看更有趣主题的视频。
随着医患沟通已经转移到作为数据录入员的医生手中,通过自动化日常任务、利用计算机比人眼更好以及患者对数据的所有权,释放人工智能的力量以重新人性化医疗保健的潜力是巨大的。
顶石项目可能比其他单元需要更多的医学专业知识,所以我可能不会完成该单元,所以这可能是唯一张贴的审查,而不是整个系列更全面的审查。如果没有,请查看将课程知识应用于新冠肺炎 x 射线和 EHR 数据分析和模型的最新回顾!
点击此处查看顶点评论
从第一原理导出逆变换采样方法
从自定义概率密度函数生成样本的见解
快速提示:
在本文中,我提供了关于使用逆变换采样方法从定制概率密度函数生成样本的见解。
几乎每种编程语言都允许用户生成随机数。但是如何生成遵循一定概率分布的数字呢?这个问题是我决定阅读这个话题的主要原因。
当处理抽象概念,即数学和编程时,通常面临的挑战是在头脑中描绘这些概念。有鉴于此,在整篇文章中,我将不断地使用图表或动画来阐述我的想法。
最后,我将努力实现的是从零开始构建——一个支持从自定义概率密度函数进行采样的工具。
概率密度函数很容易构造,但取样却不容易
在概率统计中,确切地说是在描述连续随机变量时,我们经常会碰到概率密度函数的概念。这是一个描述随机变量的强大工具,因为它给出了随机变量的值出现的概率/频率。
举例来说(见下图,如果我们考虑一个由密度函数*【f】、*** 描述的随机变量 Y ,那么如果我们生成总共 100 个独立样本,理想情况下,其中 24 个样本落在 1-2 之间,40 个落在 2-3 之间,16 个落在 3-4 之间,依此类推。**
概率密度函数图解[作者图解]
碰巧有一个庞大的概率密度函数家族,范围从最常用的(均匀、正态、指数等)到最不可见的。事实上,如果你想构造你自己的密度函数,只要取一个可积函数,用它的积分归一化,就这样!
分布的例子:第一行是 3 种常见的分布,而第二行是 3 种不常见的分布[作者举例]
从数值上来说,从均匀分布中生成样本相当简单,因为它相当于生成随机数。很明显,几乎每种编程语言都有一个伪随机数发生器,比如 Python 的 random.random() 和 JavaScript 的 Math.random() 。
然而,为一个定制的分布函数做同样的事情并不简单,需要一些考虑。
这种被限制只能从均匀分布中取样却能轻松构建密度函数的挫败感是我下定决心的导火索。
我承认,在互联网上做了一些研究之后,我发现了一些已经存在的工具可以做到这一点(Python:scipy . stats . RV _ continuous)。然而,这还不足以满足我的好奇心。
我在本文中试图实现的是通过从头开始构建——使用均匀分布——一种支持从自定义密度函数进行采样的工具(,来揭示隐藏在引擎盖下的东西。
寻找统一分布和自定义分布之间的联系
假设我构造了一个自定义密度函数 f 。我现在的目标是利用均匀分布从中生成样本。我想到的基本想法是找到均匀密度函数和期望密度函数之间的映射。换句话说,我将从均匀分布中生成样本,并将这些数字与其对应的对等体进行映射。
根据自定义密度生成样本所遵循的模式【作者举例】
考虑到这一点,剩下的工作就是构建统一密度和定制密度之间的映射函数,换句话说就是揭示上面的齿轮实际上在做什么。
建立这种映射的提示可以从测量理论中得到。简而言之,测度论是长度、面积和体积概念的概括。除了在概率论的背景下——,这是一个特例——我们测量的是概率。密度可能起作用——更准确地说是“f dx”——可以被感知为度量,它们的积分与概率有直接联系。
将密度函数曲线下的面积解释为概率[作者举例]
在均匀密度和自定义密度两种情况下,我们测量的是概率,即曲线下的面积。因此,要找到映射,我们只需要找到均匀密度和自定义密度曲线下的区域之间的联系。
为了做到这一点,我们首先从制服上抽取一个号码。然后测量它所界定的面积。最后,我们找到在自定义分布曲线下划定相同区域的对应数字。
从定制密度中取样的详细流程图[作者插图]
将其放入一个等式中,我们需要为来自均匀分布的每个采样数 x 求解以下等式,以在自定义密度函数中找到其对应的对等体
其中 F 下标 X (分别为 F 下标 Y )表示密度函数的 x (分别为 y )所界定的曲线下的面积。在文献中, F 称为累积分布函数。它测量随机变量落在由指定界限界定的左侧区间内的概率,在我们的例子中,该区间就是由指定界限界定的曲线下的区域。
统一分布和自定义分布之间映射过程的实现
现在,我们有了所有的理论材料,可以将一个统一的生成样本映射到它在自定义密度中的对等样本。剩下的就是建立一个程序来求解上面的方程。
为了简单起见,我们将从 0-1 之间的均匀分布中取样。因此,每个采样数的曲线下面积将正好等于该数本身。
另一方面,对于给定的 y ,计算定制密度曲线下的面积是简单的,因为我们有密度函数的显式表达式。事实上,是我们输入了这个表达。我们通过计算积分来计算这个面积。为了实现这一点,我们可以使用 Python:scipy . intergrate . quad。因此,必须求解的方程的最终外观如下:
解决这个问题相当于求上述非线性方程的根。为此,我们可以再次使用求解器。比如 Python:scipy . optimize . f solve。
然而,我们如何保证这个方程有解呢?如果是这样的话,如果它太多了,我们如何挑选正确的呢?
累积分布函数测量概率。因此,它是一个介于 0-1 之间的量。由于均匀分布的样本数也是一个介于 0-1 之间的量,我们保证该方程至少有个解**。**
另一方面,累积分布函数是单调递增函数。因此,我们确信无论何时有解,它都必须是唯一的**。**
基于这种推理,我们可以毫无顾虑地使用解算器来解方程。非线性求解器背后的核心思想是建立一个收敛到期望解的序列。通常,这个序列是通过一个递归公式来定义的,换句话说,序列在给定阶段的值依赖于前一阶段计算的值。因此,选择求解器的起点是一个关键因素,因为选择不合适的起点可能会产生错误的解,在最坏的情况下会产生一个根本不收敛的序列。
为了避免这样的问题,我们需要找到一种方便地选择起点的方法。为此,我们可以再次利用累积分布函数的一个性质,即它的单调性。
我们可以——在构建密度函数的时候——创建一个元组数组(见下图)*。因此,数组的元素按升序排序。基于此,假设我们从均匀分布中抽取一个数 x 。我们可以使用稍微修改过的二分搜索法版本来找到最接近它的两个元素。对应于这两个元素的’ y 将定义我们的解最可能出现的区间。因此,我们可以选择这个区间的中点作为起点。*
选择合适起点的方法说明[作者说明]
现在,我们有了从制服中找到给定抽样数的映射的所有要素。
在示例上测试映射过程
将前面的思路编码后,我开始逐步测试映射过程(见下图)*。*
我从一个特殊的例子开始,在这个例子中,我想要采样的自定义密度是一个均匀分布。基于此,映射过程应该理想地给出与从均匀分布生成的值完全相同的值。实际上,在这种情况下,我使用制服从制服中生成样本。
我选择的第二个测试是从通常的分布中产生样本,在我的例子中,我选择了正态分布。从视觉上看,我期望看到两条曲线的相同定界区域。例如,无论何时我们在正方形的右边得到一个数字(统一),映射的数字也必须在钟的右边(正常)。
最后一个测试是在一个不寻常的分布上测试这个过程。坦率地说,我真的很有创造力,想象出了我见过的最不寻常的密度函数:)
我已经收集了所有以前的动画测试,在左边我放了均匀分布的样本。另外,我用一个红点来表示取样的数字。在右边,我放上我试图从中取样的密度。类似地,我用红点表示映射的数字。
在制服上测试映射过程[作者插图]
正态分布映射的检验[作者举例]
在自定义发行版上测试映射过程[作者举例]
在确保映射过程给出准确的结果之后,是时候测试整个过程了,目标是从给定的密度函数生成样本。所以我考虑了一个定制的密度函数,我从一个制服中产生了一个大样本,然后我将这些样本与它们相应的对等体进行映射。最后,我用直方图表示结果。我的期望是,随着样本数量的增加,直方图的条应该接近密度函数的曲线。
另一次,我制作了一个动画,展示了随着样本数量的增加,直方图条长度的变化。
在自定义密度函数上测试整个过程[作者插图]
结论
在整篇文章中,我描述了如何利用均匀分布从自定义密度函数中生成样本。准确地说,我建立了一个工具来实现这一点。首先,我解释了它的实现过程。最后,我在几个发行版上测试了它,从常用的发行版到最不熟悉的发行版。
参考文献,本文描述的方法称为逆变换采样。还有其他方法可以达到同样的目的。查看这篇文章以便进一步阅读。
在写这篇文章时,我有意避免写任何代码,尽管我采用了数字视角。事实上,我希望这篇文章对于程序员和非程序员都是可以理解的。然而,如果你对事情实际上是如何实现的感到好奇,你可以查看我的 GitHub 库。在那里,我上传了关于代码的细节。
最后但同样重要的是,我可以说我已经成功地达到了我的目标。所以,为了庆祝这样的成就,满足我的自我,没有什么比想象各种密度函数并从中取样更好的了
使用内置工具生成的发行版示例[作者说明]
Rendezvous:“对伪数字生成器的洞察”
具有 Plotly 和 Streamlit 的交互式二氧化碳排放仪表板
实践教程,数据可视化
借助 Plotly charts 和 Streamlit 灵活的输入、布局和主题化选项,您可以从实时数据构建一个出色的交互式数据可视化应用程序
示例应用程序—作者图片
Streamlit 没有最全面的用户界面组件,但它们易于使用,只要有点想象力,就可以组合出良好的效果。
我们将看看如何在 Streamlit 中使用主题化和各种交互式输入和布局选项,以及 Plotly 图表,来制作一个有吸引力的、有希望提供信息的 web 应用程序。
要阅读本文,您需要对 Streamlit 和 Plotly 有所了解。文章中的大部分代码会以要点的形式显示,在文章的最后还有完整代码的要点以及下载链接。
上面的图片可能看起来不像一个典型的 Streamlit 应用程序,因为你看到的大多数应用程序都是用默认的 light 主题制作的。这一个利用了配置工具来选择默认的黑暗主题,但是其他定制的主题也是可能的。
你可以看到的图表是由 我们的世界在数据(CC BY license)中提供的定期更新数据 Plotly 创建的。这些图表跟踪全球二氧化碳(CO2)排放水平以及各个国家或地区(如欧盟或全世界)的人均排放量。
因为它们是 Plotly 应用程序,所以它们是交互式的,你可以用鼠标悬停在它们上面来查看更多细节。除此之外,Streamlit 滑块和多种选择输入设备让您能够更好地控制显示内容。
在下面的截图中,左边的图表显示了一张根据每个国家的二氧化碳排放水平而着色的地图。它有一个用于选择年份的滑块,当你移动滑块时,你会看到地图的颜色发生变化(随着排放量的增加,它们通常会随着时间的推移而变暗)。
右边的图表显示了单个国家或地区(如全球或欧盟)的人均排放量。设置了一些默认国家,但单击控件会显示一个下拉菜单,您可以在其中选择或取消选择任何有可用数据的国家。
作者图片
上面的截图是应用程序屏幕的上半部分,使用两列来显示图表。
下半部分,如下图所示,试图通过对比两个图表来显示二氧化碳排放量的增加和全球变暖之间的相关性。它使用了三列两列用于图表,一列用于文本描述。
然而,为了在图表之间建立适当的分隔,在应用程序的上部和下部,在包含图表的列之间插入窄的空白列。我们很快就会看到它是如何工作的。
作者图片
希望你现在能看到这个应用程序的样子,以及它的基本结构。那么,现在让我们来看看它是如何放在一起的。
获取数据
我们在 data 的 Github 存储库中检索来自我们世界的数据。所有 OWID 的数据都是在 CC 的许可下提供的,这意味着只要 OWID 有信用,它就可以按照你想要的方式使用。
我们使用两个文件,一个是关于二氧化碳和温室气体排放的 OWID 数据,另一个是关于气候变化影响的 OWID 数据。
更新:第二个数据集似乎已经从 OWID 存储库中删除,因此应用程序中依赖于此的部分将不再工作。
两者都是 csv 文件,我们把它们读入熊猫数据帧。
如你所见,有三个函数get_data
、get co2_data
和get_warming_data
。第一个函数从 url 返回一个 dataframe,而另外两个函数实际上设置了适当的 url 并从第一个函数返回 dataframe 结果。
还有两件事需要注意。
首先,当返回 warming 数据帧时,我们过滤数据帧,只返回那些包含小于 2021 年的年份并且“实体”(即国家或地区)是“世界”的行。这样做的原因是,首先我们只对 changedata 感兴趣,其次 year 列中的条目肯定不是真实的年份。老实说,我不知道他们代表什么,但他们的数字远远高于今年。所以我们忽略这些数据。
(仔细想想,>=2021
可能应该更高一些,比如说>=3000
,否则这款应用在今年之后就没什么用了!)
贮藏
第二件要注意的事情是 Python 装饰器@st.cache
用在了每个函数上。这个装饰器确保函数的结果被缓存,并且在应用程序的生命周期中不会不必要地调用函数。
这样做的原因是,每次进行更改时,Streamlit 应用程序都会完整地从上到下运行。因此,在我们的应用程序中,移动滑块或选择一个新的国家将导致应用程序重新运行。我们使用的数据不会经常更改,因此为了获得最佳性能,我们希望避免每次更改时都下载数据,而是使用之前缓存的数据。
如果我们要使用变化非常快的数据,比如股票行情,那么缓存数据是不合适的,因为我们会错过应用程序运行期间的更新。但其后果将是应用程序运行得更慢。
布局
应用程序的基本布局如下所示,其中未标记的列是空白的,用作其他列之间的填充。
作者图片
这是在 Streamlit 中实现的,如下面的代码大纲所示。
大纲代码—不用于复制!
我使用with col2
符号,因为我认为它使代码的布局更容易理解。
这里唯一需要注意的是标有space
的列。这些仅用作填充。所以,这一行代码
col2, space2, col3 = st.column((10,1,10))
创建三列。最外面的两个col2
和col3
宽度相同,将包含图表,而中间的一个space2
是另外两个的十分之一,并且是空白的。这在外柱之间提供了合适的间隙。
制作图表
这四张图表都是用 Plotly 制作的。第一个是在col2
中,但是这里我们从滑块组件开始,它允许你在 1750 年和 2020 年之间选择一年。选择的结果存储在变量year
中。
接下来,我们创建一个 Plotly choropleth(基本上是一个带有彩色区域的地图),其中颜色由 CO2 水平决定,数据帧由滑块设置的年份过滤。
第二张图是一个折线图,每个国家一张,显示了该国一段时间内的人均二氧化碳排放量。我们再次从输入控件开始,这次是多选框。默认国家名称列表与唯一的国家列表一起设置。除非选择了其他国家,否则 multiselect 控件将返回一组默认值。
然后,选定的国家用于设置图表上线条的颜色。
最终的图表很简单,不需要输入控件。第一个是全球海洋温度随时间变化的散点图。在此基础上,使用 lowess 平滑绘制趋势线。
第二张图表是全球排放量的折线图。
将平滑线放在第一个图表上的想法是为了让你看到它与排放线有多相似,从而试图显示两个测量值之间的相关性。
黑暗主题
在 Streamlit 中你可以做很多主题化的工作,但是要简单地启用黑暗模式你只需要在你的工作文件夹中创建一个名为.streamlit
的文件夹,并在其中放一个名为config.toml
的文件。在config.toml
文件中输入以下代码。
[theme]
base = "dark"
现在,下次你运行你的应用程序时,它将处于黑暗模式!
如果你想创建一个自定义的主题,其他的主题设置会放在同一个文件中,但是我们现在就把它放在这里。
就这些了
我希望从编码的角度来看这是有用的,但是我们也可以从这里展示的数据中学到一些东西。
如果你想试验代码,下面有完整代码的要点,或者你可以从我的 Github 库下载(向下滚动直到你看到文章的标题——链接会在那里)。
这里有一个这个应用的现场版。
一如既往地感谢阅读,如果你想知道我什么时候发表新文章,请考虑在这里注册一个电子邮件提醒。我也偶尔在子栈上发布免费的时事通讯。请在下面留下任何评论,或者您可以通过 LinkedIn 或 Twitter 联系。
完全码
机场交通的交互式仪表板
挪威机场有多忙?数据,Plotly,和破折号,可以帮助我们看到。
托马斯·威廉姆斯在 Unsplash 上的照片
现场演示 仪表盘活动-机场或查看项目**GitHub**。****
摘要
与其他欧洲国家相比,挪威在地理上是一个很大的国家,尤其是与它的居民相比。挪威的工业中心遍布全国。许多挪威公司经常开设新的较小的办公室,以获得合适的人,如果他们不愿意搬迁,或者如果该位置有足够的人来产生经济效益。此外,当一家公司收购另一家公司时,该公司的位置可能会在地理上被分割。这些因素导致了大量的国内航空旅行。本文中描述的公开可用的仪表板旨在提供视觉上愉悦和直观的用户体验,使用所需的工具查看给定机场的乘客数量,或者根据交通类型和日期比较不同的机场。
介绍
本文描述了在设计和实施探索性仪表板时所使用的数据收集和准备工作,该仪表板旨在清晰地描述给定位置或日期的挪威国内机场客流量。
功能
辅助函数定义并存储在 functions.py 中,并根据需要导入到用于准备数据的 jupyter 笔记本中。这样做的原因是为了让 Jupyter 笔记本更容易使用。已经注意到,如果笔记本有许多单元格或者很长,nbextensions 中的一些扩展往往会有滞后。我的偏好是从第一步到最后一步都在一个笔记本里。
数据集收集和准备
仪表板中用于勘探的数据来自挪威政府统计机构 SSB ,该机构拥有最新的详细数据和公开可用的 API。然而,为了简单起见,表格是从表单选择中创建的,并作为 CSV 文件下载[1]。选择包括的类别有乘客数量、月份、年份、机场名称和交通类型。然而,根据任务说明,只有国内航班和起飞及抵达时的乘客才包括在内。挪威字母表中有三个额外的字母?、和,它们都包含在机场名称中。但是,SSB 的 CSV 生成器不支持这些字符,它们被替换为“?”符号。因为没有上下文就无法创建脚本来更改这些,所以每个机场都需要手动重命名。
输入数据
CSV 文件由每个特征的列构成,“机场”、“交通类型”、“国内/国际航班”、“乘客组”,每个日期表示为“乘客 yyyyMmm”。为了进一步处理,CSV 文件被导入到 Pandas 数据框架中。
预处理
应用重命名列名或索引名的函数。该函数用于将“yyyy”从“mm”中拆分出来,删除“M ”,并将该列转换为“datetime”数据类型。
检查数据集是否有可能在以后导致问题的缺失值,但是没有发现任何缺失值。
Instances of missing data: 0
Columns with missing data: 0
Column names with missing data: None
宽数据
当前状态的数据集被称为“宽数据”,它不太适合制作图表。但是下面的一些操作在宽表单中更容易,所以现在还不会改变。
对于地理表示,需要位置数据。应用上面定义的基于机场名称查找每个机场的地理点的函数,方法是向数据帧添加带有位置数据的新列。
缺失数据
应用地理位置函数后,我们发现一些缺失值。显然,它无法识别挪威的所有机场。
Instances of missing data: 70
Columns with missing data: 5
Column names with missing data: location, point, latitude, longitude, and altitude
上面定义的missing_location()
函数用于定位缺失值的位置,以便决定下一步做什么。
经过一番调查,找到了没有给出位置的机场名称。
虽然只有两个机场,这使得手动步骤快速而简单,但这也是学习如何从地理数据中获取地址的绝佳机会。在 Jupyter 中工作时,内核有时必须重新启动,其中一些步骤非常耗时,因此结果被导出到一个 CSV 文件中。现在可以导入处理过的数据,而不是重新处理。
Instances of missing data: 0
Columns with missing data: 0
Column names with missing data: None
长数据
在制作仪表板之前,数据集被转换为“长数据”,其中日期列被融合到数据集中,因此每一行都有一个日期。不同流程生成的一些不必要的列被删除,时间和日期从日期中减去,因为它们由于无法从源中获得而完全相同。数据现在可以使用了,并且建立了快速更新数据的流程。
设计和实施
仪表盘
仪表板的用户交互设计非常强调直观性和自明性。仪表板的结构是每个图形都有自己的选项卡,因此不会给用户带来视觉负担。每个图形的控件都是自适应的,所以如果不适用于当前图形,它们会自动调整屏幕大小或隐藏起来。如果一个控件组是共享的,但是单个控件不合适,它们将被禁用并变灰,并在其标签中注明。交互的标签尽量简短明了,只陈述其功能。仪表板及其图形的视觉设计非常强调简约,以保持对数据描述内容的关注。在任何可能的情况下,蓝色、灰色和黑色的方案都被用于美学目的。第一印象对于说服用户仪表板制作精良至关重要。因此,项目标题和图标包含一个导航栏,浏览器窗格由一个 favicon 和项目标题组成。仪表板是由 Dash 框架中的自定义编码 HTML、CSS 和 Python 制作的。仪表板通过 Heroku 部署为 Flask 应用程序。尽管这不是最简单的解决方案,但它是启用所有仪表板功能所必需的。
如何部署应用程序不在本文讨论范围内,但是有许多关于如何部署的教程[2]。
要访问仪表盘,请点击此处:https://active-airport.herokuapp.com/
图表
有很多资料描述了在制作图表时应该考虑什么;PolicyViz [3]的一份整洁的备忘单总结了其中大部分的要点。所有图表的共同之处是,标题在左上角用大号粗体显示。这被大多数专业人士认为是最佳实践,因为它模仿了我们被教导阅读的方式,因此也是我们被教导对呈现给我们的信息的重要性进行优先排序的方式[4]。在适用的情况下,每个机场的值以文本或气泡尺寸的形式提供。因此,没有一个图表有任何网格线,因为它们不提供任何额外的信息,会分散注意力。此外,每个机场的任何相关信息都是通过将鼠标悬停在每个机场上来显示的。
地图图形
我不太喜欢 plotly 中的默认地图;我觉得它们很粗糙,视觉上也不美观。图 1 中显示的地图是使用 MapBox 提供的定制地图 Plotly 制作的,将土地灰和水白混合在一起,从而将焦点放在数据上。一个机场的旅客量由大小和颜色来表示,就像数量表示一样,它会自动调整所选择的机场数量和旅客总量。由于对数标度上的图形没有明显变化,因此该功能被禁用。请注意,当切换到“地理”标签时,地图并不总是完全加载。虽然这不是必须的,但是通过标签改变回调来更新图表大小已经过测试,但是没有影响到地图。然而,它适用于任何其他对象。发现“mapboxgl-canvas-container”CSS 类是问题所在,不可编辑。如果单击任何控制按钮,地图会调整大小。
图 1:地图(图片由作者提供)
条形图
图 2 所示的条形图是用 Plotly 制作的,并使用了数据集的副本,该数据集根据控件的选择与应用回调进行聚合。有很多机场可以选择,所以竖条是最好的选择。这些条根据乘客数量从高到低排序,并根据所选的机场数量自动调整,因此它们不会有令人尴尬的高度。由于各机场之间的乘客数量差异很大,可以选择对数标度来更好地表示。
图 2:条形图(图片由作者提供)
线图
图 3 所示的线形图对可接受的机场选择数量没有限制,但是因为在一个图中有许多线条被认为是不好的做法,所以没有制作“全选”按钮来促进这种行为。由于这个原因,线形图在颜色选择上有点突出,因为它是唯一一个需要选定机场图例的图,而且它们都需要是不同的。因为线形图的 x 轴是时间,所以可用的选项是“交通类型”、“机场”和“规模”。提供了范围滑块和“月”、“6 个月”、“今天”、“年”和“全部”的预设,以帮助用户探索数据并发现有趣的方面,如 2020 年 2 月新冠肺炎发生的时间。
图 3:折线图(图片由作者提供)
桌子
图 4 中所示的表格包含了所使用的数据,让用户可以看到这些图表是由什么组成的。一些数据没有包括在内,因为它只是为了功能的缘故。但是,该表是这样设置的,用户可以对数据进行筛选和排序,以找到感兴趣的特定行。
图 4:表格(图片由作者提供)
源代码
结论
机场数据从挪威统计局收集,并以适当的方式用于选定的任务。利用这些数据作为其来源,设计、实现和部署了一个仪表板。仪表板由 4 个选项卡组成,每个选项卡都有不同的数据交互方式。
参考
****[1]:挪威统计局。空运。按机场、交通类型和国内/国际航班划分的乘客。(2020),网址:【https://www.ssb.no/en/statbank/table/08507/ ****
【2】:魅力数据。"【https://www.youtube.com/watch?v=b-M2KQ6_bM4】用 Heroku 和 Dash Plotly(2020)部署你的第一个 App,网址:t
[3]: PolicyViz。数据可视化的核心原则。(2018),网址:https://policyviz.com/2018/08/07/dataviz-cheat sheet/
[4]:史蒂夫·韦克斯勒。"[不要将仪表板上的文本居中、右对齐或两端对齐。](https://www. datarevelations.com/resources/dont-center-right-align-or-justify-text-on-a-dashboard/)(2019),网址: https://www。data revenuations . com/resources/dont-center-right-align-or-justify-text-on-a-dashboard/
关于作者
Lewi Uberg 是挪威应用数据科学专业的一名四年级学生,拥有各行各业的极客、IT 经理和 CAD 工程师的背景。欢迎在 媒体上 关注他或者访问他的 网站 。
纽约医疗价格差异的互动研究
数据新闻
价格太高了。2
平均值。每个提供商/服务的调整后中间价格与每个提供商/服务的纽约市中间价格之间的差异
GitHub 资源库T3 此处 | Jupyter 笔记本T7 此处
“每个人都会死——但在美国,向出价最高者提供最好的延期机会一直被认为是合理的。”—査蒂·史密斯,暗示
有什么问题?
动机
2017 年,我定期在布鲁克林的绿点(Greenpoint)看物理治疗师,每次 80 美元。我的情况没有任何好转,在我第八次坐在椅子上,双臂被毫无意义的电击后,我决定是时候开始见其他人了。我的下一站是中城东区的一位职业治疗师,每次治疗收费约 300 美元。新的设施肯定比绿点的好,设备也更好。甚至有一台机器,我可以把胳膊伸进去,玉米皮碎片会飞来飞去打它们。现代医学!我每两周 300 美元的按摩手臂和剥玉米皮是由一个英俊的年轻人管理的,所以这次我坚持了整整一年。不幸的是,在此期间,我还做了一次无效的 19000 美元的手术(谢天谢地,由保险支付)。但最后时刻到来了。不是他,是我。我没有好转。
最终找到我的诊断的职业治疗师带来了一大笔费用——在上东区一家世界著名的医院,每次治疗大约 550 美元。当然,在我见过她之前,我不知道要花多少钱,因为医疗系统是疯狂的,买家通常在购买已经完成之前不知道价格。谢天谢地,我的雇主给我提供了不错的健康保险,这意味着四次治疗后,我基本上可以“免费”去了。想到困惑的安泰保险精算师可能会看到一个 23 岁的女人每年花费公司超过 20,000 美元的医疗索赔,我不禁笑了。我的方式坚持到男人我猜?
这段旅程,从绿点 80 美元的无用医疗护理到上东区 550 美元的改变生活的护理,让我对这个我们生活所依赖的古怪系统思考了很多。当然,更好的东西通常比更差的东西更值钱。我明白了。但是我在相当剧烈的疼痛中度过了两年。一想到挡在我和一生的痛苦之间的只是 3 万美元,我就觉得恶心。(有人打电话给上东区的医生……)
如果我真的有很高的https://www.healthcare.gov/glossary/high-deductible-health-plan/#:~:text=For 2020%2C the IRS defines,or %2413%2C800 for a family.】免赔额,或更高的最高自付费用,或没有足够的可支配收入来支付这些自付费用,或我处于工作空档期,或我正在接受医疗补助(世界著名医院不接受医疗补助),或该医院被我的雇主保险计划视为“网络外”怎么办?我可能负担不起 550 美元的预约,更不用说去看 15 位医疗专业人士(以及毫无意义的 19,000 美元的手术),这位职业治疗师改变了我的生活。除非我幸运地拥有一个病毒式的 GoFundMe 页面,否则我会陷入一生的痛苦之中。这是美国。《独立宣言》说了什么——生命、自由和对止痛药的追求?
该项目
纽约拥有一些世界上最优秀、最聪明的医学专业人士。我知道是因为我现在已经见过超过 15 个了,其中有几个非常非常聪明。其中一个非常刻薄,我甚至说“你能不能不要再对我刻薄了?”所以我们就不算她了。不幸的是,对纽约的病人来说,最好的往往也是价格最高的。我亲眼看到同样的服务在三个社区之间的价格差异有多大,所以我想把我的医疗保险索赔分析的下一部分重点放在纽约市。作为复习,请查看我的 项目概述 以及 我的分析 的第一部分,其中查看了各州和不同时间的价格差异(关键要点:从 2012 年到 2017 年的平均价格。所分析的服务价格变化为+16%,而 CPI(通货膨胀)+7%)。
许多因素 导致美国医疗费用高昂。吝啬的保险计划、持续的药品价格上涨和不断上升的医疗索赔是许多促成因素中的三个。我想看看这第三个因素,因为它通常让人感觉不受保险公司和大型制药公司的攻击。这可能是因为我们爱我们的医生、护士和其他医疗专业人员,不想责怪他们。对大多数人来说,这并不是他们的错。他们甚至可能不知道他们的病人被要求支付的费用(尽管,他们可能应该知道)。真正的问题可能是大型医院和医疗保健集团在行业中的整合,他们吞并了私人诊所,抬高价格,并额外收取“设施费”(整合是有据可查的 这里 ,而设施费在新冠肺炎时代成为头条新闻,见 这里;还可以看看《华尔街日报》最近的一篇文章,内容是 2021 年的一项新规定,要求医院公布秘密协商的价格。我在一家私人诊所的理疗师(可以说她的工作并不出色,但还不错):80 美元。我在世界著名医院的职业治疗师。$550.
在此分析中,我看一下 2017 年医疗保险提交的索赔 从医疗保险中心获得的&医疗补助服务、种族人口统计和收入。我会在一个区和一个社区的水平上查看所有这些数据。目的是不仅找出价格如何不同,而且可能找出它们不同的原因。从 NYS 健康部门的网站上获得了一张邮政编码到社区的映射图。 2018 年收入数据按邮政编码 从国税局获得。 按邮政编码 统计的种族人口统计数据是从 2019 年美国社区调查中获得的。
方法学
2017 年医疗保险索赔数据被过滤到纽约市,并通过邮政编码映射到街区和区。保留了 25 种最常见的提供者类型及其提供的 5 种最常见的服务。在少于 15 个(共 42 个)社区中提供的任何提供商/服务组合都将被取消。这样,我们可以降低异常值扭曲邻域统计数据的风险。我们剩下了 111 个提供商/服务组合,原来是 125 个。收入和种族人口统计数据同样映射到街区和自治市,并重新计算(因为所有数据最初都是按邮政编码计算的)。对于我们的收入指标,我们使用国税局的税收数据计算每个社区的“调整后人均总收入(AGI)”。这可能不是最理想的统计数据,因为它会被曼哈顿的超高收入者扭曲,但这是我在这样一个粒度级别上能找到的最好的数据。中等收入和中等家庭收入似乎不是最好的衡量标准,因为儿童也需要医疗保健。人均收入似乎是最好的选择。
一旦一切都绘制出来,我们就可以使用一系列的熊猫分组和合并来执行简单的计算。每项服务的中间价格是按纽约市、区和社区计算的。对“调整后的”每项服务的中间价格也是如此,它是通过比较社区/自治市的人均 AGI 与纽约市的人均 AGI 来计算的。以 AGI 区公园的人均 2.7 万美元和纽约市 AGI 的人均 5.3 万美元为例。如果在区公园提供的手术价格为 100 美元,其调整后的价格将为 100 美元(53k 美元 27k 美元)=~200 美元。区公园的人均收入大约是纽约市总和的一半,所以它的医疗服务费用大约是当地居民的两倍(有点像我们在调整生活成本)。*
一旦计算出纽约市、行政区和社区的每项服务的调整/未调整中值价格,我们就可以计算出每项服务与纽约市调整/未调整中值之间的差异。然后,我们可以对每个社区/自治市提供的所有服务的差异进行平均。最后,我们计算每个社区/自治市每个提供商/服务有多少人,将其与纽约市的总统计数据进行比较,并取每个社区/自治市提供的所有服务的平均值。****
对于每个具有长名称的区和街区,我们只剩下三个重要的指标,因此我将它们缩写为:
- 平均值。每项服务的平均价格与纽约市平均价格的差异:平均值。中间价差异
- 平均值。每项服务调整后的中间价格与纽约市调整后的中间价格之差:平均值。调整后的中间价差异
- 平均值。每个提供商/服务的人数与纽约市中位数的差异:平均值。每个供应商的人员差异。
结果
自治市统计
每个纽约市行政区的主要统计数据
我们可以看到,即使在调整人均 AGI 之前,布朗克斯区的医疗保险索赔相对较高,平均为+33%,高于纽约市的中位数。一旦我们对 AGI 的人均收入进行调整,由于财富集中在曼哈顿,除了曼哈顿(为-51%)之外,几乎每个区的人均收入都在飙升。布朗克斯调整后的房价现在是令人震惊的+404%。如果我们看看平均值。每个供应商的人数差异,皇后区似乎有最不堪重负的供应商,为+259%。曼哈顿在这一指标上再次表现良好,平均每个供应商少了 67%的人。
这些都是有趣的结论,但是任何去过纽约的人都知道这些区包含了非常广泛的社区。就拿曼哈顿来说——从唐人街,到地狱厨房,到东哈莱姆区,到上东区,这些街区会有很大的不同。我们将使用 散景 来创建这些统计数据的交互式 choropleth 地图(参见 jupyter 笔记本 获取代码),并将使用 数据面板 将地图嵌入到本文中,如下所示。
Choropleth 地图#1:每项服务的中间价格(未调整)
平均值。中值价格的差异,按邻近地区(边界代表邮政编码;多个邮政编码可以是同一街区的一部分)
从左右滚动,我们可以看到,平均。绿点的中间价格差为-14%,而 UES 为+7%。然而,最值得注意的是,我们可以看到皇后区东南部(+69%)和布朗克斯公园/福特汉姆社区(+60%)的房价有多高。
Choropleth 地图#2:每项服务的中间价格(调整后)
平均值。调整后的中值价格差异,按邻近地区(边界代表邮政编码;多个邮政编码可以是同一街区的一部分)
在这张地图上,我们可以通过考虑收入来更实际地看到价格差异。当然,人们可以去城市的其他地方寻求护理。但是,如果它就在附近,显然更容易寻求护理,获得护理的障碍更少。使用调整后的中间价格,很明显曼哈顿大部分地区的医疗费用相对较低。这个岛的最北端是个例外:东哈莱姆区、中部哈莱姆区和因伍德/华盛顿高地,在+200%/+130%/+233%。然而,即使是这样,与布朗克斯相比也相形见绌。布朗克斯公园/福特汉姆现在是+654%,它以南的社区都在+300–350%的范围内徘徊。另一个异常值是东纽约和新地段,为+337%。
平均值比较:白人≥50%的社区与白人< 50%的社区
白人人口≥50%和白人人口< 50%的社区中关键变量的平均值比较
在上表中,我们比较了白人人口比例≥50%的社区(13 个社区)与人口比例为<50% white (29 neighborhoods). Note that all values should be interpreted as percentage points, except AGI per Capita (dollars) and AGI Log (the log of AGI per Capita). In this table, we can see that in majority-white neighborhoods, mean AGI per Capita is $136k vs. $32k, Avg. Difference in Median Price is -4.5% vs. +4.4%, Avg. Difference in Adjusted Median Price is +26% vs. +205%, Avg. Difference in People per Provider is +34% vs. +71%, and the percentage of all provider/service combos offered in the neighborhood (out of all 111 provider/services included in analysis) is 68% vs. 53%.
This indicates that healthcare conditions in majority-white neighborhoods are more optimal: lower prices (both unadjusted and adjusted for AGI), fewer people per provider, and more services offered. However, these are small sample sizes and we should check for significance before we take anything too seriously. Simple t tests (using scipy) are run to check if the differences in means are statistically significant. In the end, only AGI Per Capita and Avg. Difference in Adjusted Median Price are significant (p<0.05; last column).
Checking for Correlations
Correlation matrix of our variables of interest
Before we run our regression analyses to see which variables can help us predict healthcare price disparities, it helps to first create a correlation matrix to gauge the strength and direction of relationships between our variables. In this heatmap, blue indicates a positive correlation and red a negative one. Again, we really only care about significant relationships between variables. Therefore, in the table below we include not only the correlation coefficient (as seen in the matrix above), but also the p value (calculated using pearsonr from scipy.stats) and R² (correlation coefficient²). As a reminder: we like p values when they are <0.05 and R² can be defined as the percentage of variation in y that can be explained by x ( (见此处 )的社区的关键变量的平均值。
我们感兴趣的变量之间的显著相关性(p<0.05)
在上表中,我们只包括显著的相关性(p <0.05), and sort high to low on R². The strongest relationships are between the Avg. Difference in Adjusted Median Price and White population rate, Hispanic/Latino population rate, and AGI per Capita. Interestingly, the percent of the population that is white or Hispanic/Latino appear to explain MORE of the Avg. Difference in Adjusted Median Price (higher R²) than AGI per Capita (lower R²), even though AGI per Capita was part of the adjusted price calculation in the first place. So there might be something about a high white or Hispanic/Latino population, beyond just AGI per Capita, that explains differences in median Medicare claims?
Let’s take the variables with the strongest correlations and visualize them with a Pair Plot, so we can see how linear (or non-linear) their relationships seem to be.
Pair Plot of correlated variables to visualize their linear (or non-linear) relationships
The positive linear relationship between the Hispanic/Latino population and adjusted claims is very apparent. The same can be said for the negative linear relationship between the white population and adjusted claims. On the other hand, the relationship between AGI per Capita and adjusted claims seems to be logarithmically decreasing — not really a linear relationship. This might explain why the correlation between the two variables was not the strongest in the correlation matrix above, although we might have expected it to be. That matrix was looking at linear correlation, not logarithmic correlation. To account for this, we will take the log of our AGI per Capita variable and add it to our pandas dataframe for further analysis.
Next, we’ll run a few multiple regressions to see if we can take a closer look at the size and significance of the effects of these different variables on Avg. Difference in Adjusted Median Price.
Running Regressions
Before we run our regressions, let’s first make sure there isn’t too much “collinearity” among our independent variables. For example, if the percent of the population that is white is too highly correlated with the percent of the population that is Black, it wouldn’t make sense to include both variables in our regression because they would essentially both be saying the same thing (in opposite directions). This could mess with our model. One way of checking for this is to see if any correlation coefficients are ≥0.8. We didn’t have that in our correlation matrix, but a second check is to look at “方差膨胀因子”(VIFs) 。如果任何变量的 VIF ≥ 5,我们就有麻烦了。
检查我们感兴趣的变量的共线性
看起来共线性没有问题,所以我们可以进行第一次回归。我们将检验人口统计学是否有助于预测调整后的价格差异。为此,我们将对因变量(平均值)进行多元线性回归。调整后的中值价格差异)对我们的三个独立变量(黑人、西班牙裔/拉丁裔和白人的人口百分比)的影响。
回归:平均值。人口统计学上调整后的中间价格的差异;调整后的 R = 0.65
我们看到,随着西班牙裔/拉丁裔人口比例的增加,价格也在上涨。调整后的中间价格的差异,其他条件相同)。白人人口的情况正好相反(+1%白人= -3.15%平均。调整后的中间价格的差异,其他条件相同)。黑人/非洲裔美国人在人口中所占的百分比在这一回归中没有显著影响(p > 0.05)。重要的是,这个回归的调整后 R 是 0.65。在我们的下一次回归中,我们将删除“黑人或非裔美国人(%)”作为独立变量(因为它没有显著影响),并查看它如何影响我们调整后的 R 值。
回归:平均值。西班牙裔/拉丁裔和白人人口比例调整后的中间价格差异;调整后的 R = 0.66
当我们从回归中去除“黑人或非裔美国人(%)”时,调整后的 R 略有改善,我们剩下两个与第一个回归相似大小的显著影响。调整后的 R 现在是 0.66。西班牙裔/拉美裔平均+1% =+2.92%。调整后中值价格的差异,其他条件相同。平均+1%的白人= -3.20%。调整后中值价格的差异,其他条件相同。
一个 0.66 的调整后 R——这还不错。这意味着只要看看西班牙裔/拉丁裔和白人的百分比,我就可以解释平均年龄变化的 66%。调整后中间价的差异。但也许人口统计学的整体效应真的只是被人口统计学和人均 AGI 之间的关系所调节。https://www.federalreserve.gov/econres/notes/feds-notes/disparities-in-wealth-by-race-and-ethnicity-in-the-2019-survey-of-consumer-finances-20200928.htm按种族和民族划分的财富差距是有据可查的。我们在计算调整后的汇率时使用了人均 AGI 汇率,因此人均 AGI 汇率显然会对调整后的汇率产生影响。为了探索这种潜在的中介效应,我将使用弗吉尼亚大学描述的 中介分析策略 。
首先,我将根据西班牙裔/拉美裔和白人的人口比例回归 AGI 的人均人口比例。对于这种回归,我将使用人均 AGI 的日志。记住,在我们的配对图中,我们发现了人均 AGI 和平均收入之间的对数递减关系。调整后中间价的差异。
回归:AGI 人均对西班牙裔/拉丁裔和白人人口百分比的对数;调整后的 R = 0.56
在上面的回归中,我们可以看到,在其他条件相同的情况下,人口中的白人比例对人均 AGI 对数有显著影响。然而,在其他条件相同的情况下,西班牙裔/拉美裔人口的百分比对 AGI 人均对数没有显著影响。因此,我们之前发现的白人比例对平均年龄的显著负面影响。调整后的中位数价格的差异可能只是由于白人人口比例与人均 AGI 人口比例的密切关系。
我们可以通过把人均 AGI 的对数加到我们的原始回归中来验证这一点。如果任何其他条款失去了他们的意义,一旦 AGI 人均对数被包括在内,这意味着他们对平均的影响。调整后的中位数价格的差异实际上是由人均 AGI“调节”的。我不知道你怎么想,但我天生不会用对数思考。在我们的结果中,我们如何解释人均 AGI 对数的系数?AGI 人均收入每增加 1%,平均收入就会增加。调整后的中间价的差额(无论系数是/100)。
回归:平均值。AGI 人均对数调整后的中间价格与西班牙裔/拉丁裔和白人人口百分比的差异;调整后的 R = 0.76
在这次回归中,白人所占的百分比已经失去了它的显著性(p > 0.05),但是西班牙人/拉丁美洲人所占的百分比仍然保持着它的显著性,甚至当 AGI 人均对数被加入到回归中时。这似乎表明,在西班牙裔/拉美裔人口较多的地区,价格较高的原因不仅仅是 AGI。也许这解释了我们在布朗克斯看到的更高的价格,不仅是 AGI 调整后的索赔(+404%),而且是未经调整的索赔(+33%),因为布朗克斯大多数是西班牙裔/拉丁裔(56%)。解释这一回归的结果,调整后的 R 为 0.76。西班牙裔/拉美裔人口每增加 1%,平均。在所有其他因素不变的情况下,调整后的价格中位数的差异增加了 2.3%。AGI 人均收入每增长 1%,人均收入就增长 1%。调整后的中位数价格差异减少 0.9%。
结论
- 除了关注保险公司和大型制药公司,我们还需要关注不断上涨的医疗价格和差距
- 纽约是世界上最好的城市,但它的众多行政区和社区之间的医疗价格差距确实很大
- 无论你怎么看,布朗克斯区的医疗保健价格都更高
- 平均值。调整后的中间价格的差异可以很好地解释,只要看看白人人口的百分比和西班牙裔/拉丁裔人口的百分比(0.66 R)
- 人口中白人百分比对平均年龄的影响。调整后的中位数价格的差异实际上是由人均 AGI 的影响调节的(更多的白人=更高的人均 AGI =更低的调整后索赔,主要是因为更高的 AGI)
- 即使控制人均 AGI,拉美裔人口较多的地方(如布朗克斯)也有较高的索赔中位数(拉美裔/拉美裔人口每增加 1%,索赔中位数就增加 2.3%,其他条件相同)
感谢您的阅读,并保持健康!