TowardsDataScience 博客中文翻译 2016~2018(一百零六)
解释:一个基于风格的 GANs 生成器架构——生成和调整真实的人造脸
NVIDIA 针对生成式对抗网络的新型架构
生成对抗网络(GAN)是机器学习中一个相对较新的概念,于 2014 年首次引入。他们的目标是合成人工样本,如图像,这些样本与真实图像无法区分。GAN 应用程序的一个常见示例是通过从名人人脸数据集学习来生成人工人脸图像。随着时间的推移,GAN 图像变得越来越逼真,但其主要挑战之一是控制其输出,即改变面部图像中的特定特征,如姿势、脸型和发型。
NVIDIA 的一篇新论文,一个为 GANs ( StyleGAN )设计的基于风格的生成器架构,提出了一个解决这个挑战的新模型。StyleGAN 逐渐生成人工图像,从非常低的分辨率开始,一直到高分辨率(1024×1024)。通过单独修改每个级别的输入,它控制在该级别中表达的视觉特征,从粗略特征(姿势、脸型)到精细细节(头发颜色),而不影响其他级别。
这种技术不仅可以更好地理解生成的输出,还可以产生最先进的结果——比以前生成的图像看起来更真实的高分辨率图像。
Source: StyleGAN
背景
每个 GAN 的基本组件是两个神经网络——一个从头合成新样本的生成器,一个从训练数据和生成器输出中提取样本并预测它们是“真”还是“假”的鉴别器。
发电机输入是随机向量(噪声),因此其初始输出也是噪声。随着时间的推移,当它收到来自鉴别器的反馈时,它学会了合成更“真实”的图像。通过将生成的样本与真实样本进行比较,鉴别器也会随着时间的推移而改进,使生成器更难欺骗它。
GANs overview
直到 2018 年,研究人员一直难以生成高质量的大图像(如 1024×1024),当时英伟达首次用 ProGAN 解决了这一挑战。ProGAN 的关键创新是渐进式训练——它从用非常低分辨率的图像(例如 4×4)训练生成器和鉴别器开始,每次都添加更高分辨率的层。
这种技术首先通过学习甚至在低分辨率图像中出现的基本特征来创建图像的基础,并且随着时间的推移随着分辨率的增加学习越来越多的细节。训练低分辨率图像不仅更容易和更快,它也有助于训练更高的水平,因此,总的训练也更快。
ProGAN overview
ProGAN 可以生成高质量的图像,但与大多数模型一样,它控制所生成图像的特定功能的能力非常有限。换句话说,这些特征是纠缠在一起的,因此试图调整输入,即使是一点点,通常也会同时影响多个特征。一个很好的类比是基因,改变一个基因可能会影响多个特征。
ProGAN progressive training from low to high res layers. Source: (Sarah Wolf’s great blog post on ProGAN).
StyleGAN 的工作原理
StyleGAN 论文提供了 ProGAN 图像生成器的升级版本,重点是生成器网络。作者观察到,如果使用得当,ProGAN 渐进层的潜在好处是它们能够控制图像的不同视觉特征。图层(和分辨率)越低,其影响的要素就越粗糙。本文将这些特征分为三种类型:
- 高达 82 的粗分辨率-影响姿势、一般发型、脸型等
- 162 到 322 的中等分辨率-影响更精细的面部特征、发型、眼睛睁开/闭上等。
- 642 到 10242 的精细分辨率-影响配色方案(眼睛、头发和皮肤)和微观特征。
新的发电机包括对 ProGAN 发电机的几个补充:
映射网络
映射网络的目标是将输入向量编码成中间向量,中间向量的不同元素控制不同的视觉特征。这是一个重要的过程,因为用输入向量控制视觉特征的能力是有限的,因为它必须遵循训练数据的概率密度。例如,如果黑头发的人的图像在数据集中更常见,则更多的输入值将被映射到该要素。因此,该模型无法将部分输入(向量中的元素)映射到特征,这种现象称为特征纠缠。然而,通过使用另一个神经网络,该模型可以生成不必遵循训练数据分布的向量,并且可以降低特征之间的相关性。映射网络由 8 个完全连接的层组成,其输出ⱳ与输入层的大小相同(512×1)。
The generator with the Mapping Network (in addition to the ProGAN synthesis network)
样式模块(AdaIN)
AdaIN (自适应实例标准化)模块将映射网络创建的编码信息ⱳ转换为生成的图像。该模块被添加到合成网络的每个分辨率级别,并定义该级别中的特征的视觉表达:
- 卷积层输出的每个通道首先被归一化,以确保步骤 3 的缩放和移动具有预期的效果。
- 使用另一个全连接层(标记为 a)将中间矢量ⱳ变换为每个通道的比例和偏差。
- 比例和偏移向量移动卷积输出的每个通道,从而定义卷积中每个滤波器的重要性。这种调谐将来自ⱳ的信息翻译成视觉表示。
The generator’s Adaptive Instance Normalization (AdaIN)
移除传统输入
大多数模型以及其中的 ProGAN 使用随机输入来创建发生器的初始图像(即 4×4 级别的输入)。StyleGAN 团队发现,图像特征是由ⱳ和阿丹控制的,因此初始输入可以被省略,并用常数值代替。虽然这篇论文没有解释为什么它提高了性能,但一个安全的假设是它减少了特征纠缠——网络只使用ⱳ学习更容易,而不依赖于纠缠的输入向量。
The Synthesis Network input is replaced with a constant input
随机变化
在人的面部中有许多方面是小的并且可以被看作是随机的,例如雀斑、头发的精确位置、皱纹,这些特征使得图像更加真实并且增加了输出的多样性。将这些小特征插入 GAN 图像的常用方法是向输入向量添加随机噪声。然而,在许多情况下,由于上面描述的特征纠缠现象,很难控制噪声效果,这会导致图像的其他特征受到影响。
StyleGAN 中的噪声添加方式与 AdaIN 机制类似,即在 AdaIN 模块之前的每个通道中添加一个缩放后的噪声,并稍微改变它所操作的分辨率级别特性的视觉表达。
Adding scaled noise to each resolution level of the synthesis network
风格混合
StyleGAN 发生器在合成网络的每个级别中使用中间向量,这可能会使网络了解到级别是相关的。为了降低相关性,该模型随机选择两个输入向量,并为它们生成中间向量ⱳ。然后,它用第一个级别训练一些级别,并(在随机点)切换到另一个级别来训练其余的级别。随机开关确保网络不会学习和依赖级别之间的相关性。
虽然它没有提高所有数据集的模型性能,但这个概念有一个非常有趣的副作用-它能够以连贯的方式组合多个图像(如下面的视频所示)。该模型生成两幅图像 A 和 B,然后通过从 A 获取低级特征并从 B 获取其余特征来组合它们。
W 中的截断技巧
生成模型的挑战之一是处理训练数据中表现不佳的区域。生成器无法学习它们,也无法创建类似的图像(反而会创建难看的图像)。为了避免生成差的图像,StyleGAN 截断中间向量ⱳ,迫使它接近“平均”中间向量。
在训练模型之后,通过选择许多随机输入来产生“平均”ⱳavg;用映射网络生成它们的中间向量;并计算这些向量的平均值。在生成新图像时,不直接使用映射网络输出,而是将ⱳ转换为ⱳ_new=ⱳ_avg+𝞧(ⱳ -ⱳ_avg),其中𝞧的值定义了图像与“平均”图像的距离(以及输出的多样性)。有趣的是,在仿射变换块之前,通过对每个级别使用不同的𝞧,该模型可以控制每组特征与平均值的距离,如下面的视频所示。
Tweaking the generated image by changing the value of 𝞧 in different levels
微调
StyleGAN 在 ProGAN 基础上的其他改进是更新几个网络超参数,如训练持续时间和损失函数,并替换从最近邻到双线性采样的向上/向下缩放。虽然这一步对模型性能很重要,但它没有什么创新性,因此这里不做详细描述(本文的附录 C)。
An overview of StyleGAN
结果
该论文展示了两个数据集的最新成果——由名人图像组成的 CelebA-HQ,以及由“普通”人图像组成的更加多样化的新数据集 Flickr-Faces-HQ (FFHQ)。下图显示了模型不同配置的 Frèchet 初始距离( FID )得分。
The performance (FID score) of the model in different configurations compared to ProGAN. The lower score the better the model (Source: StyleGAN)
除了这些结果之外,该论文通过在卧室图像和汽车图像的其他两个数据集上展示其结果,表明该模型不仅仅适用于人脸。
特征解开
为了使关于特征分离的讨论更加量化,本文提出了两种新颖的方法来测量特征解缠:
- 感知路径长度—在两个随机输入之间进行插值时,测量连续图像(其 VGG16 嵌入)之间的差异。剧烈的变化意味着多个特征一起改变,并且它们可能纠缠在一起。
- 线性可分性-将输入分类为二元类的能力,例如男性和女性。分类越好,特征的可分性越强。
通过比较输入向量 z 和中间向量ⱳ的这些度量,作者表明ⱳ的特征明显更加可分。这些指标还显示了与 1 或 2 层相比,在映射网络中选择 8 层的优势。
实施细节
StyleGAN 使用 8 Tesla V100 GPUs 在 CelebA-HQ 和 FFHQ 数据集上训练了一周。它在 TensorFlow 中实现,并将是开源的。
结论
StyleGAN 是一种突破性的论文,不仅可以生成高质量和逼真的图像,还可以对生成的图像进行高级控制和理解,使生成可信的假图像变得比以前更加容易。StyleGAN 中介绍的技术,尤其是映射网络和自适应标准化(AdaIN),将可能成为 GANs 中许多未来创新的基础。
要了解最新的深度学习研究,请订阅我在 LyrnAI 上的简讯
解释:RL 中的好奇心驱动学习
随机网络蒸馏探索
近年来,强化学习已经被证明是一种强大的技术,可以解决有持续回报的封闭任务,最常见的是游戏。该领域的一个主要挑战仍然是在行动的外部反馈(奖励)稀少或不存在的情况下训练模型。最近的模型试图通过创建一种内在的奖励机制来克服这一挑战,这种机制主要被称为好奇心,奖励发现新领土和州的模型。
OpenAI 的一篇新的论文通过随机网络蒸馏探索(RND)提出了一种内在奖励的新方法。该模型试图预测一个给定的状态以前是否被见过,并对不熟悉的状态给予更大的奖励。
该模型显示了几个雅达利游戏的最先进的结果,包括蒙特祖马的复仇,这是众所周知的 RL 算法很难。它也相对简单,并且已经证明在包括分散注意力的背景噪声的环境中是有效的。
背景
强化学习(RL)是一组以奖励为导向的算法,这意味着它们通过最大化从环境中获得的奖励来学习如何在不同状态下采取行动。对他们来说,一个具有挑战性的测试平台是 30 多年前开发的 Atari 游戏,因为它们提供了丰富的视觉输入(每帧 210X160X3)和一系列对人类来说很难的任务。
这些游戏在复杂性和外部奖励的频率上有所不同。在《越狱》中,每次击中砖块都会有奖励,而在《蒙特祖马的复仇》和《其他》中,一个关卡只有少量奖励。例如,蒙特祖马的复仇是众所周知的挑战,因为它需要长时间(数百步)和复杂的动作组合来通过致命的障碍并找到奖励。下面的动画说明了游戏之间的区别。
Breakout — The agent receives external rewards frequently, one for each brick
Montezuma’s Revenge — The only external reward is received when picking up the key
为了在没有频繁外部奖励的游戏中取得成功,代理人必须探索环境,希望发现稀疏的奖励。这些场景在现实生活中很常见,从在房子里找到丢失的钥匙到发现新的癌症药物。在这种情况下,代理人被要求使用内在奖励,同时主要独立于外在奖励。有两种常见的带内在奖励的 RL 方法:
- 基于计数的方法,对以前访问过的州进行计数,并对新的州给予更大的奖励。这种方法的缺点是,随着可能状态数量的增加,它往往变得不那么有效。
- 另一种方法是“下一状态预测”,在这种方法中,模型试图预测下一状态,采取行动转移到下一状态,然后将与预测状态相比的误差降至最低。通过探索,更多的状态变得已知,误差下降。
这些方法比只基于外在奖励的模型(如著名的 DQN 和 A3C 模型)表现得更好,但仍然比普通人差。
一般来说,当使用内在奖励时,对未来状态的评估有三个可能的错误来源:
- 不熟悉的状态错误-模型无法从以前访问过的状态归纳到新的状态,导致未来状态预测中的高错误。通过反复发现新的状态并从中学习,模型逐渐减少了这种错误。
- 随机噪声——这也称为电视噪声问题,其中环境的一部分会产生随机噪声(就像房间里有一台呈现白噪声的电视)。这导致许多状态对于代理来说是新的,下一个状态通常是不可预测的,并且与代理的动作无关。
- 模型约束—模型的架构是有限的,不能足够准确地概括环境以预测下一个状态。例如,预测下一个状态所需的神经网络的层数和大小是未知的。
RND 是如何工作的?
具有内在奖励的 RL 系统使用不熟悉状态误差(误差#1)进行探索,并且旨在消除随机噪声(误差#2)和模型约束(误差#3)的影响。为此,该模型需要 3 个神经网络:一个为给定状态生成恒定输出的固定目标网络**,,一个试图预测目标网络输出的预测网络**,以及一个决定代理下一步行动的策略网络。
目标和预测网络
通过计算两个网络输出之间的差异,目标和预测网络被用来为不熟悉的状态产生更大的内在奖励。网络具有相同的大小和架构——卷积编码器(CNN ),后面是全连接层,用于将状态嵌入特征向量 f 。然而,它们之间有一个重要的区别:
- 目标网络是一个具有固定随机权重的神经网络,从未被训练过。因此,对于给定状态(输入),其输出是恒定的,但在不同状态之间是可变的:对于任何时间步长 I,fi(x)=fj(x ),对于任何两个不同的输入,fi(x)fi(y)。
- 预测网络被训练来预测目标网络的输出。每个状态被输入到两个网络中,预测网络被训练以最小化它们的输出(ri)之间的差异(MSE)。
The target and prediction networks
随着越来越多的状态被输入到系统中,当预测网络接收到已知状态时,它在预测目标网络输出方面变得更好。当到达以前访问过的州时,代理会收到一点奖励(因为目标输出是可预测的),并且代理没有动力再次到达这些州。换句话说,与普通模型不同,智能体不是试图根据当前状态和动作来预测下一个状态,而是试图预测未来状态的新颖性。
目标预测架构有几个好处:
- 在用随机噪声(来自固定的稳定分布)对状态进行足够的训练之后,预测网络能够更好地预测目标网络的输出。随着预测误差的减小,智能体对噪声状态的吸引力会比其他未探测的状态小。这减少了电视噪音错误(#2)。
- 在下一步预测模型中,事先不知道需要哪种体系结构(层数、层大小等)来模拟动作的结果。然而,预测器网络只需要预测目标网络的结果。通过具有与目标网络相同的架构,它应该能够正确地学习熟悉状态的输出。这“解决”了模型约束错误(#3)。
- 它让代理人倾向于在游戏中存活,因为死亡迫使它回到熟悉的状态。其他“基于好奇心”的 RL 方法也有这种优势。
该模型的一个挑战是,随着更多的状态变得熟悉,内在奖励会减少,并且可能在不同的环境中变化,这使得选择超参数变得困难。为了克服这一点,内在奖励在每个更新周期中被标准化。
政策网络
策略网络的作用是根据当前状态及其内部模型决定下一步行动,该模型是根据以前的状态训练的。为了做出这个决定,它使用了一个输入嵌入器和一个策略优化器:
输入嵌入器
输入嵌入器将环境状态编码成特征。本文比较了两种体系结构——CNN 或 CNN 与循环层(GRU 细胞)的混合。重现层被认为有助于通过捕捉游戏的更长上下文来预测下一个动作,例如,在当前状态之前发生的事件,并且在大多数情况下确实被发现比只有 CNN 的层表现得更好。
PPO
训练策略模型的一个主要问题是收敛性,因为策略往往会因为奖励的一次更新而发生剧烈变化。例如,在一些架构中,一个糟糕的插曲(游戏)可以完全改变你的策略。因此,在嵌入层之上,网络有一个邻近策略优化器 ( PPO ),它根据嵌入状态预测下一个动作。PPO 的主要贡献是通过限制连续策略更新之间的差异,在没有激进更新的情况下安全地优化策略。
为了更新政策,PPO 首先需要估计给定状态的未来内在和外在报酬(“价值头”)。单独处理每种类型的奖励可以更灵活地确定每种类型对政策的影响以及每种类型的计算方式:
- 内在奖励是在固定的一批时间步长上计算的,例如 128 个时间步长,而不管代理是否已经在游戏中“死亡”。研究发现,这种独特的方法(非情节性的)能够实现更好的探索,因为它鼓励代理采取可能揭示新状态的冒险行动。如果内在奖励是偶发的,这些行为可能会结束游戏,从而结束奖励。
- 外在奖励会在整个剧集中计算,直到特工死亡。使用非偶发性奖励可能会导致代理“黑”游戏。比如通过寻找轻松快捷的奖励,然后自杀。
下图显示了策略网络和整个架构:
The policy network
The RND architecture
注意事项:
- 本文中的 PPO 是使用行动者-批评家模型(A3C)实现的。然而,它可以与任何优势功能一起使用。
- PPO 的另一个好处是,它允许多个时期的训练,每个时期都有小批量的输入,从而提高了训练效率。限制策略更新可以确保即使有多个时期,总的变化也不会太大。
结果
本文将 RND 模型与最先进的(SOTA)算法进行了比较,并将两个相似的模型作为消融试验:
- 没有内在探索奖励的标准 PPO。
- 基于前向动力学误差的内含报酬 PPO 模型。这种模型根据当前状态和动作预测下一个状态,并使预测误差最小化,这就是内在报酬。
这位 RND 特工在 6 场比赛中的 3 场比赛中取得了最先进的成绩,并在蒙特祖马的《复仇》中取得了比“普通人”更好的成绩。然而,与其他 SOTA 算法相比,它在另外两个游戏中的性能明显较低。这篇论文没有解释这种技术不太有用的游戏的本质。
Scores comparison of various RL algorithms (source: OpenAI’s blog)
结论
RND 模式体现了近年来在艰苦探索游戏中取得的进步。该模型的创新部分,即固定和目标网络,由于其简单性(实现和计算)及其与各种策略算法一起工作的能力,是有前途的。
另一方面,还有很长的路要走——没有一个模型可以统治所有人,不同游戏之间的表现也各不相同。此外,虽然 RNN 可能有助于保持更长的背景,但全球勘探仍然是一个挑战。需要长期关系的场景,例如使用在第一个房间找到的钥匙打开最后一扇门,仍然无法实现。
要了解最新的机器学习研究,请订阅我在 LyrnAI 上的简讯
解释:GPipe——使用流水线并行技术训练巨型神经网络
近年来,机器学习数据集和模型的规模一直在不断增加,允许在广泛的任务中改善结果。与此同时,硬件加速(GPU、TPU)也在改进,但速度明显较慢。模型增长和硬件改进之间的差距增加了并行性的重要性,即在多个硬件设备上训练单个机器学习模型。一些 ML 架构,尤其是小型模型,有助于并行性,可以在硬件设备之间轻松划分,但在大型模型中,同步成本会导致性能下降,从而妨碍它们的使用。
Google Brain 的一篇新论文 GPipe 提出了一种模型并行性的新技术,允许在多个硬件设备上训练大型模型,性能提高近 1:1(论文显示在 4x 硬件上有 3.5 倍的处理能力)。GPipe 库将是开源的,它自动分析 TensorFlow 神经网络模型的结构,并将训练数据和模型委托给多个硬件设备,同时应用独特的反向传播优化技术。
GPipe 帮助 ML 模型包含更多的参数,从而在训练中获得更好的结果。为了证明该技术的有效性,谷歌团队创建了一个更大版本的 AmoebaNet,即 2017 年 ImageNet 获奖者,以更大的图像(480×480)作为输入,并在 ImageNet,CIFAR-10,CIFAR-100 和其他计算机视觉指标上取得了最先进的(SOTA)结果。
背景
机器学习中的并行通常分为两类:
- 模型并行性-当在训练中使用模型并行性时,机器学习模型被划分到 K 个硬件设备上,每个设备持有模型的一部分。一种模拟并行性的简单方法是通过在每个设备上简单地托管 N/K 层(“级”)来将 N 层神经网络分成 K 个设备。更复杂的方法通过分析每一层的计算复杂度来确保每个设备处理相似的计算复杂度。标准模型并行性允许训练更大的神经网络,但是由于设备不断地相互等待,并且在给定时间只有一个设备可以执行计算,因此性能受到很大影响。
- 数据并行性-在数据并行性中,机器学习模型在 K 个硬件设备上复制,一个小批量的训练样本被分成 K 个微批量。每个设备执行微批次的向前和向后传递,并且当它完成该过程时,它与其他设备同步更新的模型权重,然后计算整个微批次的更新权重。在每次小批量计算结束时,K 个模型的重量都是同步的(相同值)。
虽然微批处理允许并行,但在使用模型并行时,每个阶段自然仍需要等待前一阶段的结果,从而导致闲置的“泡沫”,如随附的图像所示。在图中,F0,i-F3,I 是跨越四个阶段的单个微批处理的成员,而 Fi,0-Fi,3 是在单个阶段中执行的四个微批处理计算。
Model + Data Parallelism (GPipe: Huang et al. 2018)
尽管存在气泡问题,但数据并行可能是有效的,但它还会遇到一个额外的问题——通信开销。随着模型的增长和硬件变得更快,在设备之间同步整个模型的要求成为训练过程中的瓶颈,大大降低了训练速度。随附的图像举例说明了在大型神经网络中,通信开销如何占据了大部分训练时间。通信开销的现象鼓励创建非常大的小批量,但是这些对于训练网络来说通常是错误的选择,并且可能在生产中呈现较差的结果。
PipeDream: Fast and Efficient Pipeline Parallel DNN Training
GPipe 的工作原理
GPipe 同时使用模型和数据并行,这种组合通常被称为“流水线”。它为以前的流水线技术提供了两个关键贡献——自动并行和设备内存优化。
自动并行
该软件接收神经网络的结构、小批量和可用于计算的硬件设备的数量作为输入。然后,它会自动将网络层划分为阶段,将小批量划分为微批量,并将它们分布在各个设备上。为了将模型分成 K 个阶段,GPipe 在给定其激活函数和训练数据内容的情况下估计每一层的成本。虽然这篇论文没有详细说明如何在 GPipe 中实现这一点,但一个常见技术是通过神经网络运行数据样本,测量每一层的计算时间,并相应地进行划分。GPipe 接收每一层的可选成本估计函数作为输入,允许更复杂的技术来改进其内部机制。
设备内存优化
当在神经网络中计算反向传递时,需要网络的正向传递激活来执行计算。通常,这意味着对于神经网络中 N 层和 L 层大小的微批次,O(N×L)个激活在正向传递之后被保存在设备存储器中,为反向传递做准备。
GPipe 使用了一种不同的方法,应用了一种有趣的计算-内存权衡——它不是将 NxL 激活保存在内存中,而是只将 N 个激活保存在 stage 的最后一层(stage =层组)。在这种情况下,每次反向过程开始时(从最后一层开始),都会重新计算正向过程激活并保存在内存中。当单个样本的反向通过结束时,存储器中的激活被丢弃,并为下一个样本的反向通过重新计算。使用这种方法,设备内存一次只保存一组激活,以进行 O(N)次转发为代价获得了宝贵的内存。因为一般的硬件趋势是设备速度比设备内存增长得更快,所以这种权衡通常是有用的。
GPipe 应用
在论文中,研究人员将 AmoebaNet 从 1.553 亿个参数扩展到 5.57 亿个参数,并插入 480×480 ImageNet 图像作为输入,而不是标准 AmoebaNet 模型使用的降采样 331×331 图像。结果是 ImageNet 前 1 名的准确率(84.3%对 83.5%)和前 5 名的准确率(97.0%对 96.5%)有所提高,标志着一个新的最先进水平。
使用扩展的 AmoebaNet 模型进行迁移学习,研究人员在 CIFAR-10、CIFAR-100、牛津-IIIT Pets、Stanford Cars 和 Food-101 数据集上取得了最先进的(SOTA)结果。该模型在两个数据集(FGVC Aircraft 和 Birdsnap)中取得的结果不如最先进的结果,这可能是因为这些数据集中最先进的模型利用了除 ImageNet 数据之外来自 Google Image Search 的 980 万张预训练图像。
实施细节
GPipe 是用 TensorFlow 写的,会开源。该技术并不是 TensorFlow 独有的,也可以在其他平台上实现。
结论
作为一个开源库,GPipe 将允许机器学习从业者以相对较低的成本训练大得多的模型。可以肯定的是,结果将是新的大量大型机器学习模型,它们将获得优于现有模型的结果,以及与缩小图像相反的全尺寸图像数据的使用增加。
虽然对每个人都有用,但数据并行性的这一突破自然会为拥有大量计算和数据的大型组织提供特殊优势。
保持最新机器学习研究的更新,订阅我们的简讯在LyrnAI
特别感谢本文主要作者黄阳平对 GPipe 工作的宝贵见解。
向小学生解释人工智能
最近,我被邀请给五六年级的小学生(9-11 岁)讲计算机和人工智能。我花了很多时间向一系列不同的人解释 AI 和 ML,但从来没有向这么年轻的观众解释过!我在网上找不到太多的灵感,所以想出了自己的素材。这是我的课程计划大纲,每节课我都要花 30 分钟。
1。简介 我的日常工作包括语音识别,所以我先介绍自己,然后问全班有多少人曾经对着电脑或设备说话来完成某件事——通常我会让全班大多数人举手。
对于一些背景,我包括一点历史。小学生是在智能手机和语音计算的环境中长大的,他们通常不知道技术发展有多快。在撰写本文时,Y5 类诞生于 2008/2009 年。相比之下,iPhone 于 2008 年推出,Siri 于 2011 年在其上发布。
2。计算机编程 第一个讨论的话题是计算机如何通过编写规则(或程序)被编程去做事。用这种方法可以编写非常复杂和看似智能的计算机程序。到了 Y5、6 岁,这个学校的孩子已经上了用 scratch 编程的课。他们知道如何根据指令编写计算机程序,以及如何容易将这些指令弄错,从而使计算机无法按照您的意图运行。
3。识别猫咪的规则 人们喜欢在网上分享照片,他们分享了很多猫咪的照片!有一件事可能会让计算机变得人工智能,那就是能够判断一张照片是不是一只猫。我和全班一起头脑风暴,想出一些规则写在黑板上,我们可以用它们来识别照片中的猫。我们在之前的课程中提出了一些规则:
我们不能在计算机中直接实现这些规则,但它们能让人们理解这个想法。
接下来我们来看一组播放“猫不猫”的幻灯片。我的幻灯片有一系列图片——有些很容易识别是不是猫,有些是模糊不清或姿势滑稽的猫,还有一些是和猫有一些相同特征的其他动物。他们让孩子们思考如何定义这个任务(大猫算不算猫?),edge cases(一只猫的画法呢?)以及你真正需要的那种规则(你到底怎么区分小熊猫和猫?).
4。智能计算机 在这之后,我问孩子们是否认为我们的规则是好的还是坏的。大多数人承认,我们的规定并未涵盖所有图片,因此本可以更好。
有些任务,如视觉和听觉,是不可能写出计算机可以遵循的规则的。我们需要一种不同的方法。我们让计算机学习如何从数据中完成任务,而不是编写规则。为此,我们采集了大量数据(图像、音频、视频等)。)并让人们给它贴上标签。对于图像,人们可能会给每幅图像贴上什么物体被描绘的标签。从这个“标签数据”的数据库中,我们可以训练一台机器来学习构成猫的图片的模式。一旦计算机从这些训练数据中学习,我们就可以利用计算机建立的模型,用它来识别图片中从未见过的猫。
识别图片中的猫或其他物体可能看起来很无聊,但是有很多方法可以在现实世界中使用这项技术。很多人正在研究的一个例子是在自动驾驶汽车中识别出你面前的是什么。另一个是帮助拯救濒危野生动物,通过识别动物并在野外计数。
5 .讨论和问题 我最后讨论了这个班将来会制造什么样的智能机器人。如果我对他们的建议有所了解,我会谈谈那个地区已经在建的项目。
我听到的想法包括:
- 帮助盲人的计算机:例子包括微软的视觉人工智能或文本到语音技术,它可以大声朗读文本
- 太空旅行:我们已经将人类送上了月球,并将火星车送上了火星,但是人工智能可以帮助我们进行更进一步的探索,比如火星车导航或者识别太空中的物体,
- 照顾住院病人:计算机可以通过多种方式帮助医院从手术到诊断再到管理,从而节省医生和护士与病人相处的时间。
- 会烹饪的机器人:这种处理原料的机器人很难制造,但是有一些例子
- 做作业的电脑。我通常不会指出像阿列克谢这样的语音助理已经可以回答很多问题了
当我问班主任时,他们通常只想要一台智能电脑来帮助他们批改作业!
在讨论中,我还加入了其他几点讨论:
- 电脑并不总是对的。当计算机从数据中学习时,我们总是知道它们会犯一些错误。
- 有些事情是电脑做不到的,例如,判断某人是否在说谎。一般来说,如果一个人很难做到,那么机器也很难学习。
- 技术有好的一面,也有坏的一面。有时,班上的人会想出别人觉得令人毛骨悚然的想法,这有助于说明问题。
额外背景 对于那些有兴趣了解更多的人来说,图像识别有着悠久的历史,并且在最近几年得到了很好的研究。一个名为 ImageNet 的图像数据库已经成为许多物体识别学术研究的基础。该数据库有超过 20,000 个类别的数百万张图片。
2012 年,花了 16000 台电脑才学会如何识别一只猫。近年来,研究人员也在研究更困难的任务,如区分 5000 种动物、识别和跟踪视频中的物体或自动对照片中发生的事情进行深入描述。
原为 2018 年 12 月 17 日在http://mycomputerdoesntlisten.wordpress.com发表。
用通俗易懂的语言解释机器学习
在最近的演讲活动中,我遇到了一个两难的问题,即试图从概念上解释机器学习,而不牺牲对我试图推销的应用程序的关注,无论是创业风险还是研究项目。由于比赛时间的限制以及在进行推销时简洁的普遍需要,机器学习是一个特别棘手的短语,因为其过程背后的复杂性。
随着“机器学习”作为一个流行词获得关注,这种解释变得越来越重要。观众很少会假装知道机器学习算法将如何工作,但他们经常会期望一个普通人可以理解和理解的解释。这使得能够将机器学习作为一个概念和单个算法分解为可消化的部分变得至关重要。传递这些易于管理的信息的最简单的方式通常是通过相关的类比和轶事。
因此,让我们从一个最相关的轶事开始对机器学习的简单解释:数学课。数学教学的一般框架是给学生许多练习题和答案。是的,老师可能会事先教授这个概念,但是为了举例,我们假设这个概念没有被教授。每个练习题都对学生(机器学习算法)在答案(标签)旁边观察到的信息片段(有点像输入特征)进行编码。我们可以称这个学习过程为算法的训练。
在大量的练习题之后,我们假设的学生应该能够找到某种模式来解决问题。因此,我们对学生进行测试,给他们一份试题,并将生成的答案与实际答案进行比较(类似于对算法的测试)。评估学生的准确性给了我们一个衡量学生和给他们的练习题的有效性的方法。
我们也知道,每个学生往往有不同的学习风格。同样,每个机器学习算法都有不同的方式来尝试在输入数据中找到模式。这些不同的风格使得不同的学生在特定的科目上特别精通,就像一些 ML 算法对于特定的数据类型更加有用和健壮一样。
总结一下类比,机器学习算法就像数学学生,他们被给予大量的实践问题,并被指示通过找到这些问题中的信息及其相关答案之间的模式来找到解决这些问题的方法。能够找到最有效的数据(练习题)以反馈给最有效的算法(学习风格)是很重要的,因为这是产生最佳性能的地方。
显然,这种解释避免了算法开发和课堂教学的细微差别,但对于不熟悉这个概念的人来说,这是一种快速解释机器学习的便捷方式。为什么这很重要?能够清楚地解释一个非常复杂的主题(一个普通人可以识别为复杂的主题)可以让观众更容易相信你的可信度。事实证明,复杂概念的简化与大多数人的预期相反。这种简化并没有让机器学习策略看起来更强大,而是向观众传达了这样一种信息:你不仅仅是引擎盖下的一名工程师,你也是一个不仅仅能够理解代码的人。
可能存在更合适的类比来解释机器学习,这肯定是演讲者和演示者应该考虑的事情。你的听众的经历将永远是决定他们是否理解你的解释的主要因素,因此理解该场合的共同主题并根据听众的共性调整类比是至关重要的。总的来说,记住这些考虑因素,并不难做出解释,将概念及其应用传递给受众,帮助他们接受主题。无论是数学学生还是企业高管,机器学习都是一个值得分享的想法,只要它对所有参与者都有意义。
解释数据中的矛盾趋势
在我的工作中,我帮助普通人理解复杂的数据。偶尔有人会完全不知所措:他们会观察一段时间的变化,看到总值下降了。但是当他们仔细观察时,他们发现他们使用的每个类别都增加了。他们问,他们的数据有什么问题?
实际上没什么不对。
他们刚刚无意中发现了一个极其普遍的统计悖论;但它可能会一直令人困惑。以下是我如何试图解释正在发生的事情,这样他们就可以继续他们的生活(并向他们的老板汇报结果)。
从一个例子开始:
Median values in two different years, for two groups, and overall.
我们可以清楚地看到这个悖论:
- A 组下降
- B 组拒绝
- 总的来说,整个系统增加
这个例子很普通,这些数据可以在任何地方出现:公司的薪水,网络流量,病人对治疗的反应。你可能会问,我们怎么能同时看到这两种趋势呢?
这是怎么回事?
首先让我们看一下数据集(我已经把它保持得很小了):
The data, split by years, with groups shown by color.
这很容易地证实了柱状图中的汇总趋势:绿色组下降,红色组也下降。但是其他的事情也在发生。
各组的大小不同
在第 1 年,数据以红色数据为主(B 组),但这在第 2 年发生了变化,因此绿色数据更常见。中间数据点是红色的,然后变成绿色。我们可以看到绿色比红色高。这意味着整体中位数必须上移(这同样适用于平均值或其他集中趋势的衡量标准)。
**悖论就这样解决了。**两种变化同时发生:
- 个别测量的实际值增加。由于通货膨胀,工资上涨了。交通速度加快。病人会好起来。
- 我们没有仔细控制我们测量的内容,并且样品的成分发生了变化。
在一个理想的、科学严谨的世界里,我们不会让第二种情况发生。相反,我们会设计一个实验,在所有类别中有相同数量的受试者(“控制”这些差异)。但是在观察研究中,以及在混乱的现实世界中,我们经常做不到这一点。即使在科学领域,你也可以在事实发生后意识到,主题并不像你想象的那样相似。所以我们使用现有的数据——但是我们在解释这些数据时必须更加老练。
所以看似矛盾的模式实际上是两种变化同时出现:
群体平均水平确实下降了,全球平均水平确实上升了。“悖论”是我们天真的假设,即这些必须以同样的方式进行。
解决办法?
您可以通过在未来更多地控制您的组来避免这种情况,确保您每次都有相同的数量。
在报告您的结果时,您可能希望坚持总体平均值或组平均值,这取决于您试图从数据中了解什么。如果问题是,“这些病人治疗有效吗?”答案是肯定的,因为两组都有进步。如果问题是,“我所有的病人有多健康?”你要说“更差”是因为整体平均水平。
当向他人报告这些结果时,你可以试图隐藏一种效果,而强调另一种效果。但是你可能也需要变得更复杂一点——给出一个和这个很像的解释。
(这种效应有时被称为逆转悖论或辛普森悖论。)
下面的样本数据集:
year group value
1 A 7
1 A 8.5
1 A 10
1 A 11.5
1 A 13
1 B 32
1 B 34
2 A 5.5
2 A 7
2 A 8.5
2 B 27
2 B 28.5
2 B 29.5
2 B 33
解释强化学习:主动还是被动
这篇文章假设你熟悉强化学习(RL)和马尔可夫决策过程的基础知识,如果没有,请先参考这篇前一篇文章。
在这篇文章中,我们将探究,
- 解决一个 RL 问题需要哪些要素?
- 什么是被动和主动强化学习,我们如何比较这两者?
- 常见的主动和被动 RL 技术有哪些,适用的场景有哪些?
解决 RL 问题需要哪些要素?
让我们考虑一个问题,代理可以处于各种状态,并且可以从一组动作中选择一个动作。这类问题称为 序贯决策问题 。一个**的数学框架就是捕捉这样一个完全可观测的、非确定性的环境**,具有马尔科夫转移模型和加性报酬的主体在其中行动。MDP 的解是一个 最优策略 ,它指的是最大化总累积报酬的每个状态的行动选择。因此,代表代理环境的 转换模型 (当环境已知时)和决定代理在每个状态下需要执行什么动作的 最优策略 是训练代理学习特定行为的必需元素。****
Fig 1: Markov Decision Process (source: wikipedia)
什么是被动和主动强化学习,我们如何比较这两者?
主动强化学习和被动强化学习都是强化学习的类型。在被动 RL 的情况下,代理的策略是固定的,这意味着它被 告知做什么 。与此相反,在主动 RL 中,代理 需要决定做什么 ,因为没有固定的策略可供其操作。因此,被动 RL 代理的目标是执行固定的策略(动作序列)并对其进行评估,而主动 RL 代理的目标是采取行动并学习最优策略。
有哪些常见的主动和被动 RL 技术?
被动学习
由于代理的目标是评估最优策略有多好,代理需要学习每个状态 s 的期望效用 Uπ(s) 。这可以通过三种方式实现。
直接效用估算
在这个方法中,代理执行一个试验序列或运行(状态-动作转换序列,一直持续到代理到达终端状态)。每个试验给出一个样本值,代理根据样本值估计效用。可以计算为样本值的**移动平均值。主要缺点是这种方法错误地假设 状态效用是独立的 ,而实际上它们是 马尔科夫 。还有,收敛慢。
假设我们有一个 4x3 的网格作为环境,代理可以在其中向左、向右、向上或向下移动(一组可用的操作)。跑步的例子
总奖励从 (1,1) = 0.72 开始
**2。自适应动态规划
ADP 是一种比直接效用估计更智能的方法,因为它通过将状态的效用估计为处于该状态的奖励和处于下一状态的预期折扣奖励之和来运行试验以学习环境模型。
其中 R(s) =处于状态的报酬 s , P(s'|s,π(s)) =过渡模型, γ =贴现因子, Uπ(s) =处于状态的效用 s' 。
可以使用值迭代算法来解决。该算法收敛很快,但是对于大的状态空间来说,计算可能变得相当昂贵。ADP 是一种基于模型的方法,需要环境的转换模型。无模型方法是时间差异学习。
Fig 2: AI playing Super Mario using Deep RL
**3。时间差分学习(TD)
TD 学习不要求代理学习过渡模型。更新发生在连续的状态之间,代理仅更新直接受影响的状态。
其中 α =学习率,它决定了向真实效用的收敛。
ADP 用所有后继状态来调整 s 的效用,而 TD learning 用单个后继状态 s’的效用来调整。TD 的收敛速度较慢,但在计算方面要简单得多。
主动学习
具有探测功能的 ADP
由于主动代理的目标是学习最优策略,代理需要学习每个状态的期望效用并更新其策略。可以使用被动 ADP 代理完成,然后使用值或策略迭代,它可以学习最佳操作。但是这种方法导致了一个贪婪的代理。 因此,我们使用一种方法,对未探索的动作给予较高的权重,对具有较低效用的动作给予较低的权重。
其中 f(u,n) 是随着期望值 u 增加并且随着尝试次数 n 减少的探索函数
R+ 是一个乐观的奖励,Ne 是我们希望代理在每个状态下被迫选择一个动作的次数。 探索功能将被动代理转化为主动代理。
②。问学**
Q-learning 是一种 TD 学习方法,它不需要代理学习过渡模型,而是学习 Q 值函数 Q(s,a) 。
q 值可以使用下面的等式来更新,
可以使用以下策略选择下一个操作,
同样,这比 ADP 计算简单,但速度较慢。
Table 1: Comparison of active and passive RL methods
我推荐以下资源来更深入地理解这些概念,
向孩子(或你的老板)解释监督学习
既然知道了机器学习是什么,那就来认识一下最简单的那种。我在这里的目标是让所有人和(几乎)所有年龄的人都熟悉它的基本术语:实例、标签、特征、模型、算法和监督学习。
例子
请看:四个实例!
实例也被称为“实例”或“数据点”或“观察值”
数据表
当我们把这些例子放到表格中时,它们看起来像什么?遵循惯例(因为礼貌是好的),每一行都是一个实例。
数据不好看吗?但是我们到底在看什么?让我们从两个特殊的列开始:一个惟一的 ID 和一个每个实例的标签,因为这次我们很幸运。
标签
标签是正确答案。当我们向计算机展示这样一张照片时,我们希望它能学会输出什么,这就是为什么有些人更喜欢用“目标”、“输出”或“反应”这样的术语。
特征
其他栏里有什么?像素颜色。不像你,电脑把图像看成数字,而不是漂亮的灯光。你看到的是像素的红-绿-蓝值,从图像的左上角开始向下。不相信我?尝试将我的数据表中的值输入到这个 RGB 色轮中,看看它会给出什么颜色。想知道如何从照片中获取像素值?回头看看我的代码这里。
你知道什么很酷吗?每次你看一张数码照片,你都在分析数据,理解以一串数字形式存储的东西。不管你是谁,你已经是一名数据分析师了。你这个摇滚明星,你!
你已经是数据分析师了!
这些像素值是计算机将要学习的输入。我不太喜欢机器学习的名称(“特征”),因为这个词意味着各种学科中的各种事物。你可能会看到人们用其他词来代替:“输入”、“变量”或“预测”。
模型和算法
我们的特征将形成模型的基础(这是食谱的一个花哨的词),计算机将使用它从像素颜色到标签。
模型只是“配方”的一个花哨的词
但是怎么做呢?这是机器学习算法的工作。你可以在我的另一篇文章中看到它是如何在幕后工作的,但现在,让我们使用一个现有的令人敬畏的算法:你的大脑!
监督学习
我希望你成为我的机器学习系统。再次浏览实例并做一些学习!这是什么?
Classify this image using what you’ve learned from the examples above.
"布洛克尔"吗?没错。你能行的!你刚才做的是监督学习,牛逼!你现在已经体验到了最简单的学习方式。如果你能把你的问题框定为监督学习,那是个好主意。其他的更难…所以让我们来认识一个:无监督学习(本系列文章的第 2 部分)。
**总结:**如果算法对每个实例都有正确的标签,你就在处理监督学习。稍后,它将使用模型或配方来标记新的实例,就像您所做的那样。
In this video, your author gives you a quick refresher on how supervised learning (the topic of this article) differs from unsupervised learning.
感谢阅读!YouTube 课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
Enjoy the entire course playlist here: bit.ly/machinefrie…
与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。
解释这个笑话:“当公司说他们需要‘人工智能’的时候,他们真正需要的是一个带有 GROUP BY 的 SELECT 子句。”
Mat Vellosso 最近发推文:
它像病毒一样传播开来。嗯,就像一个无聊的笑话一样,奥巴马的不痛不痒的母亲节推特被十倍于奥巴马的人喜欢。尽管如此,将近一半喜欢 Mat Velloso 的推文的人也转发了它。
像所有好的笑话一样,这里有几个层次和一个巨大的真理内核。所以,让我成为那个家伙,那个解释笑话并从中获取所有乐趣的家伙。
长话短说:如果你只有几个独立的输入特征,SELECT + GROUP BY 可能和一个奇特的机器学习模型一样好。只有当特征数量增加,因素变得依赖时,你才需要机器学习。
大数据分析
假设您想预测在伦敦租了一辆自行车的人是否会在 10 分钟内归还自行车。你认为人们会在周末进行更长时间的骑行,所以在工作日进行短距离快速骑行的概率更高。你可以用一个 SELECT GROUP BY 来完成:
#standardsql
CREATE TEMPORARY FUNCTION dayOfWeek(ts TIMESTAMP) AS
(
['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'][ORDINAL(EXTRACT(DAYOFWEEK FROM ts))]
);WITH bikeshare AS (
SELECT
IF(duration < 600, 1, 0) AS short_ride,
dayOfWeek(start_date) AS dayofweek
FROM `bigquery-public-data.london_bicycles.cycle_hire`
)SELECT
dayofweek,
SUM(short_ride)/COUNT(1) AS frac_short_rides,
COUNT(1) AS num_all_rides
FROM
bikeshare
GROUP BY
dayofweek
ORDER BY num_all_rides DESC
运行这个,我们对< 10 min rides will be 33% on weekdays and 24% on weekends:
We wanted to find the likelihood that bicycles are returned in less than 10 minutes and we just computed it in brute force over the entire historical dataset. The reason this works is that there were 2.9 million rentals on Sunday and 23.6% of them were returned. Once you have Big Data, it is super-easy to make statistically significant inferences.
Sparse input features
What if you add one more factor though? In addition to day of the week, we would like to use the station that the bicycle is being rented from as an input feature. Perhaps rentals in the city center are likely to be short. We can simply 的预测通过在我们的组中添加第二个字段:
SELECT
dayofweek, start_station_name,
SUM(short_ride)/COUNT(1) AS frac_short_rides,
COUNT(1) AS num_all_rides
FROM
bikeshare
GROUP BY
dayofweek, start_station_name
ORDER BY num_all_rides DESC
桌面很好:
你需要考虑到在海德公园租自行车的人会长期保管它们。但是最底层…你在莫尼耶路有严重的问题:
你愿意根据 1、2 个历史数据点来做预测吗?这就是机器学习的用武之地——以智能的方式处理像车站这样的稀疏输入。一个好的 ML 算法不是使用由 GROUP BY 指定的硬阈值,而是“借用”其他站的可能性,并在 Monier Road 使用它们。也许您会添加一个指示车站附近人口密度的要素,然后 ML 模型将借用具有相似人口密度的车站的可能性。
我还没毁了这个笑话吗?
.
.
.
.
.
.
.
好吧,那么,让我来为你毁了它——就像所有好笑话一样,这个笑话在仔细检查后会崩溃。Mat 到底在说什么?一半关注人工智能的公司有如此多的数据行,他们可以简单地进行分组?这样的公司也没有足够的列,他们需要一个 ML 模型?
探索性分析:美国数据科学家的薪水
在我之前的帖子中,我谈到了在全美国征集 Indeed.com 的数据科学家职位。虽然我能找到 10,500 多份清单,但其中很少包含工资数据,许多工资是按小时、月或周计算的。在对数据进行大规模清理后,我只剩下 493 份工资用于建模。薪酬中位数为 10 万美元,其中 236 家高于中位数,257 家低于中位数。我很兴奋能去做模特。然而,在进入大结局之前,我想看看我还能从这些数据中获得什么样的见解。这个任务要求我从我的数据科学家工具箱中拿出我最喜欢的数据探索工具之一——Tableau!
当我将数据加载到 Tableau 时,我最感兴趣的是了解数据科学家的工资如何因地点而异,以及哪些地点的独特工作列表数量最多。
这里我们有一张各州平均工资的热图,深色代表高工资,浅色代表低工资。正如我们从地图上看到的,弗吉尼亚州的数据科学家工资似乎最高,平均为 182,000 美元。最差的是佛罗里达州,平均工资为 57253 美元。
通过观察各个城市的平均工资情况,我可以进一步细分这些数字。在收入最高的弗吉尼亚州,麦克林、莱斯顿和安布勒的平均工资最高,分别为 19.6 万美元、19 万美元和 17.5 万美元。在西海岸,旧金山以 171,245 美元的平均工资紧随其后。从较低的范围来看,佛罗里达州的 Dania Beach 以 30k 美元排名垫底。然而,来自佛罗里达州的其他人成功地将他们的数字拉高了一点,珊瑚墙和迈阿密分别为 51,311 美元和 91,000 美元。
在如此大的工资范围内,我想看看我实际上是在做什么样的工作。毕竟,弗吉尼亚在顶端,但是我的样本实际上处理了多少独特的工作列表。当你考虑到其他地方有更多的空缺职位需要填补时,少量的列表并不算多。
上图中,我们有一张地图,按照各州独特工作列表的数量来划分大小,并按照平均工资来着色。颜色从暗红色到暗绿色不等,最暗的绿色代表最高工资,最暗的红色代表最低工资。在这里,我们对之前的数据进行了分析。虽然弗吉尼亚的工资可能是最高的,但我们只看了 3 个独特的工作列表,这实际上将弗吉尼亚排在了机会的最后。加州似乎保持了它以前的记录,有来自 24 家不同公司的 33 个不同的职位,平均工资为 12.5 万美元。此外,虽然纽约州和伊利诺伊州可能不是薪酬最高的州(11.5 万英镑不是我抱怨的数字),但它们的机会数量确实最多,分别有 55 个和 37 个独特的职位空缺。
探索性分析和回归模型帮助抗击寨卡
Alerta Zika!是一项合作活动,旨在探索数据和技术改善寨卡病毒应对措施的潜力。美洲开发银行在包括里约热内卢市政厅和该市一些主要大学在内的几个合作伙伴的支持下组织了这次活动。从 2016 年 12 月 2 日到 3 日,大约 10 个注册团队探索了流行病学、环境和社会因素,以了解和解释这种疾病的进展。总结里约热内卢抗击寨卡疾病的努力,是一天半的辛苦工作。我们获得了里约热内卢市 2015 年和 2016 年期间登记的所有寨卡、登革热和基孔肯雅病病例的数据集。为了了解数据,我们的团队开始“玩”数据集并检查变量。在这样做的过程中,我们对寨卡的进化模式及其在 2016 年前几个月爆发期间的作用产生了幻想。
我们的假设是,疾病传播模式及其在时间、城市地区和天气方面的相关性可以用作一个指标,以显示疾病在何时何地传播,并帮助城市官员决定分配资源的最佳方式。我们当时设定的目标是,绘制一幅里约热内卢地图,展示寨卡病毒在不同时间和温度下的历史演变。在与市卫生秘书代表的几次交谈中,我们想知道一个社会发展指标是否可以提供关于传播模式的见解。我们决定将人类发展指数(HDI)——在巴西被称为 IDH——作为一个社会参数。
然后,我们将坐标(纬度和经度)、案件发生的日期、四季温度以及里约关于收入、教育水平和寿命的社会发展指标确定为目标变量。我们的初步任务是创建一个由里约热内卢城市地图和数据框组成的网格,以聚集来自不同数据集的变量子集。我们执行探索性分析的第一个目标是探索分布的形状。网格帮助我们检查箱子的位置;探索约 400 米的区域,这是蚊子的活动范围,并在更广阔的区域聚集患者病例。这也使我们能够检查疾病在整个城市的传播范围,并确定大多数病例发生的地区。
通过进行时间序列分析,我们能够确定温度和病例数之间的相关性。在这一点上,了解蚊子的生命周期是有价值的。埃及伊蚊在从 23 摄氏度到 28 摄氏度(大约 73 到 82 华氏度)的温度变化中茁壮成长。低于或高于这一阈值几度并不一定会杀死蚊子,但会使环境对其发展更不舒适,从而延缓其进化。从卵中的病毒接种到一个个体中,有 20 到 25 天的时间,所以前一个月的蚊子负责本月的病人。从下面的曲线图可以看出,通过逐月比较全市的疾病病例和前一个月每天的温度变化,3 月和 4 月期间的疫情(曲线图 3 和 4)遵循了整个 2 月和 3 月观察到的最佳条件,在这两个月的大部分时间里观察到了 23 至 28 摄氏度的阈值。红圈对应的是病例最多的地区。
剧情一
剧情二
剧情三
剧情四
剧情五
剧情 6
剧情 7
这让我们获得了第一个有意义的发现:上个月的气温似乎会影响本月的病例数量。
当我们将注意力转移到手头的社会指标数据时,我们能够识别出一种奇怪的行为。暴发期间的一些关键地区具有低 IDH 系数的相似性。下面的情节提供了直观的支持。橙色圆圈的大小与 IDH、较小的圆圈/下 IDH 的等级相关,反之亦然。
剧情 8
上图中突出显示的区域对应马雷(一个社区),城市的远北区和远西区。与该市其他地区相比,这些地区的社会指标水平较低。
尽管收入似乎不是影响疫情爆发的社会影响因素——从下面的图表中可以看出——但将该市最富裕的南区行为与 3 月和 4 月的情况进行比较,可以看出一个特点。在这个特殊的领域,存在着巨大的经济差异。最高档的地址位于一些贫民窟的步行距离内(贫民窟通常位于该地区周围的山上),那里的 IDH 与之前地块上的相似)。
剧情 9
从这一观察中,我们得出了第二个有意义的见解:在疫情爆发期间,社会指标(IDH)似乎在病例数量最多的地区起到了影响作用。
随着我们进一步分析,其他奇怪的行为引起了我们的注意。即使气温从 23 至 28 摄氏度的阈值下降,一些地区仍然出现在最高得分病例中(从下面 5 月至 7 月的比较中可以看出)。
剧情 10
这些地区的共同点是都被树林和森林包围着。这一共同因素提供了我们提供的第三个有意义的见解:一些复发疾病的病灶区似乎生长在树林和森林地区的周围或附近。
探索性分析通常是预测建模的良好开端,因为它有助于进一步理解数据集并总结其主要特征。探索数据和制定可能导致新的数据收集和实验的假设是从数据中提取有用信息的主要组成部分;提出假设;并支持选择适当的统计工具和技术。我们在数据考察中的主要目标是设定有助于理解过去行为的第一步,以便为未来的“作物”准备“种子”。我们的第三名是我们的骄傲,似乎表明这个目标已经实现。
数据远征后
我们继续探索数据,并汇总其他变量。我们的目标是获得一些可以添加到初始探索性分析中的预测模型。这些新的变量是每个街区的人口和降雨量。我们还添加了更多关于 2016 年最后几个月和 2017 年 1 月初的温度数据。
第一种选择是简单的线性回归,使用每个邻域的可变人口来预测基于人口的病例。下面是 R 和统计读数中的一些代码块(我们打算在 markdown 文件中显示更多信息,这是一种可以一起显示文本、代码和图表的文件)。
型号:
数据集的快速视图:
“bairro”代表邻里;针对寨卡病例的“casos _ Zika”;“populacao”代表人口。
来自 Rstudio 控制台的一些统计数据:
诊断图
在图 1(残差与拟合值)中,在某一点上,残差沿水平线均匀分布,但也有异常值。在图 2(正态 Q-Q)中,残差似乎正态分布,至少在某种程度上是这样。
情节 1
剧情二
在补充图 1 的图 3(标度-位置)中,一些残差沿预测值范围平均分布,显示出一些同质性。图 4(残差对杠杆)将有影响的观察结果确定为#120 和#23。
剧情三
剧情四
基于当温度阈值在 23 到 28 摄氏度之间时,蚊子的周期更快的理论,我们试图检查降雨是否也有助于繁殖。然后,我们试图确定这两个变量与寨卡病例数量之间的关系。我们的第二个选择是使用多元回归模型来达到这个目标。这种分析是在 Phython 进行的。
下图显示了温度阈值发生率最高的月份是 2015 年 12 月至 2016 年 4 月之间的月份。我们还可以注意到,这一趋势在 2016 年 12 月和 2017 年 1 月初再次出现。
**绿线和红线:**温度阈值
**粉色和灰色线条:**最低和最高温度
接下来的一系列图显示,在显示每周病例数、温度和降雨量的曲线之间存在类似的正趋势。该分析是基于 2016 年疫情爆发期间受到严重影响的 Campo Grande (1)、Santa Cruz (2)和 Guaratiba(3)社区进行的。
**蓝线:**每周病例数
**红线:**温度低于阈值
**黄线:**降雨量
(1)
(2)
(3)
我们决定使用多元回归模型来构建一个预测应用程序。我们通过将实际数据与用于拟合模型的测试数据集中应用的预测数据进行比较的一系列图来测试该模型。
里约热内卢的测试值与预测值
绿点:测试值
灰点:预测值
里约热内卢的真实案例与预测案例
绿线:真实案例
灰色线条:预测案例
里约热内卢真实案例与预测案例对比2015 年 12 月& 2016 年
格林:真实案例
灰色:预测病例
在这个特殊的案例中(上图),我们没有 2016 年 12 月实际寨卡病例的数量,所以我们只预测了病例的数量。
每个街区的分析 : Campo Grande。
Jupyter 笔记本电脑控制台的统计读数:
绿线:真实案例
灰色线:预测病例
每个街区的分析:圣克鲁斯。
统计读数
绿线:真实案例
灰色线:预测病例
每街坊分析:瓜拉蒂巴。
统计读数
绿线:测试值
灰色线:预测值
我们创建了一个原型来应用这个模型。这是一个网站,上面有每月寨卡病例数量的信息,以及显示每个社区实际病例和预测病例的图表。
对于那些想了解它的人来说,这里有和。
利用 R 对 FIFA 18 数据集的探索性分析
[Image [1] (Image courtesy: www.easports.com/fifa)]
随着 2018 年 FIFA 世界杯的临近,我结合了我对足球和数据科学的热爱,使用 r 对 FIFA 18 数据集进行了一次简短的探索性分析。我使用了非身体球员属性,如Name, Age, Nationality, Overall, Club, Value, Wage, Preferred.Positions.
我使用了在 Kaggle 上可用的数据集,其中包含 17,000 多名 FIFA18 中的球员,每个人都有超过 70 个属性。是从网站 SoFiFa 上刮下来的。
如果你对数据可视化感兴趣,你可以看看我的另一篇文章gg plot ' Em All | Pokemon on R。如果你对大数据感兴趣,可以看看我的文章开始使用 Hive 。
在开始分析之前,让我们导入库并读入数据集。
library(ggplot2)
library(dplyr)
library(gridExtra)df = read.csv(file = "CompleteDataset.csv", stringsAsFactors = FALSE)df = tbl_df(df)df <- select(df, ID, X, Name, Age, Nationality, Overall, Club, Value, Wage, Preferred.Positions)
head(df, 10)
First 10 rows of the dataset [Image [2]]
读取数据后,我做的第一件事是将Value和Wage列转换为实际的货币值。我编写了一个函数,将一个向量作为输入,并从列中删除“€”符号,然后乘以适当的数字,将其转换为千(K)和百万(M)。
toNumberCurrency <- function(vector) {
vector <- as.character(vector)
vector <- gsub("(€|,)","", vector)
result <- as.numeric(vector)
k_positions <- grep("K", vector)
result[k_positions] <- as.numeric(gsub("K","", vector[k_positions])) * 1000
m_positions <- grep("M", vector)
result[m_positions] <- as.numeric(gsub("M","",
vector[m_positions])) * 1000000
return(result)
}df$Wage <- toNumberCurrency(df$Wage)
df$Value <- toNumberCurrency(df$Value)
然后,我从Preferred.Positions列的空格分隔值中选取第一个位置值。数据集中的不同位置是:CAM CB CDM CF CM GK LB LM LW LWB RB RM RW RWB ST。
df$Preferred.Positions <- gsub(" ", "", substr(df$Preferred.Positions, 1, 3))
基于上面的Preferred.Positions,我创建了另一个专栏,将这些Preferred.Positions分类为更一般的职位,即GK DEF MID FWD。清理后的数据集如下所示:
x <- as.factor(df$Preferred.Positions)levels(x) <- list(GK = c("GK"),
DEF = c("LWB", "LB", "CB", "RB", "RWB"),
MID = c("LW","LM","CDM","CM","CAM","RM","RW"),
FWD = c("CF", "ST"))df <- mutate(df, Position = x)head(df)
选择Preferred.Position栏中的第一个职位,并创建一个表格,将这些职位分类为更一般的职位,即GK DEF MID FWD。
Cleaned data set [Image [3]]
首先,球员的年龄分布。我们看到有很多 25 岁左右的球员。
g_age <- ggplot(data = df, aes(Age))g_age +
geom_histogram(col="orange", aes(fill = ..count..)) + ggtitle("Distribution based on Age")
Distribution of players based on their age [Image [4]]
下面的图表显示了运动员的年龄和他们的一般比赛位置之间的关系。
g_age +
geom_density(col="orange", aes(fill = Position), alpha=0.5) + facet_grid(.~Position) +
ggtitle("Distribution based on Age and Position")
Distribution based on Age and Position [Image [5]]
根据玩家的总体评分来分配玩家。我们看到大多数玩家的总体评分在 65 分左右。
g_overall <- ggplot(data = df, aes(Overall))g_overall +
geom_histogram(col="orange", aes(fill = ..count..)) + ggtitle("Distribution based on Overall Rating")
Distribution based on overall rating [Image [6]]
来自不同(前 10 名)国家的玩家数量。
countries_count <- count(df, Nationality)top_10_countries <- top_n(countries_count, 10, n)top_10_country_names <- top_10_countries$Nationality
country <- filter(df, Nationality == top_10_country_names)ggplot(country, aes(x = Nationality)) +
geom_bar(col = "orange", aes(fill = ..count..)) + ggtitle("Distribution based on Nationality of Players (Top 10 Countries)")
Number of players from different countries [Image[7]]
我使用 R 中的分位数函数来获得玩家Value和Wage的前 1 %的计数。许多球员的周薪为 10 万€。
top_1_percent_wage <- quantile(df$Wage, probs=0.99)filtered_wage <- filter(df, Wage > top_1_percent_wage)
g_value <- ggplot(filtered_wage, aes(Wage))g_value +
geom_histogram(aes(fill=..count..)) +
ggtitle("Distribution of top 1% value")
Top 1% wage [Image [8]]
大量的球员价值 2500 万€,随着价格的上涨,人数急剧减少。
top_1_percent_value <- quantile(df$Value, probs=0.99)filtered_value <- filter(df, Value > top_1_percent_value)
g_wage <- ggplot(filtered_value, aes(Value))g_wage +
geom_histogram(aes(fill=..count..)) +
ggtitle("Distribution of top 1% Value")
Top 1% player valuation [Image [9]]
为了进一步分析wage和value,我创建了wage_brackets和value_brackets。
wage_brackets是:0–100k 100k-200k 200k-300k 300k-400k 400k-500k 500k+。value_brackets是:0–10M 10–20M 20–30M 30–40M 40–50M 50–60M 60–70M 70–80M 80–90M 90–100M 100M+。
# Create wage bracketswage_breaks <- c(0, 100000, 200000, 300000, 400000, 500000, Inf)wage_labels <- c("0-100k", "100k-200k", "200k-300k", "300k-400k", "400k-500k", "500k+")wage_brackets <- cut(x=df$Wage, breaks=wage_breaks,
labels=wage_labels, include.lowest = TRUE)df <- mutate(df, wage_brackets)# Create value brackets
value_breaks <- c(0, 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000, 100000000, Inf)
value_labels <- c("0-10M", "10-20M", "20-30M", "30-40M", "40-50M","50-60M", "60-70M", "70-80M", "80-90M","90-100M","100M+")value_brackets <- cut(x=df$Value, breaks=value_breaks, labels=value_labels, include.lowest = TRUE)df <-mutate(df, value_brackets)head(df)
Dataset [Image [10]]
很多球员的工资在 0-10 万英镑之间,估值在 0-5000 万英镑之间。绘制这些值会使图形发生很大的倾斜,因为与其他值相比,它们的幅度很大,因此我没有在这里展示它们。
not0To100K <- filter(df, wage_brackets != "0-100k") ggplot(not0To100K, aes(x = wage_brackets)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution of top Wage between 100K-500K+")
Wage between 100k and 500k+ [Image [11]]
moreThan50M <- filter(df, Value>50000000)ggplot(moreThan50M, aes(x = value_brackets)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution of value between 50M-100M+")
Player valuation between 50M-100M+ [Image [12]]
不同工资等级的球员的年龄和总体情况。工资最高的是年龄在 30 岁左右的 85 岁以上的球员。克里斯蒂亚诺罗纳尔多是上面三个紫色点之一。在下面的评论区猜另外两个。:P
g_age_overall <- ggplot(df, aes(Age, Overall))g_age_overall +
geom_point(aes(color=wage_brackets)) + geom_smooth(color="darkblue") +
ggtitle("Distribution between Age and Overall of players based on Wage bracket")
Overall vs Age (Wage) [Image [13]]
玩家的年龄与整体价值的关系图与上面的趋势非常相似。
g_age_overall <- ggplot(df, aes(Age, Overall))g_age_overall + geom_point(aes(color=value_brackets)) + geom_smooth(color="darkblue") +
ggtitle("Distribution between Age and Overall of players based on Value bracket")
Age vs Overall (Value) [Image [14]]
根据运动员的一般比赛位置确定运动员人数。中场人数最多,其次是后卫,前锋,最后是守门员。
ggplot(df, aes(Position)) +
geom_bar(aes(fill = ..count..)) +
ggtitle("Distribution based on General Playing Position")
Number of players per playing position [Image [15]]
根据玩家偏好的游戏位置确定玩家数量。基于上面的图表,我们期望一些特定的中场位置有最高的数量,但是这里中后卫的数量是最高的,其次是前锋的数量。
ggplot(df, aes(Preferred.Positions)) + geom_bar(aes(fill=..count..)) +
ggtitle("Distribution of players based on preferred position")
Number of players per Preferred Position [Image [16]]
让我们看看球员的工资是多少,以及他们基于首选位置的估值。
gf1 <- filter(df, Value<30000000)g1 <- ggplot(gf1, aes(Preferred.Positions)) + geom_bar(aes(fill=value_brackets)) +
ggtitle("Position based on Value (0-50M)")gf2 <- filter(df,Value>30000000)g2 <- ggplot(gf2, aes(Preferred.Positions)) + geom_bar(aes(fill=value_brackets)) +
ggtitle("Position based on Value (50M +)")grid.arrange(g1, g2, ncol=1)
Wage based on Preferred position [Image [17]]
gw1 <- filter(df, Wage > 100000, Wage<300000)g1 <- ggplot(gw1, aes(Preferred.Positions)) + geom_bar(aes(fill=wage_brackets)) +
ggtitle("Position based on Wage (0-100k)") gw2 <- filter(df,Wage>300000) g2 <- ggplot(gw2, aes(Preferred.Positions)) + geom_bar(aes(fill=wage_brackets)) +
ggtitle("Position based on Wage (100k+)")
grid.arrange(g1, g2, ncol=1)
Valuation based on preferred position [Image [18]]
最后,
十大最有价值俱乐部。俱乐部价值通过合计每个俱乐部的球员估价来计算。
group_clubs <- group_by(df, Club)club_value <- summarise(group_clubs, total_val = sum(Value))top_10_valuable_clubs <- top_n(club_value, 10, total_val)
top_10_valuable_clubs$Club <-as.factor(top_10_valuable_clubs$Club)
ggplot(top_10_valuable_clubs, aes(x = Club, y = total_val)) + geom_bar(stat = "identity", aes(fill=total_val)) + coord_flip() + ggtitle("Top 10 valuable clubs")
Top-10 valuable clubs [Image [19]]
感谢您的阅读。你可以在 RPubs 和 GitHub 找到源代码(R-notebook)。你可以在 LinkedIn 和 Twitter 上找到我。
点击查看我的其他博客。
gg plot ' All |口袋妖怪
Pokemon [Image [0] Image courtesy: bdfjade.com/pokemon-pic…]
这篇博文致力于使用口袋妖怪数据集的数据可视化进行分析。第一部分是探索性分析。第二部分有一个机器学习的方面——将口袋妖怪归类为传奇。两篇博文都在 r。
Pokemon Image [1] [Image courtesy]
让我们开始吃吧。:D
导入库。
library(dplyr)
library(ggplot2)
library(gridExtra)
library(tidyr)
library(reshape2)
library(RColorBrewer)
library(ggrepel)
请阅读。csv 文件。
df = read.csv(file="/home/akshaj/projects_R/Pokemon/pokemon.csv")
df = tbl_df(df)
colnames(df)[25] <- "classification"
df$capture_rate <- as.numeric(df$capture_rate)
head(df)
First 5 rows of the dataset [Image [2]]
现在,我们将从整个数据框中选择并使用一些列进行探索性分析。
df = select(df, name, classification, hp, weight_kg,
height_m, speed, attack, defense,
sp_attack, sp_defense, type1, type2,
abilities, generation,is_legendary,
capture_rate)head(df)
Subset of the original dataset [Image [3]]
密度图
各种口袋妖怪属性的密度图。密度图显示了连续时间间隔内的数据分布。这个图表是一个直方图的变体,它使用内核平滑来绘制值,通过平滑噪声来实现更平滑的分布。密度图的峰值有助于显示值在间隔内的集中位置。
density_hp <- ggplot(data=df, aes(hp)) + geom_density(col="white",fill="pink", alpha=0.8) + ggtitle("Density Plot of HP")density_speed <- ggplot(data=df, aes(speed)) + geom_density(col="white", fill="darkorchid", alpha=0.8) + ggtitle("Density Plot of Speed Characterstics")density_attack <- ggplot(data=df, aes(attack)) + geom_density(col="white", fill="orange", alpha=0.7) + ggtitle("Density Plot of Attack Characterstics")density_defense <- ggplot(data=df, aes(defense)) + geom_density(col="white", fill="firebrick", alpha=0.7) + ggtitle("Density Plot of Defense Characterstics")density_height <- ggplot(data=df, aes(height_m)) + geom_density(col="white", fill="slateblue1", alpha=0.8) + ggtitle("Density Plot of Height (m) ")density_weight <- ggplot(data=df, aes(weight_kg)) + geom_density(col="white", fill="mediumturquoise", alpha=0.8) + ggtitle("Density Plot of Weight (kg)")grid.arrange(density_hp, density_speed, density_attack, density_defense, density_height, density_weight, ncol=2)
Density plot of various attributes [Image [4]]
条形图
条形图可能是媒体最常用的统计数据显示方式。条形图将分类数据(因子)按组细分,并用不同长度的条形表示这些数量。我们将绘制每组中的个体数量(也称为频率)。
基于主要和次要类型的口袋妖怪数量
我们观察到最常见的口袋妖怪类型有水、普通和 Bug 。而最常见的二次元口袋妖怪类型是飞。请注意,大量的口袋妖怪没有第二类型。
type_1_poke <- ggplot(data=df, aes(type1)) + geom_bar(aes(fill=..count..), alpha=0.8) + theme(axis.text.x = element_text(angle = 90, hjust = 0)) + ggtitle("Distribution Based on Type-1") + coord_flip()type_2_poke <- ggplot(data=df, aes(type2)) + geom_bar(aes(fill=..count..), alpha=0.8) + theme(axis.text.x = element_text(angle = 90, hjust = 0)) + ggtitle("Distribution Based on Type-2") + coord_flip()grid.arrange(type_1_poke, type_2_poke, ncol=2)
Distribution of Pokemon based on Primary and Secondary type [Image [5]]
基于主要类型的传奇口袋妖怪数量
我们观察到有超过 15 个 Pyschic 类型的传奇口袋妖怪。仙、飞、鬼类型的传说口袋妖怪数量最少。这可能是因为灵媒口袋妖怪很“神秘”。
df %>%
filter(is_legendary==1) %>%
ggplot(aes(type1)) + geom_bar(aes(fill= ..count..)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + ggtitle("Number of Legendary Pokemon Based on Type-1")
Distribution of Legendary Pokemon based on primary type [Image [6]]
每一代引入的初级口袋妖怪数量
该数据集中有 7 代。例如,在第 5 代中引入了大量 Bug 类型的口袋妖怪,而在第 7 代中引入了极少数黑暗类型的口袋妖怪。
这个图表的代码有点长,所以我在这里展示了这个图表。你可以查看完整的代码在这里。
Distribution of primary type per generation [Image [7]]
散点图
散点图是一种二维数据可视化,使用点来表示两个不同变量的值,一个沿 x 轴绘制,另一个沿 y 轴绘制。散点图对于解释统计数据的趋势很有用,并且在您想要显示两个变量之间的关系时使用。散点图有时被称为相关图,因为它们显示了两个变量如何相关
防御 vs 攻击口袋妖怪的特点
这里,传说中的口袋妖怪是红色的,而非传说中的口袋妖怪是蓝色的。对于非传奇的口袋妖怪,攻击和防御属性之间似乎存在正线性关系。这意味着拥有更高攻击属性的口袋妖怪也倾向于拥有更高的防御属性。而传说中的口袋妖怪却没有这种关系。
虽然有一些异常,传说中的口袋妖怪,总的来说有更大的防御和攻击属性。像 Groudon 和 Gyarados(右上)这样的口袋妖怪似乎在攻击和防御方面都很平衡,而像鲤鱼王和凯西这样的口袋妖怪则具有低防御和攻击的特点。你可能会选择格鲁登而不是鲤鱼王来赢得决斗。
ggplot(data=df, aes(attack, defense)) + geom_point(aes(color=is_legendary), alpha=0.8) + scale_color_gradient(low="darkblue", high="red") + ggtitle("Defense vs Attack Characterstics") +
geom_label_repel(data=subset(df,attack > 150 | defense >150 | attack < 25), aes(label=name),
box.padding = 0.35, point.padding = 0.5,
segment.color = 'grey50')
Defense vs Attack attributes [Image [8]]
速度、身高、体重、 Hp V.S .攻击属性
我们在所有 4 个图中观察到的一个共同趋势是,口袋妖怪的速度、身高、体重和 Hp 特性相对于攻击属性增加。
速度与攻击属性之间存在微弱的正相关关系,而身高、体重、血量与攻击属性之间存在较强的正线性关系。
我已经在散点图上标注了传说中的口袋妖怪。《宇宙》和《科斯莫姆》是传奇口袋妖怪的例外。与其他口袋妖怪相比,它们的速度*、、高度和血量更低。然而,就重量而言,科斯莫姆是一个异数。与其他传奇口袋妖怪相比,它拥有异常高的重量和较少的攻击*。
speed_attack_legendary <- ggplot(na.omit(df), aes(attack, speed)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (attack > 170 | attack < 50 & speed >150 | speed < 50) & is_legendary == 1 | speed > 145), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")weight_attack_legendary <- ggplot(na.omit(df), aes(attack, weight_kg)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (attack > 170 | attack < 50 | weight_kg > 650) & (is_legendary == 1)), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")height_attack_legendary <- ggplot(na.omit(df), aes(attack, height_m)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, ((attack > 170 | attack < 50 | height_m > 7.5) & is_legendary == 1) | height_m > 5 & is_legendary == 0), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")hp_attack_legendary <- ggplot(na.omit(df), aes(attack, hp)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, ((attack > 170 | hp > 190 | attack < 50) & is_legendary == 1) | hp >160), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")grid.arrange(speed_attack_legendary, weight_attack_legendary, height_attack_legendary, hp_attack_legendary, ncol = 2)
Height, Weight, Speed, Hp vs Attack [Image [9]]
速度、身高、体重和 Hp V.S .防御属性
我们绘制了与上面相同的图表,但这次是防御属性。我们在这里观察到趋势的不同。速度和防守有一种微弱的负线性关系。速度随着防御的增加而降低。这意味着防守型口袋妖怪通常比进攻型口袋妖怪要慢。
对于一个传奇的口袋妖怪来说,Cosmog 在拥有超级弱属性方面是非常一致的。为什么 Cosmog 这么没用?我在网上查了一下 Cosmog。这是我发现的。
Cosmog 从 43 级开始进化成科斯莫姆,它从 53 级开始进化成 Solgaleo 或 Lunala 取决于它进化的游戏。
Evolution of Cosmog [Image [10]]
speed_defense_legendary <- ggplot(na.omit(df), aes(defense, speed)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 130 | defense < 50| speed > 140 | speed < 50) & is_legendary == 1), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")weight_defense_legendary <- ggplot(na.omit(df), aes(defense, weight_kg)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 160 | defense < 50 | weight_kg > 600) & is_legendary == 1), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")height_defense_legendary <- ggplot(na.omit(df), aes(defense, height_m)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 150 | defense < 50 | height_m > 6) & is_legendary == 1 | height_m >5 & is_legendary ==0), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")hp_defense_legendary <- ggplot(na.omit(df), aes(defense, hp)) + geom_point(aes(color=is_legendary)) + geom_label_repel(data=subset(df, (defense > 150 | defense < 50 | hp > 150) & is_legendary == 1 | hp > 200), aes(label=name), box.padding = 0.35, point.padding = 0.5, segment.color = 'grey50') + geom_smooth(method = "lm")grid.arrange(speed_defense_legendary, weight_defense_legendary, height_defense_legendary, hp_defense_legendary, ncol = 2)
Height, Weight, Speed, Hp vs Attack [Image [11]]
箱线图
箱线图是显示数据集的分布和中心的一种方式。传播的测量包括数据组的四分位数范围和平均值。中心的度量包括平均值和中值(数据集的中间)。
黑线表示中间值。彩色框表示代表中间 50%数据的四分位数范围。胡须从盒子的两边延伸出来。晶须代表数据值的底部 25%和顶部 25%的范围,不包括异常值。
口袋妖怪属性的方框图
我们观察到,传奇口袋妖怪的所有特征的中位数都高于非传奇口袋妖怪。
与其他属性相比,非传奇口袋妖怪的 Hp 属性有更多的异常值。但是另一方面,相同的 Hp 属性与其他属性相比变化最小。
与传说中的口袋妖怪相比,非传说中的口袋妖怪有更多的离群值。
box_plot_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)box_plot_attr_leg <- filter(box_plot_attr, is_legendary == 1)box_plot_attr_nor <- filter(box_plot_attr, is_legendary == 0)box_plot_attr_leg_long <- gather(box_plot_attr_leg, attribute, value, -c(type1, is_legendary))box_plot_attr_nor_long <- gather(box_plot_attr_nor, attribute, value, -c(type1, is_legendary))bp_leg <- ggplot(data = box_plot_attr_leg_long, aes(attribute, value)) + geom_boxplot(fill="green4") + ggtitle("Legendary Pokemon")bp_nor <- ggplot(data = box_plot_attr_nor_long, aes(attribute, value)) + geom_boxplot(fill = "yellow2") + ggtitle("Normal Pokemon")grid.arrange(bp_leg, bp_nor,ncol=2)
Boxplot of Pokemon attributes’ [Image [12]]
热图
热图基本上是用颜色代替数字的表格。热点图中的最低值设置为深蓝色,最高值设置为红色,中间值设置为白色,在这些极端值之间有相应的过渡(或渐变)。热图非常适合可视化大量多维数据,并可用于识别具有相似值的行的聚类,因为这些行显示为相似颜色的区域。
接下来,我们将看到各种类型的口袋妖怪的属性如何相互叠加。为此,我们将计算这些属性的中位数,并绘制传奇和非传奇口袋妖怪的热图。
初级类型 vs 属性热图|传奇口袋妖怪
冰型传奇口袋妖怪的 sp_ 防御值很高,而速度值很低。地传奇口袋妖怪有非常高的攻击属性。 Bug 型传奇口袋妖怪 sp_defense 很低。
相反, bug 型和黑暗型口袋妖怪有着相似的速度属性。
hmap_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)hmap_attr_leg <- filter(hmap_attr, is_legendary == 1)
hmap_attr_nor <- filter(hmap_attr, is_legendary == 0)hmap_attr_leg <- group_by(hmap_attr_leg, type1)
hmap_attr_nor <- group_by(hmap_attr_nor, type1)hmap_attr_leg <- summarise(hmap_attr_leg, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_leg_m <- melt(hmap_attr_leg)hmap_attr_nor <- summarise(hmap_attr_nor, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_nor_m <- melt(hmap_attr_nor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'RdYlBu')), space='Lab')ggplot(data=hmap_attr_leg_m, aes(type1, variable)) + geom_tile(aes(fill=value)) + ggtitle("Legendary Pokemon: Type1 - Attribute") + scale_fill_gradientn(colours = hm.palette(100)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + coord_equal()
Heat map of legendary attributes vs primary type [Image [13]]
初级型 vs 属性热图|非传奇口袋妖怪
钢铁型口袋妖怪防御数值高但是速度很低。战斗型口袋妖怪攻击值很高而 sp_attack 值很低。地、冰、普通口袋妖怪都有类似的 Hp 水平,毒药、和摇滚型口袋妖怪也是如此。
hm.palette <- colorRampPalette(rev(brewer.pal(5, 'RdYlBu')), space='Lab')ggplot(data=hmap_attr_nor_m, aes(type1, variable)) + geom_tile(aes(fill=value)) + ggtitle("Non-Legendary Pokemon: Type1 - Attribute") + scale_fill_gradientn(colours = hm.palette(100)) + theme(axis.text.x = element_text(angle=90, hjust=0)) + coord_equal()
Heatmap of non-legendary attributes vs type1 [Image [14]]
相关矩阵
相关矩阵是一个显示变量集之间相关系数(皮尔逊系数)的表格,它允许您查看哪些变量对具有最高的相关性。相关系数的取值范围为 1 至+1。系数的绝对值越大,变量之间的关系越强。
对于皮尔逊相关,绝对值为 1 表示完美的线性关系。
传奇口袋妖怪属性关联热图
我已经把相关矩阵转换成了热图。热点图中的最低值设置为深蓝色,最高值设置为白色,中间值设置为绿色,在这些极端值之间有相应的过渡(或渐变)。
现在,在绘图之前,让我们制定一个假设,看看它是否是真的。人们会认为防御性口袋妖怪会有更高的 Hp(也许这样它可以承受很多攻击?)和攻击值高到 sp_defense 值高但防御值低的口袋妖怪。
对角线上的元素都是白色的,因为属性与其自身具有线性关系。矩阵是其自身在白色对角线上的镜像。
基于以下传奇口袋妖怪的相关矩阵,在攻击和防御之间似乎存在某种线性关系,但在攻击和sp _ 防御之间并没有那么大的关系。此外,在防御和生命属性之间存在某种关联。
hmap_attr <- select(df, type1, is_legendary, hp, defense, attack, sp_attack, sp_defense, speed)hmap_attr_leg <- filter(hmap_attr, is_legendary == 1)
hmap_attr_nor <- filter(hmap_attr, is_legendary == 0)hmap_attr_leg <- group_by(hmap_attr_leg, type1)
hmap_attr_nor <- group_by(hmap_attr_nor, type1)hmap_attr_leg <- summarise(hmap_attr_leg, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))hmap_attr_nor <- summarise(hmap_attr_nor, hp=median(hp), attack=median(attack), defense=median(defense), sp_attack=median(sp_attack), sp_defense=median(sp_defense), speed=median(speed))row.names(hmap_attr_leg) <- hmap_attr_leg$type1
hmap_attr_leg$type1 <- NULL
hmap_attr_leg$is_legendary <- NULLrow.names(hmap_attr_nor) <- hmap_attr_nor$type1
hmap_attr_nor$type1 <- NULL
hmap_attr_nor$is_legendary <- NULLhmap_attr_leg_cor <- cor(hmap_attr_leg)
hmap_attr_leg_cor_m <- melt(hmap_attr_leg_cor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'GnBu')), space='Lab')ggplot(data=hmap_attr_leg_cor_m, aes(Var1, Var2)) + geom_tile(aes(fill=value)) + ggtitle("Attribute Correlation - Legendary") + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal()
Correlation matrix of legendary Pokemon [Image [15]]
非传奇口袋妖怪属性的关联热图
对于非传说中的口袋妖怪来说, sp_attack 和 sp_defense 之间似乎有关联,而 attack 和 sp_attack 或 defense 和 speed 等等之间则没有这样的关系。
例如,具有高值 sp_attack 的口袋妖怪往往具有高值 sp_defense。
hmap_attr_nor_cor <- cor(hmap_attr_nor)
hmap_attr_nor_cor_m <- melt(hmap_attr_nor_cor)hm.palette <- colorRampPalette(rev(brewer.pal(5, 'GnBu')), space='Lab')ggplot(data=hmap_attr_nor_cor_m, aes(Var1, Var2)) + geom_tile(aes(fill=value)) + ggtitle("Attribute Correlation - Normal") + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal()
Correlation matrix of non-legendary Pokemon [Image [16]]
基于初级类型的口袋妖怪的有效性
为此图选择数据框的一部分。
df_fight_against <- select(df, type1, against_bug:against_water)
head(df_fight_against)
Fight_against data frame [Image [17]]
求所有对 _type 列的中值。
df_fight_against_g <- group_by(df_fight_against, type1)df_fight_against_summ <- summarise(df_fight_against_g,
against_bug = median(against_bug),
against_dark = median(against_dark),
against_dragon = median(against_dragon),
against_electric = median(against_electric),
against_fairy = median(against_fairy),
against_fight = median(against_fight),
against_fire = median(against_fire),
against_flying = median(against_flying),
against_ghost = median(against_ghost),
against_grass = median(against_grass),
against_ground = median(against_ground),
against_ice = median(against_ice),
against_normal = median(against_normal),
against_poison = median(against_poison),
against_psychic = median(against_psychic),
against_rock = median(against_rock),
against_steel = median(against_steel),
against_water = median(against_water))
绘制热图。
df_fight_against_long <- melt(df_fight_against_summ)hm.palette <- colorRampPalette(rev(brewer.pal(9, 'RdYlBu')), space='Lab')ggplot(data=df_fight_against_long, aes(type1, variable)) + geom_tile(aes(fill=value)) + scale_fill_gradientn(colours = hm.palette(100)) + coord_equal() + theme(axis.text.x=element_text(angle=90, hjust=0)) + ggtitle("Effectiveness of different types of Pokemon")
热点图中的最低值设置为深蓝色,最高值设置为红色,中间值设置为白色,在这些极端值之间有相应的过渡(或渐变)。
热图显示会飞的型口袋妖怪对冰型口袋妖怪高效,而火型口袋妖怪则不然,等等。
Effectiveness of Pokemon in a duel based on fight [Image [18]]
感谢您的阅读。欢迎提出建议和建设性的批评。:)你可以在 LinkedIn 和 Twitter 上找到我。你可以点击查看的完整代码。
你也可以在这里查看我的其他博客文章。
什么是探索性数据分析?
当我在考虑我应该开始写博客的第一个话题是什么时,EDA 立刻出现在我的脑海中。逻辑上很贴切,不是吗?!为什么?你很快就会知道了!
直觉
想象一下你的狼群决定去看一部你没听过的电影。这是绝对没有争议的,它会导致你发现自己被许多问题所困扰,而这些问题需要得到回答才能做出决定。做一个好酋长你会问的第一个问题是,这部电影的演员和工作人员是什么?作为惯例,你还会在 YouTube 上观看这部电影的预告片。此外,你还可以找到观众对这部电影的评价和评论。
无论你最终在影院为你的家族购买爆米花之前会采取什么样的调查措施,都只不过是数据科学家的行话所说的“探索性数据分析”。
探索性数据分析是指对数据进行初步调查的关键过程,以便发现模式,发现异常,测试假设,并借助汇总统计数据和图表检查假设。
首先理解数据并尝试从中收集尽可能多的见解是一个很好的做法。EDA 就是在数据被弄脏之前,理解手头的数据。
EDA 用样本数据集解释:
为了分享我对我所知道的概念和技术的理解,我将以 UCI 机器学习知识库上的葡萄酒质量数据集的白色变体为例,并尝试使用 EDA 从数据集中获取尽可能多的见解。
首先,我导入了必要的库(在本例中是 pandas、numpy、matplotlib 和 seaborn)并加载了数据集。
注意:无论我能得出什么样的推论,我都提到了要点。
- 原始数据由分隔符“;”分隔在给定的数据集中。
- 为了仔细查看这些数据“帮了大忙了。head()" pandas 库的函数,它返回数据集的前五个观察值。同样”。tail()"返回数据集的最后五个观察值。
我用“.”找出了数据集中的行和列的总数。形”。
- 数据集由 4898 个观察值和 12 个特征组成。
- 其中一个是因变量,其余 11 个是自变量——物理化学特性。
了解列及其对应的数据类型,以及发现它们是否包含空值,也是一个很好的做法。
- 数据只有浮点值和整数值。
- 没有变量列具有空值/缺失值。
pandas 中的 describe()函数在获取各种汇总统计数据时非常方便。该函数返回数据的计数、平均值、标准差、最小值和最大值以及分位数。
- 在这里,您可以注意到平均值小于每列的中间值,中间值由索引列中的 50%(第 50 个百分位)表示。
- 预测值“残余糖”、“游离二氧化硫”、“总二氧化硫”的最大值与 75%之间存在显著差异。
- 因此,观察 1 和 2 表明,在我们的数据集中存在极端值-异常值。
仅通过观察因变量得出的一些关键见解如下:
- 目标变量/因变量本质上是离散的和分类的。
- “质量”评分范围为 1 至 10 分;其中 1 表示差,10 表示最好。
- 1、2 和 10 质量等级不是由任何观察给出的。只有获得的分数在 3 到 9 之间。
- 这告诉我们按降序排列的每个质量分数的投票数。
- “质量”的大多数值集中在类别 5、6 和 7 中。
- 对于第 3 类和第 9 类,只做了一些观察。
我很好地浏览了一下数据。但这就是数据科学,你参与的越多,就越难停止探索。现在让我们用漂亮的图表来探索数据。Python 有一个可视化库, Seaborn ,它构建在 matplotlib 之上。它提供了非常有吸引力的统计图,以便执行单变量和多变量分析。
要使用线性回归建模,必须移除相关变量以改进模型。人们可以用熊猫来寻找相关性。corr()"函数,并可以使用 seaborn 中的热图来可视化相关矩阵。
Heatmap
- 深色代表正相关,而浅色代表负相关。
- 如果设置 annot=True,您将获得格网单元中要素相互关联的值。
在特征选择过程中移除相关变量是一个很好的做法。
Correlation Matrix
- 这里我们可以推断“密度”与“残糖”有很强的正相关性,而与“酒精”有很强的负相关性。
- “游离二氧化硫”和“柠檬酸”与“品质”几乎没有相关性。
- 由于相关性为零,我们可以推断这两个预测值之间没有线性关系。但是,在对数据集应用线性回归模型的情况下,删除这些要素是安全的。
箱线图(或盒须图)以一种便于变量间比较的方式显示定量数据的分布。该框显示数据集的四分位数,而触须延伸以显示分布的其余部分。
盒状图(也称为盒须图)是一种基于五个数字摘要显示数据分布的标准化方法:
- 最低限度
- 第一四分位数
- 中位数
- 第三个四分位数
- 最大值。
在最简单的箱线图中,中间的矩形跨越第一个四分位数到第三个四分位数(四分位数间距或 IQR)。
矩形内的一段显示了中间值,方框上下的“胡须”显示了最小值和最大值的位置。
Boxplot
异常值要么高于第三个四分位数 1.5 倍 IQR,要么低于第一个四分位数 1.5 倍 IQR。
- 在我们的数据集中,除了“酒精”之外,所有其他特性列都显示异常值。
现在,要检查变量的线性度,绘制分布图并寻找特征的偏斜度是一个很好的做法。核密度估计(kde)是绘制分布形状的一个非常有用的工具。
Distribution Plot
- “pH”列似乎呈正态分布
- 剩余的所有独立变量都是右偏/正偏的。
最后,总结所有的探索性数据分析是一种哲学和艺术的方法来衡量早期接触的数据的每一个细微差别。
你可以浏览我的 jupyter 笔记本 这里 并且尝试用不同的方法进行测试,例如,尝试一个 pairplot 并且分享你可以从中获得的所有推论,或者如果我在我自己的方法中没有捕捉到任何有用的信息,也请在评论中分享。
阅读我发表的其他文章—
Kaggle 竞赛初学者的探索性数据分析(EDA)技术
EDA 和数据科学竞赛初学者实践指南
Photo by Andrew Neel on Unsplash
E 探索性数据分析 ( EDA )是一种分析数据集以总结其主要特征的方法,通常采用可视化方法。以下是 EDA 中涉及的不同步骤:
- 数据收集
- 数据清理
- 数据预处理
- 数据可视化
数据收集
数据收集是以一种既定的系统方式收集信息的过程,这种方式使人们能够轻松地检验假设和评估结果。
获得数据后,我们需要检查要素的数据类型。
有以下类型的功能:
- 数字的
- 绝对的
- 序数
- 日期时间
- 协调
为了了解数据的数据类型/特征,我们需要运行以下命令:
train_data.dtypes
或者
train_data.info()
让我们看一下关于我们数据集的统计摘要。
train_data.describe()
数据清理
数据清理是通过识别数据中的任何错误或通过更正或删除丢失的数据来确保您的数据正确可用的过程。参考此链接进行数据清理。
一旦数据是干净的,我们可以进一步进行数据预处理。
数据预处理
数据预处理是一种数据挖掘技术,涉及将原始数据转换成可理解的格式。它包括标准化和规范化、变换、特征提取和选择等。数据预处理的产品是最终的训练数据集。
数据可视化
数据可视化是信息和数据的图形表示。它使用统计图、曲线图、信息图和其他工具清晰高效地传达信息。
在这里,我们将重点放在常用的 Seaborn 可视化。Seaborn 是一个基于 matplotlib 的 Python 数据可视化库。它提供了一个高层次的界面来绘制有吸引力的和信息丰富的统计图形。
以下是常用的 seaborn 可视化
- 散点图
- 箱形图
- 柱状图
- 猫图
- 小提琴情节
- 配对图
- 联合地块
- 热图
#导入 seaborn 库
import seaborn as sns
散点图
散点图是绘制在水平轴和垂直轴上的一组点。
下面的散点图显示了乘客年龄和乘客票价之间的关系,基于从泰坦尼克号数据集获取的数据的 pclass(客票等级)
sns.scatterplot(x="Age", y="Fare", hue = 'Pclass', data=train_data)
箱形图
箱形图是在图上表示统计数据的一种简单方法,在图上画一个矩形来表示第二个和第三个四分位数,通常用一条垂直线来表示中间值。上下四分位数显示为矩形两侧的水平线。
下图显示了乘客票价如何根据机票等级而变化。
sns.boxplot(x="Pclass", y="Fare",data= train_data)
柱状图
直方图是数字数据分布的精确表示。它是对连续变量的概率分布的估计
sns.distplot( train_data['Pclass'], kde=False)
猫图
Cat plot 提供了对几个轴级函数的访问,这些函数使用几个可视化表示中的一个来显示数值变量与一个或多个分类变量之间的关系。我们可以使用不同种类的绘图来绘制(对应于分类绘图函数的名称)选项有:“点”、“条”、“带”、“群”、“框”或“小提琴”。更多关于猫情节的细节在这里
下面我们用条形做一个猫图
sns.catplot(x="Embarked", y="Survived", hue="Sex",col="Pclass", kind = 'bar',data=train_data, palette = "rainbow")
让我们看看同样的猫情节与小提琴类
sns.catplot(x="Embarked", y="Survived", hue="Sex",col="Pclass", kind = 'violin',data=train_data, palette = "rainbow")
小提琴情节
小提琴图与盒须图的作用相似。它显示了数量数据在一个(或多个)分类变量的几个级别上的分布,以便对这些分布进行比较。关于小提琴剧情的更多细节是这里
sns.violinplot(x='Sex', y='Survived',data=train_data)
配对图
seaborn 中的 Pair plot 仅绘制数字列,尽管稍后我们将使用分类变量进行着色。更多关于双人剧情的是这里。
sns.pairplot(train_data, hue="Sex")
联合地块
Jointplot 是 seaborn 库特定的,可用于快速可视化和分析两个变量之间的关系,并描述它们在同一图上的单独分布。
更多关于联合剧情的是这里。
sns.jointplot(x="Age", y="Fare", data=train_data, color ='green')
热图
热图是以地图或图表的形式表示数据,其中数据值用颜色表示。
sns.heatmap(train_data.corr(), fmt = ".2f")
这篇文章到此为止,希望对你有所帮助。干杯!
原载于 2018 年 11 月 25 日confusedcoders.com。
探索性数据分析、特征工程和使用超市销售数据的建模。第一部分。
通过处理真实世界的数据集,学习数据分析和见解生成的基础知识。
source: pixabay
在这一系列的文章中,我们将深入并全面探索数据探索、特征工程和建模的神奇世界。如果您是机器学习和数据科学的初学者,并且需要对这些概念进行实用和直观的解释,那么本系列适合您。
这个系列分为三个部分,我将在接下来的几周内撰写。
第 1 部分:学习如何探索数据集并从中获得洞察力。
第二部分:通过数据探索 学到特征工程的基础知识。
第三部分: 造型与特征重要性 。
在我们开始这个旅程之前,我们需要定义一些我们将在这篇文章和后续文章中使用的重要术语。
一、 EDA (探索性数据分析)什么是 it ?
source: dsguide
探索性数据分析*(EDA)是一种对* 数据集进行分析以总结其主要特征的方法,往往带有直观性。一个 统计模型 可以用,也可以不用,但主要是 EDA 是为了看看数据能告诉我们什么,超越正式的建模或假设检验任务。(来源: 维基百科 )
总之, EDA 可以向我们展示数据中隐藏的关系和属性,甚至在我们将数据扔给机器学习模型之前。
接下来, F.E (特征工程)你是谁?
Source: Data Science Central
特征工程 是利用数据的领域知识来创建使机器学习算法工作的特征的过程。特征工程是机器学习应用的基础,既困难又昂贵。(来源:维基百科)
总之,FE 只是使用您现有的数据集知识来创建新的功能,这些功能可以帮助机器学习模型更好地执行。让我们看一个例子。假设我有一个不同汽车类型的数据集,如下所示;
sample car dataset
现在,假设我想根据数据集中的信息预测汽车的价格,我可以使用我在汽车领域的知识来创建额外的功能,帮助机器学习模型更好地完成这项任务。像车速或引擎类型这样的特征。我甚至可以进一步添加布尔特性,比如:
1.这辆车有信息娱乐系统吗?
2.车上有后座娱乐吗?
3.这辆车是四轮驱动还是四轮驱动?电子贸易公司
你掌握了窍门。
我也可以通过我们所谓的 特征交叉 (下一篇文章中会有更多关于这个的)从现有的特征中创建特征。****
现在我们已经熟悉了术语 EDA 和 FE,让我们获取数据并开始探索。
我们将使用由尼日利亚 数据科学 提供的超市销售数据集。这里有一个 链接 到数据。
我们将使用流行的原型开发工具 Jupyter Notebooks 和抱歉" R "各位,我将使用 Python 进行这次探索。
下载数据后,将其放在与笔记本相同的文件夹中,以便可以访问。启动您的笔记本并导入以下库,如下所示。
- 这里,我们导入 NumPy、pandas 和 matplotlib,它们分别用于数组操作、CSV 文件处理和绘图可视化。
- 这里,我们导入 stats 模块,它包含一些统计函数,比如 norm 和 skew,我们将使用它们来计算一些统计数据。
- 我们进口海博**。基于 matplotlib 构建的强大绘图库。我们将用它来创造一些有见地的情节。**
- Python 可能会抛出一些烦人的警告,我们使用 ignore_warns 函数来阻止这种情况。
- 我们导入了操作系统**,一个可以轻松访问文件和文件夹的软件包。我们使用 os.listdir 来显示我们当前目录(当前工作目录)的内容**
接下来,让我们读入数据。
first five rows of our data
- 我们使用 pandas read_csv() 命令读入数据
- 我们打印出数据的前五行。
注意:我调换了 train.head() 命令,因为我想在一个页面上看到所有的行和列,而不需要水平滚动。
现在我们可以看到我们的数据和它包含的特征。让我们言归正传。
source: pixabay.com
首先,我们需要知道我们的目标变量。
我们可以选择任何特征作为我们的目标,这反过来会告诉我们我们将构建什么样的模型。
例如,如果我们选择 Product_Fat_Content 作为我们的目标变量,那么我们将有一个分类问题,如果我们决定选择 PProduct _ Price**,那么它将变成一个回归问题。**
但是因为我们在这篇文章中不关心构建模型,我们就假设我们正在尝试预测产品 _ 超市 _ 销售额(超市的总销售额)。****
接下来,我们来了解一下我们的特点。由于特征的数量很少,我们可以手动查看它们,并立即删除那些不值得研究或放入模型的特征。为此,我们将使用我们在超市领域的知识。
我通常拿出笔和纸,画出如下所示的五列,并手动填充所有功能:
特征==重要==介于==不重要= =原因
不过,你也可以用其他方式来做这件事。让我们来看看这些特征。
- 产品标识:这是每个特定产品的唯一标识。判决:介于两者之间。 原因:有时最好删除任何唯一的 ID 列,因为我们的模型可能会超出这个范围,但有时它可能会有所帮助。我们可以用这个做实验。
- ****超市标识符:这是每个超市的唯一 ID。 判决:介于两者之间。 原因:同上
- ****产品超市标识符:这是产品和超市标识符的串联。 判断:中间 原因:该特性可以用来代替产品和超市标识符。这可能是两种特征的结合。这可能很重要,但在编码时可能会大大增加我们的维度空间。(稍后会有更多相关内容)
- ****产品 _ 重量:产品的重量。 判决:重要 理由:一件商品的重量可能会影响其价格,而价格又会影响超市的总销售额。
- 产品 _ 脂肪 _ 含量:产品中所含的脂肪量。 判决:重要 理由:脂肪含量也会影响价格,进而对超市总销售额有贡献。
- Product _ Shelf _ Visibility:**根据数据描述,这是分配给一组产品的百分比中的总展示面积。 结论:重要 原因:产品的知名度很可能决定了该产品是否会被顾客看到。这会影响该产品的销售。
- ****产品类型:产品所属的类别。 结论:重要 原因:某种类型的产品一般会比其他产品卖得多。
- ****产品 _ 价格:产品的价格。 判决:重要 原因:这当然是一个重要的特征因为产品的价格肯定会影响我们的目标变量 产品 _ 超市 _ 销售 。
- ****超市 _ 开业 _ 年份:超市开业的年份。 判决:重要 原因:开业年份可能影响产品销量。
- ****超市 _ 大小:这是超市的大小。它被分为小型、中型和高级。 判决:重要 理由:超市的规模可以意味着超市的销售额更多。
- 超市 _ 位置 _ 类型:该特征是对超市位置的描述。根据数据,有 3 个集群(集群 1、2 和 3)。我们不知道哪个更高,但是我们想保留这个特性。 结论:重要 原因:位置类型可能包含超市所在位置的信息,无论它们是在城市、农村、繁忙还是偏僻的地方。
- ****超市 _ 类型:超市的类型分为杂货店、超市类型 1、超市类型 2、超市类型 3。 结论:重要 原因:它给了我们关于超市的有用信息,这些信息在预测总销售额时可能很重要。
- ****产品 _ 超市 _ 销售:这是我们这个岗位的 目标 变量。它是超市的销售总额。 判决:对,重要! 原因:是我们的目标变量。
现在我们已经手动检查了我们的数据,发现几乎所有的特性都很重要(尽管有些还在检查中),我们可以开始我们的 EDA 了。
当对一个有合理数量的数字列的数据集进行 EDA 时,我喜欢做的第一件事是检查我的目标变量和这些数字特征之间的关系。一个快速的方法是使用 seaborn 热图 图。此 seaborn 热图 采用根据我们的数据集中的数字特征计算的相关矩阵,并对其进行加热绘图。输入下面的代码制作一个热图。
seaborn heatmap plot of correlations
- 首先,我们使用熊猫 计算数据的相关性。corr( ) 函数,然后我们将它存储在变量 corrmat 中
- 这里,我们简单地设置我们的图的图形大小。
- 在这里,我们将 corrmat 传递给seabornfunction*heat map()*来制作美丽的剧情。
现在我们来解读一下上面的剧情。看一看它,看看你能从中得到什么启示。
如果你不知道如何解读一个 热图 剧情,下面几段给你。如果有,请跳过。
Heatmap plot of Supermarket dataset
解读热图
热图中的每个方块显示了任意两个特征与的相关程度(它们之间是否存在某种关系)。一个特性的增加会导致另一个特性的增加吗?(正相关)还是一个的增加导致另一个的减少?(负相关)。
- 从 0.0 到 1.0 的垂直范围显示了任意两个要素之间相关性的相对大小,其中较热的值较高,意味着相关性较高。
- 矩阵的几乎发白的对角线部分表示所有特征都与自身高度相关。(当然,他们应该是。)
现在,让我们来解释正方形内的标签。
向左水平追踪 标签 3 引出 产品 _ 重量 垂直向下追踪引出 产品 _ 价格 。这意味着方形的框(3)** 向我们展示了产品 _ 重量和产品 _ 价格的相关程度。我们可以看到它们实际上并不相关,因为正方形几乎是冷的。**
标签 4 显示产品 _ 价格和产品 _ 超市 _ 销售之间的关联。我们清楚地看到该区域很热,这意味着相关性很高。****
这就是你解读热图的方式。
好了,你已经获得了热图阅读的学位。现在,你开始了你的第一份工作,下面的热图就摆在你面前。
heatmap of dataset
你的老板满怀信心地看着你,认为他雇对了人,并要求你给出答案。
你站起来,看一眼热图,笑着说:
这个图显示了产品价格是与我们感兴趣的目标 【产品 _ 超市 _ 销售】 最相关的特征,根据我们的直觉,如果销售更贵的产品,那么总的产品 _ 超市 _ 销售可能会增加,反之亦然。
你的老板点点头,让你继续。你现在充满了自信,而且还在继续。
我能看到的另一个关联——通过 small——是 产品 _ 价格 和 超市 _ 开业 _ 年份。
你的老板问这是什么意思?
嗯,综上所述,这是在告诉我们,超市开业的年份似乎是影响着产品的价格。它可能是积极的(新超市卖得更多),也可能是消极的(旧超市有更多忠诚的顾客,卖得更多)。我必须对此进行调查并找到更多的信息。
除此之外,这个图没有其他有趣的关联,先生。但这些只是数字特征。我还是要检查分类特征。
source: pixabay.com
你的老板很高兴,他给你一个坚定的握手,并要求你调查进一步向他报告第二天。
你走吧,去做更多的探索。
首先,您决定调查数据集中所有要素之间的关系。因此,您希望根据其他特性来绘制每个特性,但是您希望只绘制一次,而不编写多个 for 循环。
还好, Seaborn 的*pair plot()*前来救援。
seaborn pairplot on supermarket dataset
**如果你以前没有见过 seaborn pairplot,这就是它的样子。基本上就是一个 的单线奇观。我们还可以指定一个分类特征,用于着色。
注意:Seabornpair plot只绘制数字特征,但是我们可以根据所选的分类列为我们的图着色。此外,如果传递给 pairplot 的数据集包含缺失值,它将引发错误。
首先,让我们检查有缺失值的列,这样我们就不会将它们添加到 pairplot 中。
Check for missing values
嗯,我们有两个缺少值的列,Supermarket_size 是一个分类特征,Product_Weight 是一个数值特征。我们将在下一篇文章中讨论这些缺失的特性,现在,让我们将它们从我们的 pairplot( ) 专栏中排除。
code block to pairplot features
- 这里我们列出了数据集中所有的分类特征。(我们将用它们来着色。这意味着每个分类特征都有一组配对图。
- 在 for 循环中,我们列出了所有没有缺失值的列。
- 每次创建一个新的图形
- 调用单行奇迹 pairplot( ) 并传递我们的数据“火车”和我们想要的列。我们指定尺寸为 3.0 ,这样我们就可以看到完整的 pairplot 而无需滚动。
- hue 变量从我们的分类列中提取一列,并使用它们为我们的配对图着色。
运行上面的代码后,我们总共会有四个图。让我们一个接一个地看它们,并试着从中解读或得出见解。
情节一:类别(产品 _ 脂肪 _ 含量)
Plot one: Category (Product_Fat_Content)
释义:
- 我们可以看到绝大多数产品都含有正常脂肪。那么,我们能用这些知识做些什么呢?** 嗯,我们可以创建一个布尔特征列 is_normal_fat 并将正常脂肪(多数类)与另外两个低脂肪和**超低脂肪(少数类)分开。这只是一个建议。****
- 产品价格和超市销售额之间呈正相关趋势。这证实了热图图所示的相关性(正相关)。那么,我们能用这些知识做些什么呢?
- 嗯,这个功能肯定很重要。我们可以从中创造更多的功能。
- 我们还注意到我们的目标变量(产品 _ 超市 _ 销售)和变量产品 _ 货架 _ 可见性是 右偏 。我们可以使用对数函数对它们进行转换,使它们正常偏斜。我们以后再做这个。
- 我们也可以看到 低脂 和 超低脂 的价格相对高于 正常脂 的产品。那么,我们能用这些知识做些什么呢? 嗯,我们可以创建一个分类功能,将 正常脂肪 产品的价格设置为低,将 低/超低脂肪 产品的价格设置为高。
- 我注意到的另一件事是 Supermarket _ Opening _ Year之间似乎有差距。注意 90 年代的超市集群和 2000 年代的另一个集群。我们能用这些知识做些什么?嗯,我们可以创建一个新的特性列来捕获这两个集群。
- 在这一对情节中,我没有注意到任何其他有趣的关系,所以我们继续下一个。
如果你注意到任何其他关系,请在下面留言通知我。
地块二:类别(产品 _ 类型)
Plot two: Category (Product_Type)
释义:
- 从Product _ typecategory家居、健康卫生、** 和 其他 主导剧情。那么,我们能用这些知识做些什么呢? 我们可以创建一个特征列,将数据分为两组,一组捕获 家庭、健康卫生 和 其他 ,另一组捕获其余产品。谁知道呢?这可能是一个很好的功能。**
- 其他的似乎都没什么意思。所以我就暂时停在这里,进入下一个情节。
地块三:(超市 _ 位置 _ 类型)
Plot three: (Supermarket_Location_Type)
释义:
- 似乎集群 2 是最昂贵的位置。是产品 _ 价格和产品 _ 超市 _ 销售看起来更高。
- 我们还注意到,集群 2 中的超市较新(2010 年以后)。
- 集群 1 的产品价格较低,集群 2 介于两者之间。那么,我们能用这些知识做些什么呢? 好了,现在我们知道了超市 _ 位置 _ 类型是一个非常重要的特性,它似乎有一些 平凡性 。如果我们要标记编码这个变量,我们应该尽量保持这个顺序结构。
请记住,如果你注意到我错过了任何解释,请使用下面的评论框。
地块四(超市 _ 类型):
Plot four (Supermarket_Type)
释义:
看着这个图,我们可以立即看到不同的超市几乎被精细地分开。我们可以从中获得很多启示:
- 首先,我们可以看到超市类型 3** 的商品价格一般从 350 左右开始,超市类型 1 的商品价格大约在 0-250 之间,而超市类型 2 的商品价格大约在 250-350 之间,最后,杂货店接受所有范围的价格。我们能用这种洞察力做什么? 我们可以创建分类列来捕获这些范围,或者我们可以创建箱并根据价格范围对每个超市进行分组。**
- 查看超市 _ 开业 _ 年份**,我们立即注意到属于超市类型 3 的超市都是在 90 年代开业的;这意味着我们之前提议创建的功能——将开放年份划分为两个集群——将非常重要。**
一如既往,如果你注意到我可能错过了任何好的解释,请在下面的评论框中通知我。
哇哦!这是一个漫长的第一个帖子。希望你学到了很多。
**在我的下一篇帖子中,我们将谈论 特征工程和创作 **。在那里,我们将把我们在做这个 EDA 时收集的所有直觉带入生活。
我给你的临别建议是,你得到一个数据集,戳它,撕开它,找到隐藏的宝石并从中获得洞察力,并从中获得乐趣。
source: pixabay.com
但是请记住,EDA 是一门艺术,它可以用许多不同的方式来完成;上面列出的步骤绝不是你必须严格遵循的大纲。做对你有用的事。
Source: Pixabay.com
所以,去享受探险的乐趣吧。再见了。
本帖的笔记本和资料可以在 这里 找到
欢迎提问、评论和投稿。
在 twitter 上跟我连线。
在insta gram上跟我连线。
R 中的探索性数据分析-使用伪脸书数据集探索一个变量
根据维基百科,“ 探索性数据分析*(EDA)是一种分析 d*ata 集合以总结其主要特征的方法,通常采用可视化方法。可以使用或不使用统计模型,但 EDA 主要是为了查看数据可以告诉我们什么,而不仅仅是正式的建模或假设测试任务。
EDA 是一个让数据给你惊喜的机会。回想调查的目标,重新思考我们试图回答什么问题。识别可能导致意外结果的数据特征。
作为一个实际的例子,我们将使用由 Udacity 整理的 facebook 数据集。该数据集有近 99,000 个观察值和 15 个变量,即对于每个观察值,我们都有用户的不同信息,如姓名、年龄、出生日期。
我们的目标是了解用户的行为和他们的人口统计数据。因此,我们有诸如 friend_count、likes_received 等变量。
使用 ggplot
ggplot 是一个用于统计编程语言 r 的数据可视化包。它是为了用最少的代码行为数据分析设计优雅的可视化而构建的。您可以使用以下功能下载并安装 ggplot 库
install.packages('ggplot2')
qplot — qplot 代表快速绘图,可用于绘制直方图。
1。生日等级分析
为伪 facebook 数据集中出现的所有用户的生日绘制直方图。
Histogram using qplot
在上面的图中,假设我们需要为一个月中的每一天绘制一个清晰的图形,那么我们需要添加scale_x_continuous,这是连续 x 美学的默认比例。
Histogram using qplot with continuous x axis scale
绘制直方图的另一种方法是使用 ggplot()
Use of binwidth in ggplot2()
这里的线条是等间距的,因为我们还指定了 binwidth。同样在上面的图中,我们观察到大多数人在每个月的第一天出生,这看起来很奇怪。让我们使用刻面来深入研究这个问题。
刻面
在某些情况下,我们希望绘制多个数据子集中的集合变量之间的关系,结果显示为面板。这是 ggplot2 的一个漂亮的特性。分面由分类变量定义。facet_wrap 和facet_grid用于 r 中的刻面
Faceting in R
从上面可以推断,只有第一个月,即一月,由出生于第一天的大多数用户组成。这可以是数据集中的默认值,也可以是异常值。
极端值
远离数据集中其他值的值称为异常值。异常值会影响均值和标准差等测量值。异常值可能是关于极端情况的准确数据,或者是由于数据集中的一些变量被顶部编码或底部编码,即一些变量被设置了最大或最小限制。
2.朋友级别分析
画出用户的生日后,让我们画出每组观察的朋友数量。
Long tail graph for number of friends of each observation
这种类型的图叫做长尾图。该图是这样的,因为许多人在 500 范围内有脸书朋友,因此我们在左边得到高的箱子。但是有些用户有很多朋友,可能多达 5000 个,这是一个用户可以拥有的最大朋友数量。为了进一步研究这个尾巴中的一些其他观察结果,我们将不得不检查朋友数低于 1000 的用户。
为了避免看到这种长尾数据,我们可以使用以下方法之一:
- qplot 内的 xlim 参数。这个参数取一个向量,我们有轴的开始位置和结束位置。
qplot(x=friend_count,data=pf,xlim=c(0,1000))
2.添加一个层并在scale_x_continuous内使用限制
qplot(x=friend_count,data=pf) +
scale_x_continuous(limits=c(0,1000))
这两个步骤都会产生下图
现在让我们添加一些更好的标签和一些宁滨。要调整 binwidth,我们可以传递 binwidth 参数 25,我们也将每隔 50 个单位断开 x 轴,这可以通过将 breaks 参数传递给 scale_x_continuous 层来实现。
从上面的图表我们可以知道,许多用户的朋友少于 25 个。因此,他们可以被认为是新用户。
3.性别水平分析
Gender Level Analysis
当我们绘制朋友的性别等级数量时,我们发现很多性别被归入 NA 类别。去掉 NA 后,我们得到下图。
qplot(x = friend_count, data = subset(pf,!is.na(gender)), binwidth = 10) +
scale_x_continuous(limits = c(0, 1000),
breaks = seq(0, 1000, 100)) +
facet_wrap(gender ~ .)
Gender Level Analysis — Removing NA
4.任期水平分析
用户的天级任期是下面给出的数据集。请注意,参数 color 决定图中对象的颜色轮廓,而参数 fill 决定图中对象内部区域的颜色。
qplot(x=tenure,data=pf,
color=I('black'),fill=I('#632b6c'))
Daily Tenure Level Analysis
如果我们希望看到年级别的任期,那么使用下面的代码, xlab 和 ylab 是为图分配标签的参数。
qplot(x=tenure/365,data=pf,binwidth=0.25,
xlab="Number of years using facebook",
ylab="Number of users in sample",
color=I('black'),
fill=I('#632b6c')) +
scale_x_continuous(breaks = seq(1, 7, 1),limits=c(0,7))
Yearly Tenure Level Analysis
github 上共享了使用权图的等效 ggplot 语法。
5.年龄层次分析
绘制年龄水平直方图显示,对于某些特定的年龄,存在某些峰值,并且存在一些一百岁的用户,这在此刻看起来相当奇怪。
qplot(x=age,data=pf,xlim=c(0,200),binwidth=1,
xlab="Number of years using facebook",
ylab="Number of users in sample",
color=I('black')
,fill=I('#95ada5')) +
scale_x_continuous(breaks=seq(10,130,5))
Age Level Analysis
转换数据
在生成汇总统计数据时,我们经常会发现一些情况,例如,一些值比中间值大 10 或 100 倍。乍一看,这可能被认为是异常值,但当深入研究时,会发现这是正确的数据。在我们的伪脸书数据集的情况下,可能一些用户比大多数用户具有更高的喜欢和评论量。在统计学中,我们说数据过于分散。通常它有助于转换这些值,所以我们可以看到标准差,所以简单地说,我们只是缩短了尾巴。
从用户级别的好友计数直方图,我们知道我们的直方图有一个长尾。我们可以通过取对数(以 2 为底或以 10 为底)或平方根来转换这个变量,这将帮助我们更清楚地找到一个模式,而不会被尾部所偏离。
统计技术,如线性回归,是基于假设变量具有正态分布。因此,通过取对数,我们可以将数据转换成更接近正态分布的形式,这对于建模来说是有效的。虽然本文的范围仅限于探索性的数据分析,但是让我们看看变量转换后的情况。
Data transformation
从上图中可以推断出,变量 friend count 下所有观察值的对数是正态分布的,可以用于线性回归。
频数多边形
正如在线统计手册、中所定义的,频率多边形是一种用于理解分布形状的图形设备。它们的作用与直方图相同,但在比较数据集时尤其有用。”
频率多边形类似于直方图,但它们绘制了一条连接直方图中计数的曲线,从而使我们能够更详细地观察分布的形状和峰值。
qplot(x = friend_count,
data = subset(pf,!is.na(gender)),
xlab="Number of users using facebook",
ylab="Number of friends per user",
binwidth = 10
, geom="freqpoly",color=gender) +
scale_x_continuous(limits = c(0, 1000),
breaks = seq(0, 1000, 100))
箱形图
我们将生成一个按性别划分的好友数量的箱线图
qplot(x=gender
,y=friend_count
,data= subset(pf,!is.na(gender))
,geom='boxplot')
BoxPlot 1 — Gender Level Total Friends
上面方框图中的黑色水平线是中间值,这意味着上面图中的大多数小点都是异常值。我们认为异常值是中位数的四分位数范围的一倍半。按照这种逻辑,这个数据集中有很多离群值。
为了解决这个问题,我们调整了代码,将重点放在好友数量在 0 到 1000 之间的用户上。
qplot(x=gender
,y=friend_count
,data= subset(pf,!is.na(gender))
,geom='boxplot')+
coord_cartesian(ylim=c(0,1000))
BoxPlot 2— Gender Level Total Friends
在上图中,我们将scale _ y _ continuous(limits = c(0,1000)) 替换为 coord_cartesian(ylim=c(0,1000)) 。我们这样做是为了让表格摘要与我们的方框图相匹配(查看 github 了解更多细节)。
结论
在一个变量的探索性数据分析中,我们知道每个变量都是重要的,它们可能有一些隐藏的特征,直到我们绘制它们时才显现出来。接下来,我们将通过探索两个变量来讨论 EDA。
GapMinder 全球数据的探索性数据分析
Hans Rosling/GapMinder
在这篇文章中,我对来自 GapMinder 的两个数据集进行了探索性的数据分析( EDA )。这个帖子包括使用的 R 代码(也可以在这个 GitHub repo 中找到)。总而言之:
- 方法:探索性数据分析、相关、线性回归
- 程序/平台:R/RStudio
- 资料来源:世界卫生组织、世界银行
数据
在这个数据分析中,我使用了 GapMinder 的数据网页上的数据。具体来说,我专注于:
这个问题
我在这个分析中提出的问题是:
在 15-49 岁年龄段中,人均国内生产总值和艾滋病毒感染率之间是否存在关联?如果是,这种相关性有多强?
我的预期是,人均 GDP 和艾滋病毒流行率之间存在负相关关系;这意味着越穷的国家艾滋病毒感染率越高。
数据争论
让我们在 R 中对从 GapMinder 下载的 CSV 文件进行一些初始数据辩论,为我们的数据分析做准备。
人均国内生产总值数据
来自 GapMinder 的数据是 CSV 文件的形式,需要根据原始 CSV 表中的键值对进行重新组织。我使用了惊人的' tidyr '库中的函数 gather() 。
让我们来看看生成的数据帧结构,并确定该数据集涵盖的时间范围:
**## 'data.frame': 14300 obs. of 3 variables:
## $ Income per person (fixed 2000 US$):
Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 2 3 5 6 7 8 9 10 12 ...
## $ Year : int 1960 1960 1960 1960 1960 1960 1960 1960 1960 1960 ...
## $ GDP : num NA NA NA NA 1280 ...**
**## [1] 1960 2011**
产生的数据框架包含 3 个变量(国家、年份、GDP)的 14,300 个观察值。“国家”一栏列出了 275 个国家。提供了 275 个国家从 1960 年至 2011 年的人均国内生产总值。
艾滋病毒流行率数据
让我们对艾滋病毒流行率数据进行类似的数据整理。同样,我将使用来自“ tidyr ”库中的函数 gather() 。
同样,让我们来看看生成的数据帧的结构:
**## 'data.frame': 9075 obs. of 3 variables:
## $ Estimated HIV Prevalence% - (Ages 15-49):
Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 2 3 5 6 7 8 9 10 12 ...
## $ Year : int 1979 1979 1979 1979 1979 1979 1979 1979 1979 1979 ...
## $ HIV_prev : num NA NA NA NA NA ...**
由此产生的数据框架包括 3 个变量(国家、年份、估计的艾滋病毒流行率)的 9075 个观察值。“国家”一栏列出了 275 个国家。提供了 275 个国家从 1979 年至 2011 年的人均国内生产总值。
组合数据帧
让我们结合这两个数据框架来比较人均 GDP 和艾滋病流行率。我正在使用 【合并() 功能。接下来,让我们来看看结果数据帧的结构。
**## 'data.frame': 9075 obs. of 4 variables:
## $ Country : Factor w/ 275 levels "Abkhazia","Afghanistan",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ Year : int 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 ...
## $ GDP : num NA NA NA NA NA NA NA NA NA NA ...
## $ HIV_prev: num NA NA NA NA NA NA NA NA NA NA ...**
我们现在有了一个用于后续数据探索的数据框架。该数据框架分为四栏:(一)国家,(二)年份,(三)该国该年的人均国内生产总值,(四)该国该年的艾滋病毒流行率。
探索数据
数据集通常以缺失数据为特征。我怀疑这个数据集也是如此,即使它来自一个官方组织。让我们来看看缺失的 GDP 数据在综合数据框架中所占的百分比。
**## [1] 35.30579**
综合数据框架中约 35.3%的人均国内生产总值列有缺失数据。这是相当可观的,很可能是因为持续的 GDP 测量成本很高,而且只是在过去几十年才开始(注意:世界银行成立于二战后的 1945 年)。
在随后的分析中,缺失的数据将被排除(即不绘制),而不是用平均值或估计值代替缺失的数据。
让我们来看看艾滋病毒流行率方面缺失数据的百分比。
**## [1] 63.62534**
在综合数据框架中,艾滋病毒流行缺失数据的比例甚至更高,达到 63.6%。这当然是因为世界卫生组织的初始数据框架包括了始于 1979 年的时间框架,而我们的综合数据框架始于 1960 年。
自 20 世纪 80 年代初,HIV/Aids 成为公认的重大健康危机后,HIV 相关指标的一致性测量才真正大规模开展。
让我们从两组数据中初步了解一下分布的类型。对于人均国内生产总值:
**## Min. - 1st Qu. - Median - Mean - 3rd Qu. - Max. - NA's
## 54.51 - 590.26 - 2038.88 - 7315.07 - 9239.73 - 108111.21 - 3204**
关于艾滋病毒流行率:
**## Min. - 1st Qu. - Median - Mean - 3rd Qu. - Max. - NA's
## 0.010 - 0.100 - 0.300 - 1.743 - 1.200 - 26.500 - 5774**
快速浏览清楚地显示,在我们的数据框架中,一些国家显著提高了分布的平均值(与中位数相比)。艾滋病毒流行率数据尤其如此。
情节
在本节中,我生成了各种图(使用 ggplot )来获得分布的概况,并试图确定趋势和模式。
首先,我们查看整个数据集,并生成一个散点图,显示 1960 年至 2011 年数据集中所列的 275 个国家的人均 GDP。
我们还覆盖了平均值和上下限(5%;95%)的 GDP。这将使我们更好地理解我们的大部分分布在哪里。
该图显示了 1960 年至 2011 年间全球 GDP 的总体增长趋势。大部分数据属于最高人均国内生产总值 30,000 美元(2,000 先令)。
让我们通过生成我们的数据集中所列的 275 个国家从 1960 年到 2011 年的艾滋病毒流行率散点图来查看艾滋病毒流行率的数据集。
与人均 GPD 类似,我们也叠加了平均值和上下限(5%;95%)的艾滋病毒感染率。我们将关注 1985 年至 2011 年的数据。
根据我们的数据,艾滋病毒感染率在 1985 年至 2011 年期间有所上升,平均水平从 2000 年代初开始停滞,自 2005 年以来略有下降。这将对应于预防措施的进步,以减少感染艾滋病毒的发生率和可能性。
相关和线性回归
现在,让我们将重点放在我们之前创建的组合数据框架上,以研究两个感兴趣的变量之间的相关性。为了先看一下相关性,让我们画出 HIV 感染率与人均 GDP 的关系图。
散点图清楚地表明,与人均国内生产总值较高的国家相比,人均国内生产总值较低的数据点(即国家)的艾滋病毒流行率要高得多。
让我们通过创建一个将平方根标度应用于 x 轴的图来进一步强调人均 GDP 较低的国家。我们还将使用 R 函数 geom_smooth() 来执行简单的线性回归,以更好地显示两个变量之间的关系。
上面的散点图进一步表明,人均国内生产总值较高的国家平均艾滋病毒感染率较高。
让我们使用皮尔逊方法计算两个变量之间的相关系数。
**## ## Pearson's product-moment correlation
## ## data: gdp.HIV$HIV_prev and gdp.HIV$GDP
## t = -10.938, df = 3183, p-value < 2.2e-16
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.2235800 -0.1566303
## sample estimates:
## **cor**
## **-0.1903264****
得到的相关系数是-0.19,这是一个负的但微弱的相关性。这与上面绘制的线性回归相匹配。
这种负相关但很弱的负相关与其他发表的结果相匹配,这些结果发现个人的财富(而不是个人居住国家的人均 GDP)是个人特定社区内艾滋病毒流行率的更强指标。
结束语
在这个项目中,我们从公共来源(GapMinder,世卫组织,世行)收集数据。我们进行了数据辩论和初步的探索性数据分析。然后,我们推导出一个相关因子,并应用线性回归来评估两个感兴趣的变量(人均国内生产总值、艾滋病毒流行率)之间的线性关系。