TowardsDataScience-博客中文翻译-2019-三十九-
TowardsDataScience 博客中文翻译 2019(三十九)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
使用强化学习打乒乓球
原文:https://towardsdatascience.com/intro-to-reinforcement-learning-pong-92a94aa0f84d?source=collection_archive---------5-----------------------
对强化学习关键原则的简明介绍
Home version of the Atari Pong console, released in 1975, by Sears Tele-Games [Source: youtube.com]
这篇文章的目的是通过训练一个代理玩游戏 Pong 的例子来介绍强化学习的一些关键原则。它呼应了很多资源,但我以一种对我来说直观的方式来写它——希望它对其他人也有一些用处。
注意:关于神经网络和机器学习的一些知识是假定的,但是不要因此而影响你阅读这篇文章。
简要背景
2013 年,DeepMind 的研究员 Volodymyr Minh 与 deep mind 的同事发表了一篇论文,引起了新闻界和机器学习界的关注。在论文中,他们开发了一个系统,该系统使用深度强化学习(深度 RL)来玩各种雅达利游戏,包括 Breakout 和 Pong。该系统纯粹从视频游戏显示器的图像/帧的像素作为其输入来训练,而不必显式地编程任何规则或游戏知识。更引人注目的是,论文中详细描述的系统在多个 Atari 游戏中使用(几乎)相同的架构击败了人类的表现,并且基于相对简单的概念,这些概念已经分别在强化学习(RL)和机器学习(ML)领域中被了解和研究了几十年。
A short snippet of a game that was the output of a Neural Network I trained — the green paddle is controlled by RafAI Nadal.
这一发现是第一个被证明可以推广到多个游戏的方法之一。自 2013 年最初的论文以来,其他几个研究小组已经在雅达利设置和其他几个场景中建立并超过了这些结果,例如 p 奠定 DOTA 或创建一个通用算法,可以通过自我游戏掌握多种游戏,如国际象棋&围棋。
怎样才能程序化的打败 Pong?
如果我们试图在没有任何正式方法的情况下编写代码来击败 Pong,我们可以尝试并捕获所有可能的动作,并查看哪些动作最终导致了游戏的胜利。
为了手动地做到这一点,我们可以根据两个玩家的球和桨的位置,为给定的输入帧选择最佳动作,并在每个场景中提出建议的动作,例如,在场景 A 中,如果 AI 桨在屏幕的顶部,球的轨迹朝向底部,则 AI 应该向下移动。
让我们回顾一下我们在这里处理的数字:模拟 Pong 的 Atari 仿真器输出一个 210 x160 RGB 显示,这是 100,800 像素。这些像素中有许多对于代理理解如何玩 Pong 是不相关的——在技巧部分中有更多的相关内容,所以我们可以丢弃它们,但是即使我们减少了 50%的输入像素,我们仍然有大量的像素。
手动计算出一个给定状态的正确动作是非常痛苦的。此外,如果我们编写一些试探法来分组屏幕的各种场景,例如在场景 A 中,并为给定的场景编写一个动作,这将意味着我们最终会编写非常 Pong /游戏特定的代码,这不是我们想要的。
我们如何才能避免手动编写推荐操作的代码?最天真的解决方案是,首先对输入采取随机动作,看看哪些动作有效,并在如下所示的地图中存储给定输入图像中哪些动作效果好(即,导致游戏获胜):
这允许我们估计场景的概率,并通过选择具有最高概率的动作来选择更好的动作。
例如,在 Pong 游戏中,如果我们想要比较给定图像的向上和向下动作,我们会看到下面的分数是否超过 0.5,并且在这种情况下选择向上动作:
For Pong, assuming we only have UP & DOWN actions, we only need to store counts for either UP or DOWN to get the correct fraction
如果概率是 0.5,我们可以抛硬币选择一个随机动作。
通过大量的游戏和*均,这将很好地工作,因为我们对给定图像的哪些动作有效的经验有助于通知代理(基本上是 AI)一个比完全随机的动作更好的动作。上面描述的自动化方法可以更正式地描述为强化学习,,因为我们有一个代理,它正在对其环境执行动作,观察结果,收集奖励,并使用收集的奖励知识来修改任何未来的动作,以便表现得更好。
尽管上述方法存在一些低效之处:
- 奖励的稀疏性使得这种方法相当无效,因为在游戏过程中可能有多个动作和过渡,但是在 Pong 的情况下,比如说 10 个来回的回合只有一个奖励,每个回合包含大约 10 个动作/移动,所以大约每 100 个动作有一个奖励。其他游戏可能比 Pong 少得多,其中一个动作现在影响游戏进行几分钟,也许几小时后。这使得给一个特定的行为分配信用变得相当具有挑战性。
- 你可能知道在 Pong 中有一类行动,其中代理人只是保持反弹,而另一类行动可能会赢得比赛,包括在赢得比赛之前的行动。
- 对于我们以前没有见过的图像,它不会工作得很好,因为它不能处理看起来相似的图像。这意味着我们必须运行更多的迭代,以允许 AI 探索整个状态空间和/或直到我们开始得到好的结果。
天真地将一场胜利游戏中的每一个动作都贴上好的标签是危险的,可能会导致混乱的结果,并且可能需要很长时间才能击败对手。稍后我将谈到我们如何解决这个问题,但首先请阅读 RL 的更正式定义。
什么是强化学习?
RL 的主要前提是通过在多个周期内在环境中尝试各种允许的动作,观察那些动作的结果,并使用经验来通知未来的动作,来为 AI(在该领域中被称为代理)建立经验历史。这是一个反复试验的过程,适合于完全自主运行的代理,不依赖于人的输入。对于一个学习有效玩 Atari Pong 游戏的 AI 代理来说,它需要玩多轮游戏,观察给定输入*图像的哪些动作效果最好,然后修改其行为以增加对输入效果好的动作的频率,反之亦然。
*暂且不提对强化学习感兴趣的术语
注意,输入对应于我们的 Pong 示例的状态。 状态 是代理认为它对允许它做出决策的环境的了解的表示。
代理的环境可以是或 部分可观察的 :在 Pong 的情况下,环境是完全可观察的,假定整个游戏区域是可见的,并且可以完全被输入图像所占据。完全可观察的环境,其中输入映射到状态的情况很少发生,例如在现实生活场景中,机器人使用相机在户外导航其环境,它部分观察其环境并基于其观察结果计算状态,这可能是存储障碍物及其感兴趣特征的某种地图。在这种情况下,摄像机输入并不映射到整个状态,而是只贡献其中的一小部分。
A simple diagram showing the way in which an Agent interacts with its environment [Source — OpenAI Spinning up]
RL 使用奖励的想法来决定执行哪些动作,对于 Pong 游戏,代理人每赢一轮,奖励就是+1,而对手 CPU 每赢一轮,奖励就是-1。对于其他游戏,如太空入侵者,奖励可以与击落不同类型的外星人获得的分数增量挂钩,但在现实生活中,计算奖励可能会更棘手,尤其是在没有明显的单一分数或目标需要优化的情况下。
在 RL 领域中,策略是规则、策略或行为功能,它评估并推荐给定特定状态的下一个动作;实际上,它可以被认为是从国家到行动的地图。一个策略在本质上可能是确定性的或随机的,由于一个 RL 代理的最终目标是最大化它的回报,我们希望选择一个策略来最大化给定行为的未来预期回报。Pong 情况下的策略帮助代理选择一个可能的动作,即向上、向下移动球拍或什么也不做。
Markov Decision Process diagram [Source — Wikipedia] . Green Circles represent states, red nodes represent actions, decimals represents probabilities of given actions, lines represent transitions between states. The expected reward for a transition is represented by the number at the end of the yellow wiggly line
RL 基于称为马尔可夫决策过程 (MDPs)的模型,这些模型是包含与环境中的可能状态相对应的不同节点的状态图,以及与代理可能采取的行动、其概率和预期回报相对应的状态之间的链接/边。Pong 也可以建模为 MDP,其中桨&球的每个配置都是一个状态,每个状态都有两个可能的状态转换箭头,每个转换都有一个奖励 0,除了最终的终端状态,奖励可能是+1 或-1。将问题公式化为 MDP 允许我们受益于马尔可夫属性,该属性陈述:
"鉴于现在,未来独立于过去."
MDPs 的主要优点是,当前状态可以完全描述问题的特征,并允许代理独立于历史做出最优决策,因为历史可以编码在当前状态中。
*暂且不提对强化学习感兴趣的术语
值函数 是一种评估给定状态或状态-动作对有多好的方法,可用于选择试图将代理转换到未来状态的动作。有多种类型的价值函数,它们对将用于计算价值的政策做出不同的假设。要获得大量资源,请查看 OpenAI 对值函数类型的解释 。
在 基于模型的 学习中,模型编码了一种对世界的理解,这种理解是由一个代理探索其环境而获得的,并且这种对世界的理解被用于在执行任何动作之前提前计划和计算对未来状态的期望。基于模型的代理的缺点是选择一个动作会导致较高的计算成本,但是可能更适合于具有大量状态的环境,其中评估所有状态是不可能的,例如在国际象棋游戏中。
在 无模型 学习中,一个智能体利用没有关于世界的先验知识,例如物理定律,关于如何玩其他游戏的知识,来采取一个行动。在这篇文章中,我们使用了一个无模型代理,因为神经网络被用来直接选择未来的行动,而政策并没有直接给我们任何关于世界未来状态的预测。
稍后我们将使用一个非常简单的优势函数,它是一个标量。
在一场胜利的游戏中,除了给每个动作*均分配奖励,我们还能做得更好吗?
前面描述的随机方法结合存储获胜动作的计数可以被描述为一种策略,一种糟糕的策略,但仍然是某种策略。
我们可以做得更好的方法之一是通过奖励折扣更明智地分配行为奖励。在代理人收到奖励之前的最*动作或帧是最相关的,因此在正面奖励的情况下应该鼓励,在负面奖励的情况下不鼓励。从收到奖励时起,时间上更早的任何行为或帧都被归因于指数因子贴现因子γ(γ)的较少功劳,在本文稍后编码的示例中将其初始化为 0.99:
*1\. def discount_rewards(rewards):2\. discounted_r = np.zeros_like(rewards)3\. sum_of_rewards = 04\. for t in reversed(xrange(0, rewards.size)):5\. if rewards[t] != 0: running_add = 06\. sum_of_rewards = sum_of_rewards * gamma + rewards[t]7\. discounted_rewards[t] = sum_of_rewards8\. return discounted_rewards*
这段代码是在一集的基础上运行的(一集是一系列回合,直到一个玩家达到 21 岁),但实际上我们只对一个回合应用折扣,因为上面第 5 行的sum_of_rewards
变量在奖励不为零时被重置,这是在每个“回合”结束时。
The effect of discounting rewards — the -1 reward is received by the agent because it lost the game is applied to actions later in time to a greater extent [Source — Deep Reinforcement Bootcamp Lecture 4B Slides]
折扣的效果是更准确地将奖励归因于可能对奖励有重要贡献的行为,因此帮助我们更接*我们想要的地方。
Pong 有一个非常简单的奖励设置,因为只有赢得游戏的奖励,但在更复杂的问题中,折扣函数可以用作 RL 问题中值函数的一部分,以根据预期的未来奖励来评估状态:
Finite-horizon reward discounting function, γ is the discounting factor, n is the number of timesteps, r is the magnitude of the reward for a given timestamp t + n, and H is the horizon for which we count the rewards. H may be infinity if we wish to account for actions an infinite amount of time away, which in practice is difficult.
更好的架构是什么样子的?我们实际上是如何编码的呢?
正如前面所观察到的,手动尝试捕获程序的状态是很棘手的-来自 DeepMind 论文的关键见解是使用神经网络作为一种手段来*似策略函数,而不必为每个输入图像状态显式编码。
Architecture of the Neural Network used in the code example later in this post [Source — Andrej Karpathy, Pong from Pixels blog post]
策略函数,或称策略网络,用于根据 Pong 和许多 Atari 游戏的输入来决定下一步做什么,是一个具有 n 个隐藏层的全连接神经网络,这就是为什么这种方法被称为 Deep RL,尽管在本文中我们只有一个隐藏层。神经网络将游戏的一帧图像作为输入,其中每个像素对应于一个单独的输入神经元,并输出一个介于 0 和 1 之间的小数概率,该概率对应于我们的代理过去对类似图像采取的行动是向上移动的概率。请注意,如果概率低于 0.5,并且越接* 0,代理采取向下移动的动作的概率越高。由于该策略输出一个概率,因此该策略是随机的。
对于隐藏层代表什么的直觉,它可以被认为对应于各种游戏场景,例如,一个可能的场景是球向上移动,代理桨在底部。在下面的链接代码中,我们在隐藏层中有 200 个单元,这比 6400 个输入神经元减少了很多(参见技巧预处理部分了解我们如何从 100000 像素增加到 6400 像素)。
隐藏层中的单元数量是系统的超参数,对于我们的系统,我们有 200 个单元。这个数字是我们需要多少表示的粗略猜测,但在实践中,我们将使用自动方法来确定隐藏层的数量和大小。
隐藏层的输出被映射到一个 sigmoid 函数,它有效地将输出压缩到 0 & 1 之间的概率范围内。
然后,我们使用这个神经网络输出和一个锁定的随机数生成器来生成一个介于 0 和 1 之间的浮点数,以确定下一步是上涨还是下跌。
*action = 'DOWN' if np.random.uniform() < action_prob else 'UP'*
Playing pong before much training, the green paddle, RafAI Nadal, is struggling to keep up since it is initially performing completely random actions
随机数生成器的目标是引入对新状态的探索,这在早期神经网络无法真正区分好的行为和坏的行为时至关重要,因为神经网络权重是随机初始化的,并且由于 sigmoid 函数的形状,任何给定输入图像的概率输出都接* 0.5。这导致我们的代理人随机采取一系列行动,起初没有协调感…附带说明:根据随机因素调整的计算行动概率选择行动的过程也称为采样。
随着神经网络越来越多地被训练,并且假设政策*均回报增加,随机性因素起着较小的作用,因为随着时间的推移,应该采取某个行动的概率更接*于 0 或 1 的极端值,并且action_prob
决定结果。有助于代理探索状态空间的另一个因素是随机策略的使用——如果策略是确定性的,我们将只依赖随机数生成器进行探索,这最初是好的,但是这将意味着任何新的动作都是完全随机的,并且较少受 NN 捕获的先验概率的驱动。由于代理停止探索状态空间,探索的减少和对已知良好动作的更大利用也会使策略陷入局部最优。
神经网络方法的另一个好处是,如果前面描述的映射实际上没有遇到输入图像,这对神经网络来说不是问题,因为大部分像素可能与神经网络已经看到和训练的图像相似,所以神经网络可能输出与先前看到的图像相似的预测。同样,我们可以手动进行这种相似性比较,但这需要更多的工作,而且神经网络是免费的。
但是当&强化学习中的神经网络是如何得到训练的呢?
强化学习(RL)使用尝试各种动作的多个周期来教会自主代理如何在环境中执行任务。
在一个情节 *** 中,在多个回合 *** 中尝试了一系列动作之后,我们通过使用该情节中发生的所有动作来训练NN。
Pong 中回合 对应其中一方玩家获得分数&奖励 1 并赢得一场拉力赛,输的玩家获得分数 0 和奖励-1。*
在 Pong 比赛中,安 第一集 一直进行到其中一名选手得分达到 21 分。剧集是一个术语,在所有 OpenAI 健身房环境 中使用,包含一个严格定义的任务。*
要更深入地了解神经网络是如何训练的,请继续阅读…
在监督学习中,我们通常有代表样本输入的基本事实的标签,这有助于我们计算损失(预测和实际标签之间的差异),进而有助于我们使用反向传播和优化算法调整神经网络的权重。
**
Supervised learning has a lot in common with Policy Gradients [Source — Andrej Karpathy’s blog]. The diagram on the left shows the supervised learning case: an image of Pong in which the agent’s best action is DOWN, and there is a label corresponding to the DOWN action, therefore the gradient that encourages the DOWN label for the input image is encouraged. The diagram on the right shows the Policy Gradient case: an image of Pong in which the action ‘sampled’ was UP, however given the game in which the action took place led to an eventual reward of -1 (due to a loss), a negative gradient is used to discourage the UP action for the given image.
在 RL 中,没有标签,也没有地面真相,所以我们改为使用假标签,它对应于一轮结束时收到的奖励,以便计算损失和梯度。如同常规的监督学习一样,损耗和梯度向量被用于使用反向传播和优化算法来更新 NN 权重,该算法被用于鼓励导致正奖励的行为(通过增加其输出概率),反之则为负奖励。假标签由我们之前计算的贴现优势因子 A i、决定,其大小取决于我们对该行为的奖励贴现多少。让我们看一个例子:
The loss function for the Neural Network that implements the Policy Gradient. y is the action we happened to sample given the image x, and A is a number that we call an advantage, which is a number from between -1 & 1 for our Pong example. Maximize this function for when an action has a positive reward, minimize when action has a negative reward
如果我们的策略采样的动作是向上,但是发生该动作的一轮导致最终奖励-1,因为它是一个失败的一轮,负梯度用于阻止给定图像的向上动作-参见上图右侧的直观解释。
请注意,我们只能在 Pong 的一轮比赛结束后更新 NN 的权重,因为当我们知道这一轮比赛的结果时,我们只能得出优势因子/假标签。
这种技术被称为策略梯度,因为我们使用梯度向量来更新 NN 权重,以改进 RL 问题中用于选择动作的策略。当通过足够的迭代训练时,策略梯度是一种非常有效的方法,它可以让我们训练出一个*均可以击败 Pong CPU 玩家的代理。
提高我们代理绩效的其他“技巧”
我们可以做一些小技巧来帮助我们减少计算时间,在给定的“挂钟时间”内运行更多的剧集,并总体上提高性能。
图像预处理
- 图像裁剪 —正如你从 Pong 截图中看到的,有许多冗余区域对我们的算法没有任何价值,例如分数部分,以及分数下方的白色条。这有一个额外的好处,允许我们忽略比赛结果已经决定的部分,即在球已经过了挡板之后。
Diagram illustrating the case for ignoring / cropping the image section after the ball passes the paddle [Source — Deep RL Bootcamp Lecture]
- 灰度 —像素的颜色是不相关的,因此我们可以移除它们,无论是背景色还是桨色。球拍和球可以是相同的颜色,但应该是与背景不同的颜色。
- 下采样/降低分辨率 —让我们更少关心图像,并降低内存和计算要求。
Pong image after cropping, downsampling cropping
所有这些预处理步骤允许我们将超过 100,000 像素的图像转换为 6400 像素(80px * 80px 图像),如右图所示。
数值方法
- 获取一帧和另一帧之间的差异,而不是仅仅向神经网络提供图像——这允许我们捕捉图像中的运动
- RMS Prop 优化算法用于更新神经网络中的权重——每 10 集我们进行一次参数更新,以确保神经网络梯度得到调整,从而尝试更快地收敛
- 在将奖励传递给反向传播算法之前,将奖励标准化(减去*均值,除以标准偏差)。
编写代理程序
库& GitHub 库
代码使用了 python 和 numpy ,但没有深度学习库——正向&反向传播步骤是手工完成的。此外, OpenAI gym environment 用于加载 Atari Pong 仿真器并接收输入,这允许我们的代理采取行动。健身房环境也将奖励从环境反馈给我们的代理——因此我们不需要手动解析游戏图像中的分数。
更多细节可在 GitHub Repo 中找到:
* [## omkarv/像素乒乓
训练神经网络从像素播放 Pong-omkarv/Pong-from-pixels
github.com](https://github.com/omkarv/pong-from-pixels)
这个回购是基于安德烈·卡帕西的出色报道和要点。我添加了解释性的行内注释,录制视频功能,修复了一个小问题,所以我现在比基本报告裁剪更多的图像宽度,原因如上所述。
我修改了学习率,使其比源 repo 收敛得更快,并实现了一个提高性能的修复。
超参数值也可以在上面的报告中找到,但被设置为源报告的默认值,除了 RMSProp 的学习率被设置为 1e-03,而不是 1e-04,因为它的训练速度比 1e-03 快 3-4 倍。
接受过 GitHub 回购培训的代理的表现
Average reward per episode for the agent
玩这个游戏的代理在大约 13 个小时的时间里接受了 10000 集的训练,使用的是 2.6GHz i7 (6 核)的 MacBook Pro 2018。
在后面的 100 集里,在我停止训练的那一点,每集的运行*均分数是 2.5,也就是说,训练的 AI 智能体将赢得每集 21 分,达到 18.5 分。这篇博文的目标已经达到,所以我们现在可以停止了,但是如果你想知道进一步的训练是否会产生更好的表现…
在暂停训练脚本后再训练 5000 集,在大约 10 小时的时间内,每集的运行*均分数达到 5,即被训练的 AI 智能体将赢得每集 21 分对 16 分。随着剧集数量的增加,回报明显减少且更加嘈杂。噪音可以通过降低学习速度来减少,但代价是训练时间。
我还运行了没有上述 bugfix 的基本代码,并获得了更差的性能——花了 12000 集才达到每集-5 的尾随*均分数。性能上的差异有多少可以用 bugfix 或用于发现新状态的随机性来解释,这并不明显,只能通过两种解决方案的重复迭代来测试,不幸的是我没有时间进行测试。
感谢阅读!
参考资料/灵感
- 动词 (verb 的缩写)Mnih,K. Kavukcuoglu,D. Silver 等人,用深度强化学习玩雅达利(2013) ,NIPS 深度学习研讨会 2013
- 安德烈·卡帕西,学习玩像素乒乓
- 深度 RL 训练营视频
- 开放 AI 在 RL 中加速旋转
- 大卫·西尔弗深度 RL 系列讲座*
用 R 语言中的 OpenBUGS 求解基本贝叶斯网络简介
原文:https://towardsdatascience.com/intro-to-solving-basic-bayesian-networks-with-openbugs-in-r-51def271f3ed?source=collection_archive---------31-----------------------
贝叶斯网络是一种概率图形模型,它通过有向无环图表示一组变量及其条件依赖关系。“定向的”意味着连接图的节点的箭头是定向的(即具有方向),因此条件依赖具有单向方向。“无环”是指不可能通过网络循环。它只能上升或下降。
让我们从一个例子开始:
曼彻斯特联队正在参加英格兰超级联赛。在俱乐部历史上最成功的教练弗格森爵士退休后,他们一直在努力保持他们作为世界上最大的俱乐部之一的形象。去年,他们在联赛中只获得了第 6 名。因此,在 2019/20 赛季开始时,球迷们认为俱乐部将以 0.2 的概率排名联盟前 3,以 0.3 的概率排名第 4,以 0.5 的概率排名前 4。
这些可能性只有在俱乐部的关键球员马库斯·拉什福德整个赛季都没有严重受伤的情况下才成立。他受重伤的概率是 0.2。如果发生这种情况,上述季末头寸的概率分别为 0.1、0.2 和 0.7。
如果他们以前 3 名结束,他们将获得明年冠军联赛小组赛的资格。如果他们获得第四名,他们将不得不通过冠军联赛资格赛,因此他们进入冠军联赛小组赛的概率降低到 0.7。
曼联也在参加欧洲联赛,欧洲冠军联赛的第二梯队。作为前冠军,如果拉什福德身体健康,他们有 0.6 的概率再次赢得欧联杯。如果拉什福德受伤,概率降低到 0.4。如果他们赢得欧联杯,那么他们即使进不了前 3,也保证以 0.99 的概率在明年的欧冠小组赛中占有一席之地,除非欧足联改变明年的规则。
如果俱乐部获得了明年冠军联赛小组赛的资格,他们将有 0.7 的机会签下他们的首要转会目标之一,来自里斯本竞技的布鲁诺·费尔南德斯。如果没有,签下费尔南德斯的几率降低到 0.4。
2020/2021 赛季初,布鲁诺·费尔南德斯是曼联球员。
-拉什福德受伤的概率有多大?
-俱乐部获得欧冠资格的概率有多大?
-俱乐部进入前 3 名的概率有多大?
-俱乐部获得第四名的概率有多大?
-俱乐部赢得欧联杯的概率有多大?
当涉及的变量和依赖项的数量很小时,这种类型的一些问题可以直接使用贝叶斯定理公式来解析求解。然而,对于像上面的例子这样的问题,使用贝叶斯分析的软件应用程序来找到有问题的概率要容易得多。
这里,我们将使用 R 中的库“R2OpenBUGS”来求解这些概率。该库基于 OpenBUGS 软件,用于使用马尔可夫链蒙特卡罗(MCMC )方法对复杂统计模型进行贝叶斯分析。“bug”代表(贝叶斯推断使用吉布斯采样)。因此,要运行这个库,需要安装 OpenBUGS。安装说明可以在 这里 找到。
首先,我们导入库“R2OpenBUGS ”,并定义 OpenBUGS 程序的安装路径。
然后,我们将定义我们的模型
这里,先生表示马库斯·拉什福德,当先生大约为 2 时,拉什福德受伤,我们将该事件分配给受伤先生。请注意,在这种情况下,当先生在 1 左右返回时,拉什福德是合适的。这些事件的顺序可能会改变,这取决于我们以后如何分配概率。在这种情况下,我们几乎可以映射像(MRfit,MRinjured) -> (1,2)这样的事件。
类似地,还定义了其他变量。请注意,由于曼联在英超(EPL)的表现取决于马库斯·拉什福德的状况,因此在我们定义 EPL 变量时,“先生”变量也包括在内。其他依赖项也遵循类似的方式。
接下来,我们分配我们拥有的数据(即概率、确凿证据)。
我们看到 BF 被设置为 1。这是因为我们从这个问题中知道布鲁诺·费尔南德斯将在本赛季结束后与曼联签约。因此,这是确凿的证据,我们将 BF 变量赋值为 1。
其余的数据是给定的概率。具有相关性的概率具有矩阵的形式。请注意,这里定义矩阵的方式不同于 OpenBUGS 本身的原生矩阵配置。更多关于如何在 OpenBUGS 软件上定义矩阵的信息可以在 这里 找到。
接下来,我们需要遵循一个默认的强制步骤,称为初始化。然而,这更适用于涉及连续随机分布的问题,我们不需要在这里初始化任何值。但是,如果我们没有给初始化步骤赋值,那么这个包会返回一个错误,所以我们把它赋值为 NULL。
现在,我们可以运行模型来计算有确凿证据的概率。
“调试”默认为假。但是,建议将其切换为 True,因为在模型不运行的情况下更容易看到错误。我们现在可以运行代码让模型运行起来。这里,我们将运行并迭代模型 100,000 次,然后丢弃前 1,000 个结果,以确保不包括任何大的初始变化。
当模型运行时,OpenBUGS 将打开并显示一个类似上面的窗口。
它包含了我们正在寻找的所有答案,但是如果我们希望一切都在 R 中,我们将需要关闭应用程序,以便 R 代码可以完成运行。然后我们使用下面的代码在 r 中显示结果。
鉴于布鲁诺-费尔南德斯与曼联签约的消息,曼联获得明年欧冠参赛资格的概率为 81%。他们赢得欧联杯的概率也提高到了 62.5%。他们在英超联赛中获得前 3 名或第 4 名的概率也略高,分别为 20.8%和 30.3%。
值得注意的是,马库斯·拉什福德受伤的概率降低到了 17.6%,因为他对球队的表现起着重要作用,并直接影响到球队是否有资格参加 UCL 的比赛,这直接影响到费尔南德斯是否决定与曼联签约。
library(R2OpenBUGS)
OpenBUGS.pgm = "c:/Program Files (x86)/OpenBUGS/OpenBUGS323/OpenBUGS.exe"#Setting up the model
model <- function() {
MR ~ dcat(p.MR[]);
MRinjured <- equals(MR, 2);
EPL ~ dcat(p.EPL[MR,]);
EPLTop3 <- equals(EPL,1);
EPL4th <- equals(EPL,2);
EPLElse <- equals(EPL,3);
Europa ~ dcat(p.Europa[MR,]);
WonEL <- equals(Europa,1);
UCL ~ dcat(p.UCL[EPL,Europa,]);
InUCL <- equals(UCL,1);
BF ~ dcat(p.BF[UCL,])
}#Hard evidence: 1 is TRUE and 2 is FALSEdata <- list( BF = 1,p.MR = c(0.8,0.2),p.Europa = structure(.Data = c(0.6,0.3,
0.4,0.7), .Dim = c(2,2)),p.EPL = structure(.Data = c(0.2, 0.1,
0.3, 0.2,
0.5, 0.7), .Dim = c(2,3)),p.UCL = structure(.Data = c(1, 0.99, 0.99, 1, 0.7, 0,
0, 0.01, 0.01, 0, 0.3, 1), .Dim = c(3,2,2)),p.BF = structure(.Data = c( 0.7, 0.4,
0.3, 0.6), .Dim = c(2,2))
)#Initialization
inits <- NULL#Run BUGS and save resultsout <- bugs(data = data,
inits = inits,
parameters.to.save = c("MRinjured", "EPLTop3", "EPL4th", "EPLElse", "WonEL", "InUCL"),
model.file = model,
digits = 5,
n.chains = 1,
n.burnin = 1000,
n.iter = 100000,
OpenBUGS.pgm=OpenBUGS.pgm,
WINE = WINE,
WINEPATH = WINEPATH,
useWINE=F,
debug = T,
working.directory=getwd(),
DIC = F
)print(out$summary)
统计学简介—查看数据
原文:https://towardsdatascience.com/intro-to-statistics-looking-at-data-1-23c49ef2bbd8?source=collection_archive---------15-----------------------
有许多关于统计的免费学习课程和资料。
统计学可以有效地用于分析、估计,有时甚至预测现实世界的事件。当正确使用时,它将引导我们根据数据观察做出更好、更安全的决策。它是数据科学中的基本支柱,也是许多领域中极其有用的工具。
你能找到的最优秀的课程之一是【乌达城统计学导论】。
你会发现一个温和的和自定进度的领域介绍。对于那些像我一样在大学学位完成几年后对数据科学感兴趣的人来说,更新知识并开始在自己的模型中工作是完美的。我想全面地介绍一门统计学课程,作为课程完成的一部分,我正在写一些关于所有测试、编码和补充研究的帖子。
这些帖子可以在不参加课程的情况下阅读,因为它们主要涉及小测验,但我想对正在参加或考虑参加的人来说会更有趣——这是我强烈推荐的。
我希望你喜欢它们,让我们开始吧。
第 2 课:查看数据
在本课程的第 2 课中(第 1 课只是一个预告片),通过一组关于房价的实际例子介绍了数据探索的基本概念。
这些概念引入线性回归作为估计值的最简单形式。给定一个遵循直接关系的样本数据集,您可以估计一个表示直线的函数,这将使您能够估计任何值。
第一个数据集显示以下值:
Quiz: Valuing Houses 1 – Image from Udacity Intro to Satistics –
在这种情况下,首先要做的是绘制值。我们可以通过下面的源代码轻松实现:
# --编码:utf-8 --
导入 matplotlib
matplotlib . use(' Agg ')将 numpy 作为 np 导入
将 matplotlib.pyplot 作为 plt 导入size = [ 1400,2400,1800,1900,1300,1100]
cost = [ 112000,192000,144000,152000,104000,88000]plt.scatter(size,cost)
PLT . save fig(' values 1 . png ')
Valuing Houses — Plot 1
这是一个理想化的场景,其中所有的点都正确对齐。没有必要做数学来提取线参数来回答一个 1300 英尺的房子多少钱,这个问题是数据的一部分和所有的数据点完全对齐。请注意,如果这些点没有对齐,数据集中的精确数据点并不意味着价格有效。
即使这是一种理想化的情况,并且不需要计算线性回归,我们也将使用第一个例子来实现我们的第一个线性回归。
我们的第一个线性回归
用直线来逼*数据集的统计操作称为线性回归。线性回归基本上是一种算法——实际上,它是实现相同目标的一系列算法——它找到一条尽可能接*所有数据点的线。正确的定义可以在维基百科中找到,它简洁明了,所以我们在这里引用它:
在统计学中,线性回归是一种线性方法,用于模拟标量响应(或因变量)与一个或多个解释变量(或自变量)之间的关系。一个解释变量的情况称为简单线性回归。[1]
在第一个课程示例(测验 1)中,展示了所有数据点对齐的特殊情况。在这种情况下,线性回归可以有效地跨越所有数据点。这是一个很好的机会来看看线性回归提供的统计数据会发生什么。
为了计算线性回归,我们可以使用 SciPy 包中的 stats 模块。
# --编码:utf-8 --
导入 matplotlib
matplotlib . use(' Agg ')从 scipy import stats 导入 numpy 作为 np
导入 matplotlib.pyplot 作为 plt#散点图
size = [ 1400,2400,1800,1900,1300,1100]
成本= [ 112000,192000,144000,152000,104000,88000]plt.scatter(size,cost)
PLT . xlabel(' \n size in ft2 ')
PLT . ylabel('美元价格\ n ')#线性回归
gradient,intercept,r_value,p_value,std_err = stats . Lin regressive(size,cost)
打印“梯度和截距”,Gradient,intercept
打印“R *方”,r_value**2
打印“p 值”,p_value
打印“标准误差”,STD _ errlr_x = np.linspace(1000,2500,100)
lr _ y = gradient * lr _ x+interceptplt.plot(lr_x,lr_y,'蓝色')
#构建图
plt.xlim([1000,2600])
plt.ylim([80000,200000])
PLT . save fig(' values1b . png ')
Valuing Houses — Plot 1 with linear regression line
该代码还从计算的线性回归中提供以下值:
梯度和截距 80.0 -2.91038304567e-11
R *方 1.0
p 值 1.5e-40
标准误差 0.0
线梯度为 80,与数据集有意义;一栋 1300 英尺的房子意味着 104.000 美元的价格,也就是 80 乘以 1300。截距点几乎为零(与 y 轴刻度相比可以忽略不计)。
关于 R *方、零假设、p 值和标准误差
我们的第一个例子是探索第一个统计变量的绝佳机会。线性回归不仅提供了数据的估计模型,而且我们还可以测量我们的模型有多精确和可靠。
我不会深入回顾这些概念,因为它们在其他地方会有更好的解释(我会提供链接),但至少我会提到它们,说明它们如何帮助您了解您使用的模型是否可靠。
—
R 的*方 是决定系数。它介于 0 和 1 之间,代表线性回归模型与数据的拟合程度。接* 1 的值意味着模型非常符合数据。因为它实际上跨越了所有的数据点。所以这是我们能得到的最好的了。
**R 的*方是决定系数。它是数据与拟合回归线接*程度的统计度量。
—
不先理解零假设**就无法解释 p 值。
在推断统计学中,零假设是一个一般的陈述或默认立场,即两个测量的现象之间没有关系,或者组之间没有关联。[2]
所以基本上,默认情况下,你假设因变量和自变量完全不相关。这就好比,除非被证明有罪,否则每个人都是无罪的。维基百科对零假设提供了一个很好且容易理解的解释。
—
p -values 帮助你确定你的结果/模型的重要性。它基本上衡量你是否否认/拒绝零假设。较小的值(小于 0.05)表示反对零假设的有力证据。较大的值(大于 0.05)表明您的模型/分析未能否定/拒绝零假设,因此您的模型/分析没有证明变量之间的依赖性。更多关于 p 值的信息可以在找到。
p 值帮助您确定结果/模型的重要性。它基本上衡量你是否否认/拒绝零假设。
在这个例子中,p 值可以被认为几乎为零,因此我们可以相当确定自变量和因变量之间存在相关性。
—
线性回归的标准误差代表观察值偏离回归线的*均距离。一个合适的定义可以在这里找到。
线性回归的标准误差表示观察值偏离回归线的*均距离。[3]
在我们的例子中是零,因为所有的数据都完全符合我们的模型。
你的模型准备好了
Quiz: Valuing Houses 3 – Image from Udacity Intro to Satistics –
现在你已经提出了一个模型,你可以准确地估计其他价格值,比如一个 2100 英尺。由于坡度为 80 °,而截距为零,得到的值就是坡度乘以*方英尺。
p =大小梯度+截距= 210080 = 168000
第二课复习到此结束。在本课程中,所有示例价格都是在假设数据是线性的情况下计算的。这篇文章更准确地解释了线性是如何计算的,以及线性回归在完美的线性数据集中是如何表现的(这在现实世界中几乎不会发生)。
参考
[1]https://en.m.wikipedia.org/wiki/Linear_regression
[2]https://en.m.wikipedia.org/wiki/Null_hypothesis
[3]http://statisticsbyjim . com/glossary/standard-error-regression/
[4]https://eu.udacity.com/course/intro-to-statistics-ST 101
结合交易实例介绍支持向量机
原文:https://towardsdatascience.com/intro-to-support-vector-machines-with-a-trading-example-1d4a7997ced6?source=collection_archive---------7-----------------------
让我们试着理解支持向量机,以及如何在金融市场中实现它们
就像任何其他机器学习算法一样,支持向量机(SVM)将数据作为输入,试图找到并识别模式,然后告诉我们它学到了什么。支持向量机属于监督学习的范畴,这意味着它创建一个将给定输入映射到输出的函数。更具体地说,SVM 是一种分类算法。
在我们开始实现交易算法和寻找阿尔法值之前,让我们弄清楚 SVM 是如何工作的
最大间隔分类器
支持向量机算法来自于最大间隔分类器。 最大间隔分类器 使用距给定决策边界的距离来对输入进行分类。距离或裕量越大,分类器处理数据就越好。在笛卡尔*面上,边界可以被认为是一条线。在三维空间中,它是一个*面,但在此之后,它变得难以概念化。这个边界可以更好地被认为是一个 超*面 ,特别是维度 p-1 中的一个,其中 p 是数据点的维度。
我们的边界或超*面被称为分离超*面,因为它用于将数据点分成所需的类别。一般来说,有许多超*面可以分离给定的数据集,但我们关心的是 最大间隔超*面 或 o 最佳分离超*面。这个分离超*面是与训练集中的每个数据点具有最大最小距离的超*面。通过使用这个超*面来分类来自测试集的数据点,我们得到了最大间隔分类器。
Source: Introduction to Statistical Learning
上图中的线代表超*面。请注意,它完全分隔了图表中蓝色和紫色区域的所有点。
现在,最大间隔分类器在一定程度上起作用了。如果你有一个不能被超*面分割的数据集,你就不能再使用它了。有时,您可能会遇到具有两个以上类别的数据,这使得线性边界毫无用处。
此时,您必须考虑您的选择:
- 如前所述,您可以将分类器基于分离超*面。但是超*面不存在…所以你没有分类器。
- 考虑一个不完美的分类器,但是它在某些时候/大部分时间都可以工作
支持向量分类器
我也喜欢第二种选择。通过使用一个不完美的分类器,您至少可以处理大多数观察结果,并在模型出现新数据时引入一定程度的适应性。
最大间隔分类器的这种演变被称为 支持向量分类器 (SVC),或者软间隔分类器。SVC 的分类并不精确,也不是非常稳健,它允许一些观察值位于边缘和/或超*面的错误一侧(软来自于此),以便得到最正确的分类。
在不涉及太多数学知识的情况下,该算法通过找到一个优化问题的解决方案来确定一个观察值将位于超*面的哪一侧,该优化问题使用一个调整参数、边缘的宽度(它试图最大化该宽度)和松弛变量。
调谐参数用于控制偏差-方差权衡。当它很小时,分类器非常适合数据,因为边距很小。换句话说,低偏差,高方差。更大的调谐参数是相反的。它允许更多的观察值位于误差的错误一侧,从而允许高偏差和低方差。
尤其是松弛变量非常酷。它们允许数据点位于边缘或超*面的一侧。它们还被用来将不*等转化为*等。松弛值的值也可以告诉我们给定数据点的行为。如果给定数据点的松弛变量等于 0,则该数据点位于页边距的右侧。如果松弛变量大于 0 但小于 1,则数据点位于页边距的错误一侧,但位于超*面的右侧。如果松弛变量大于 1,则数据点位于超*面的错误一侧。
这种优化的主要原因是它对超*面的影响。影响超*面并进而影响数据点如何分类的唯一值是那些位于边缘或错误一侧的值。如果一个物体在超*面的右边,它对它没有影响。分类器的名字来源于之前的数据点,因为它们被称为支持向量。
最后,支持向量机
支持向量机通过使用内核来增长特征空间,从而在支持向量分类器中建立优化。
与前面的优化类似,内核使用了相当多的数学知识。简而言之,内核告诉我们数据点有多相似。通过给数据序列分配权重,它可以识别两个点有多相似,因为它已经学会了如何比较它们。内核允许以更简单的方式处理数据,而不是在高维空间中处理。更具体地说,它计算特征空间中所有数据点对的所有可能输出之间的内积。通过使用核而不是扩大特征空间,该算法可以更加有效。它使用一个函数来比较不同数据点对,而不是对数据集中的原始要素使用函数。
存在许多不同的核,包括 RBF 核、图形核、线性核、多项式核。例如,线性核通过使用它们的二元相关性来比较一对数据点。多项式核试图在高维空间中拟合 SVC。支持向量分类器与使用具有 1 次多项式核的 SVM 是一样的。
基本上,支持向量机的主要目标是构建一个超*面,然后使用它来分类数据。尽管通常被归类为分类算法,但有一个用于回归的支持向量机的扩展,称为支持向量回归。
交易的支持向量机
在我进入这个应用程序之前,这绝不是关于你应该如何交易的建议。那是你的责任。
我们将从收集数据开始。
我们将使用大约五年前的时间段,从 2014 年 10 月 28 日到 2019 年 10 月 28 日。我们将获得数据的股票是道琼斯工业*均指数的组成部分。
雅虎财经曾经很容易获得数据,但大多数软件包不再工作,所以我们也将在这个过程中创建一个网络刮刀。
我们要做的第一件事是导入我们需要的所有包。
然后我们将使用 requests 包来抓取雅虎财经上这个页面的内容。该页面包含组成道琼斯工业*均指数的公司名称,以及它们的代码。接下来,我们将使用beautiful soup 4使 Dow_Content 中的信息可搜索。
上面的几行代码解析从 web 页面收集的数据,并搜索与页面上的表格相对应的 HTML 代码。这可以通过右键单击页面区域,检查元素来找到,稍微调查一下就可以找到上面使用的类名。
搜索将会遇到两种类型的行:
- 包含股票代码的行
- 包含公司名称但没有股票代号的行
我们不关心后者,所以当循环找到它们时,它忽略那个位并继续前进。一些字符串操作来删除多余的脂肪,我们有我们的股票。然后,每一个股票都被添加到一个列表中,以便安全保管。
Yahoo Finance 在他们的 URL 中使用了 Unix 时间戳,所以我们使用了 time 包来将我们的开始和结束日期转换成所需的格式。它可以采用 struct_time (这里有更多关于的内容)或者一个由 9 个时间参数组成的元组。我们真的不在乎任何过期的东西。
ScrapeYahoo 函数有四个参数:
- data_df ,你指定的存储输出的数据结构
- ticker ,代表给定股票的字符串
- start ,一个代表开始日期的 Unix 时间戳
- end ,代表当天的 Unix 时间戳
它将这些与 Yahoo Finance 的基本 URL 结合起来,并从所需的网页中获取数据。我们不再像以前那样处理它,而是从页面中解析 JSON 数据。雅虎财经现在用 cookies,单纯用 HTML 代码会抛出错误。
后面的几行解析 JSON 数据的内容。在我最初探索数据集时,Python 字典的 keys() 方法非常有用。这使得遍历 JSON 数据变得更加容易。你可以在这里读到它
字典 Stock_Data 将保存我们解析的数据。字典中的关键字将是给定股票的代码。对于每只股票,函数 ScrapeYahoo 将创建一个包含开盘价、最高价、最低价、收盘价和成交量数据的数据框架。
我们有历史价格数据,现在呢?回想一下,支持向量机是一种分类算法。我们将尝试在技术分析的帮助下为我们的模型创建特性。
技术分析是一种利用过去的数据来预测价格未来走向的方法。一般来说,技术指标在计算中使用价格数据和交易量。选择这些指标的动机来自于文章末尾参考文献部分列出的论文。
继续前进之前需要注意的一件非常重要的事情: 前瞻偏差 。我们已经有了所有的结算数据,这些数据将用于计算。在现实世界中,你最多只有前一天的收盘。我们必须确保我们的计算不会包含技术上尚未出现的数据。为此,我们将滞后数据。也就是说,将我们的数据向后移一天。
技术分析
我们将利用 talib 库执行技术分析计算。
Example of a chart with Bollinger Bands Source: Trading With Rayner
我们将使用我们的回报栏来计算我们每个交易日的标签。如果返回为 0 或正数,则标记为 1,否则标记为 0。请注意,returns 列使用的是开盘价而不是收盘价,以避免前瞻偏差。
训练模型
在我们开始建立模型之前,必须对数据进行规范化。这样,当 SVM 计算其距离时,所有的要素都会被缩放并赋予同等的重要性。
我们使用了maxabscaler,它根据每个特征的最大绝对值对其进行缩放。
接下来,我们创建了一个字典来存储训练和测试数据。如果不删除 NaN 值,模型将不会运行。变量 X 将包含模型的所有特征,然后将被缩放。丢弃信号和返回列是很重要的。我们正在预测这个信号,如果它保持下去,这个模型将*乎完美。如果我们保留 Returns 列,也会对模型产生太大的影响。请记住,信号列最初是通过使用计算的回报率计算的。 Y 是我们要预测的,所以我们把它赋给包含信号的列。
我们的模型将使用 70%的数据进行训练,30%的数据进行测试,如第 11 行所示。
该模型由模型变量定义(以防您感到困惑)。我在下面链接的笔记本中留下了各种内核配置,您可以随意使用。该模型符合训练数据,并用于预测信号列中的值。
最后,我们将每只股票的准确度、精确度和召回率添加到我们的模型字典中。
快到了!下一段代码使用来自 SVM 模型的信号计算回报。通过对熊猫数据帧使用 iloc 方法,将信号附加到末尾比我们之前所做的要容易得多。
我们将计算相对于市场表现的回报率,并以此作为我们的基准。投资组合的表现通过使用夏普比率来衡量。
最后,绘制预测结果的图表。
输出的几个例子如下:
Not bad!
Not too good…
结论
无论如何,这个模型并不完美,但它确实适用于道琼斯工业*均指数中的一些股票。有几种方法可以改进这一点:
- 使用技术指标创造信号,而不仅仅是回报
- 根据长/短场景调整模型
- 使用不同的技术指标
- 创建一个投资组合,包括头寸规模、交易成本、滑点等。
金融市场是一个非常复杂的地方,而我们的模型相当简单。这个例子简单地分类了以前的回报是否预示了未来的价格走向。
有很大的改进空间,所以尝试一下吧。参考资料中会有笔记本的链接,所以可以随意使用代码。
我希望这有助于你理解支持向量机!
参考
[1] R .罗西洛、J .吉纳、d .德拉·富恩特和 r .皮诺,标准普尔 500 指数中基于支持向量机的交易系统 (2012),2012 年国际人工智能会议论文集,ICAI,2012
[2] B. Henrique,V. Sobreiro 和 H. Kimura,使用支持向量回归对每日和最新价格进行股票价格预测 (2018),《金融和数据科学杂志》
[3] X. Di,用 SVM (2014)的技术指标预测股票走势
[4] G. James,D. Witten,T. Hastie 和 R. Tibshirani,统计学习导论及其在 R 中的应用(2017)
Python 代码
编辑:修正了在代码的不同部分使用“shift”的问题。感谢那些喊出它的人,我感谢他们的反馈。
介绍 Arauto:一个用于时间序列预测的交互式工具
原文:https://towardsdatascience.com/introducing-arauto-an-interactive-tool-for-time-series-forecasting-14b3e36b5f81?source=collection_archive---------16-----------------------
时间序列模型的快速实验和训练工具
Photo by Aron Visuals on Unsplash
时间序列预测一直是应用机器学习和统计模型的一个杰出领域,尽管许多数据科学家可能不认为它是一个像计算机视觉或 NLP 这样性感的领域。事实是,许多公司依靠时间序列预测和分析来了解业务的未来,如预测收入、活跃客户、*均门票等。
今天,我想介绍一个工具,它帮助我优化和提高了构建时间序列模型的效率: Arauto,这是一个用 Python 开发的开源应用程序,旨在为提供一种交互式和直观的方式来构建混合自回归移动*均模型(AR,MA,ARMA,ARIMA,SARIMA,ARIMAX,SARIMAX) 。
动机
在我目前的工作中,我负责创建和维护生产中运行的多个时间序列模型。 Hotmart 是世界上最大的数字产品*台之一,我们的高管、投资者、经理和领导层需要了解我们对未来一些关键业务指标的预期,比如我们将获得多少收入,我们将在基础设施上花费多少资金,或者我们预计未来几个月有多少活跃用户。
然而,我注意到我在构建模型时有两个主要问题:
- 我的大部分时间都浪费在了重复构建流程和代码上:那些肯定可以自动化的东西;
- 为我的模型迭代和试验不同的模型和参数不是很有成效。
这几点促使我开发了一个工具,它可以帮助我——当然也可以帮助更多面临类似问题的人——在我的项目中更加敏捷和高效。这个项目的结果是自动的。
Arauto at work!
阿拉图是什么?
Arauto 是一个开源工具,结合了一个交互式和直观的 web 应用程序,引导你完成时间序列模型的分析和构建。Arauto 的目标是在几分钟内给你一个预测模型,在这个过程的最后,它会生成用于转换和训练模型的代码,这样你就可以在 Jupyter 笔记本或 Python 脚本上复制和修改它。以下是 Arauto 的一些功能:
- 支持外生回归变量;
- 季节性分解,让你知道数据的趋势、季节性和残差;
- 使用增强的 Dickey-Fuller 检验的*稳性检验;
- 数据转换的*稳性定制:您可以使用从一阶差分到季节日志来转换您的数据;
- 用于项估计的 ACF (自相关函数) PACF (部分相关函数);
- 定制 ARIMA 条款或让 Arauto 根据您的数据选择最适合您的;
- 网格搜索功能用于参数调整;
- 代码生成:在过程结束时,Arauto 返回用于转换数据和训练模型的代码
Arauto predicting in-sample and out-of-sample data
如何安装
网
使用 Arauto 非常容易。如果你对你能做什么感到好奇,有一个在线版本,你可以点击这个链接进入。请记住,这是一个用于演示目的的轻量级版本,因为它使用的是 Heroku 的自由层实例。
码头工人
Arauto 可以很容易地安装使用 Docker。通过运行三个命令,您将准备好在自己的基础设施上使用 Arauto。
**# Clone the repository**
git clone https://github.com/paulozip/arauto.git
cd arauto**# Run the docker compose**
docker-compose up --build
还有另一个选择是通过使用 Conda 的环境来安装 Arauto。更多信息请参考 Github 知识库。
The code used to transform the data and train your model will be available at the end of the process
如何使用 Arauto
Arauto 被设计得尽可能直观,即使对于那些没有深入统计知识的人也是如此。然而,我们在几分钟内为你制作了一个完整的教程来帮助你开始使用 Arauto。请, 参考 Arauto 的文档了解更多 。
You can customize Arauto or let it choose the best parameters for you
如何投稿
目前,这个项目只由一个人维护。如果有更多的人合作并为这个开源项目做出贡献,那就太好了。如果你想和 Arauto 合作,你可以这样做:
- 文档和教程:让用户一打开浏览器就进入 Arauto 真的很重要。教程和更深入的文档可以帮助我们实现它。
- 新算法:我们可以给 Arauto 添加许多不同的算法,比如 ARCH、VAR 和基于树的算法等等。你所需要做的就是派生存储库,构建特性并打开一个 PR 来合并它。
- 错误修复:某些东西可能被破坏了。我们需要优秀的人来修复它。
- 测试 : Arauto 不包含测试,这是错误的。
- 请求功能 : 您可以使用我们的问题跟踪功能提出新的想法和功能。请求将通过竖起大拇指表情符号(👍)
获取更新
Arauto 将增加新功能。如果你想知道新版本何时到来,请订阅 Arauto 的时事通讯,了解新的事情。我们不会发送垃圾邮件或共享您的电子邮件。只会发送与 Arauto 相关的内容。
我希望你对和 Arauto 一起创造新事物感到兴奋。我是 Paulo Vasconcellos, Hotmart 的数据科学家,数据黑客的联合创始人:巴西最大的数据科学和机器学习社区。欢迎在 Linkedin 或 Twitter 上关注我(推文和帖子在 PT-BR 中)了解更多关于 Arauto 和数据科学的信息。再见!
熊猫图形用户界面 Bamboolib 简介
原文:https://towardsdatascience.com/introducing-bamboolib-a-gui-for-pandas-4f6c091089e3?source=collection_archive---------3-----------------------
几天前,Tobias Krabel 先生通过 LinkedIn 联系我,向我介绍他的产品,一个名为 Bamboolib 的 Python 库,他说这是一个学习熊猫的 GUI 工具——Python 的数据分析和可视化库。
Photo by Marius Masalar on Unsplash
他说,我引用他的话:
我们的目标是帮助人们快速学习和使用熊猫,我们希望加入下一代 python 数据科学家。
我不得不承认,一开始我持怀疑态度,主要是因为我不是 GUI 工具和拖放原则的忠实粉丝。尽管如此,我还是打开了网址,看了介绍视频。
这是少有的一次我被合理地激起了兴趣。
从那以后,我很快回复了 Tobias,他友好地让我测试一下这个库,看看我是否喜欢它。
情况怎么样?嗯,你必须继续阅读才能找到答案。所以让我们开始吧。
免费吗?
在一个像 Numpy 和 Pandas 这样令人惊叹的图书馆可以免费使用的世界里,这个问题可能甚至不会出现在你的脑海里。然而,它应该,因为不是所有版本的 Bamboolib 都是免费的。
如果你不介意与他人分享你的作品,那么是的,它是免费使用的,但如果这造成了一个问题,那么它会让你每月至少花费 10 美元,这对于普通用户来说可能是令人失望的。下面是完整的价目表:
正如该库的开发者所说,Bamboolib 旨在帮助你学习熊猫,因此我认为使用免费选项没有问题——如果你刚刚开始,很可能不会从事一些绝密项目。
然而,这篇评论将基于私人版本的图书馆,因为这是托拜厄斯给我的。话虽如此,这篇文章绝不是抱着劝你买许可证的想法写的,它只提供我个人的看法。
在进入好的内容之前,您需要首先安装库。
安装过程
要做的第一件也是最明显的事情是 pip 安装:
pip install bamboolib
然而,如果你想让这个东西完全工作,还有很多事情要做。它被设计成一个 Jupyter Lab 扩展(或者 Jupyter Notebook,如果你还在用那些),所以我们也需要在那里设置一些东西。
在命令行中键入以下内容:
jupyter nbextension enable --py qgrid --sys-prefix
jupyter nbextension enable --py widgetsnbextension --sys-prefix
jupyter nbextension install --py bamboolib --sys-prefix
jupyter nbextension enable --py bamboolib --sys-prefix
现在您需要找到安装在您机器上的 Jupyter Lab 的主要版本。您可以使用以下命令获得它:
jupyter labextension list
我的是“1.0”,但是你的可以是任何东西,所以这里是你需要执行的下一个命令的通用版本:
jupyter labextension install @jupyter-widgets/jupyterlab-manager@MAJOR_VERSION.MINOR_VERSION --no-build
请注意,您需要替换“MAJOR_VERSION。MINOR_VERSION”和版本号,在我的例子中是“1.0”。
再多几个命令,你就可以开始摇滚了:
jupyter labextension install @8080labs/qgrid@1.1.1 --no-build
jupyter labextension install plotlywidget --no-build
jupyter labextension install jupyterlab-plotly --no-build
jupyter labextension install bamboolib --no-build
jupyter lab build --minimize=False
就这样。现在你可以开始 Juypter 实验室,我们可以深入到好东西。
第一次使用
在 Jupyter 中,您可以导入 Bamboolib 和 Pandas,然后使用 Pandas 加载一些数据集:
以下是使用库查看数据集的方式:
当你第一次使用图书馆时,这是行不通的。您需要激活它,因此请确保将许可证密钥放在附*的某个地方:
输入电子邮件和许可证密钥后,您应该会收到以下消息,表明一切顺利:
很好,现在您可以再次执行前一个单元格了。你马上会看到一个陌生的,但看起来很友好的界面:
现在一切都准备好了,我们可以开始一些基本的功能了。走到这一步需要做很多工作,但是相信我,这是值得的!
数据过滤
任何数据分析师/科学家最常见的日常任务之一就是数据过滤。基本上,你只想保留在给定时刻与你相关的数据子集。
要开始用 Bamboolib 过滤,点击过滤器按钮。
应该会弹出一个类似下面的侧菜单。我决定按“年龄”列进行筛选,只保留“年龄”值小于 18 的行:
一旦你按下执行,你会看到动作立即发生:
太好了!但是你还能做什么呢?
替换值
另一个常见的日常任务是用相应的数字替换字符串值。这个数据集非常适合演示值替换,因为我们可以很容易地将“性别”列中的字符串值替换为数字值。
首先,点击替换值按钮,指定列、要替换的值以及要替换的内容:
一旦按下执行按钮:
太棒了。对于“女”的选项也可以这样做,但要不要做由你自己决定。
分组依据
是的,您还可以执行聚合!要开始,点击聚合/分组按按钮,并在侧边菜单中指定应该做什么。
我决定按“Pclass”分组,因为我想看看每个乘客级别的幸存者总数:
这将产生以下输出:
厉害!在结束之前,让我们再探索一件事。
一个热编码
很多时候,在为机器学习准备数据时,您会想要创建虚拟变量,因此为给定属性的每个唯一值创建一个新列。这样做是个好主意,因为许多机器学习算法无法处理文本数据。
要通过 Bamboolib 实现该逻辑,点击 OneHotEncoder 按钮。我决定从“apollowed”属性创建虚拟变量,因为它有 3 个不同的值,你不能说一个比另一个好。此外,确保移除第一个虚拟变量,以避免共线性问题(的变量是其他变量的完美预测变量):
如您所料,执行将在数据集中创建两个新列:
很好,我已经完成了我的转变,但是下一步是什么?
获取代码
直到现在都是有趣的游戏,但是迟早你会注意到这些操作没有在适当的位置执行——因此如果你不明确地指定它,数据集将不会被修改。
这不是一个错误,因为它使您能够在不弄乱原始数据集的情况下进行试验。然而,Bamboolib 要做的是,它将生成 Python 代码来实现期望的转换。
要获取代码,首先点击导出按钮:
现在指定您希望它如何导出—我选择了第一个选项:
最后,它会给出您可以复制并应用到数据集的代码:
值得吗?
至此,我简要展示了 Bamboolib 的主要功能——这绝不是详尽的教程——只是想向您展示它背后的思想。
问题是,它值这个钱吗?
如果你决定走付费路线的话。你仍然可以免费使用它,前提是你不介意与他人分享你的作品。该库本身值得一试,主要有两个原因:
- 它提供了一个学习熊猫的好方法——通过做来学习比通过读来学习要容易得多,而且像这样的 GUI 工具肯定只会对你有所帮助
- 它非常适合摆弄数据——让我们面对现实吧,有时候你知道你想做什么,但你就是不知道如何用代码实现它——bamboo lib 可以提供帮助
请记住——付费版本不会给你带来任何额外的功能——唯一真正的好处是你的作品将是私有的,并且可以选择用于商业用途。
即使你还没有准备好拿你的信用卡,尝试一下免费版并看看它是否能让你受益也不会有什么坏处。
感谢阅读。保重。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
在深度学习中引入卷积神经网络
原文:https://towardsdatascience.com/introducing-convolutional-neural-networks-in-deep-learning-400f9c3ad5e9?source=collection_archive---------10-----------------------
卷积神经网络又名 Convnets 或 CNN,是深度学习中神经网络的超级明星。这些网络能够执行图像、声音、文本、视频等相对复杂的任务。第一个成功的卷积网络是在 20 世纪 90 年代后期由 Yann LeCunn 教授为贝尔实验室开发的。
在类似 MNIST 的分类问题中,多层感知器(MLP)是最常用的,并且提供非常好的结果(很高的准确度),此外,训练时间保持合理。然而,对于具有较大图像的较大数据集,模型的参数数量呈指数增长,因此,训练变得更长,性能更差。
爆炸参数的数量
MLP 对于解决几类问题非常有效,例如分类、估计、*似、识别等。但是,它们很快就会变得有限,尤其是对于非常高维的输入数据。
假设我们想要创建一个深度学习模型来执行猫或狗的分类任务。该模型在大小为 420x420px 灰度的图像数据集上训练;训练结束后,我们希望模型能够说出图像是狗还是猫。例如,第一种方法是使用具有 128 个神经元的输入层的多层感知器。由于该层的每个神经元接收 420x420 像素值作为输入,并为每个像素值分配一个权重,因此我们得到每个神经元 420x420 = 176400 个权重,乘以总共 128 个神经元,最后加上 128 个偏差,每个神经元一个偏差。这个微小的模型将不得不学习超过 2200 万个参数,只需要 128 个神经元和一个中间层。如果我们想要一个强大的模型,它将需要几个附加层和每层更多的神经元。参数数量激增。例如,一个 3 层模型(128–256–1)需要将* 2300 万个参数。这种模型需要大量的数据来训练,并且由于要调整的参数多得多,训练阶段将持续更长时间,并且性能下降;让我们清楚地说,即使我们有足够的计算能力,也不可能正确地训练这个模型,因为这不是唯一需要处理的问题。
图像的空间退化
训练多层感知器需要以向量(一维数组)的形式提供输入数据。如果输入数据是一个矩阵图像,那么它必须被展*以得到一个矢量。然而,在自然图像中,相邻像素之间存在非常强的联系;通过展*图像,我们丢失了这些信息,网络在训练阶段解释数据变得更加困难。这证明了对解决这种问题的另一种神经网络结构的兴趣。让我们首先介绍卷积是由什么组成的。
卷积算法
卷积是一种滤波器(也称为内核)与图像矩阵的乘积运算,用于从中提取一些预先确定的特征。从字面上讲,我们使用卷积过滤器来“过滤”图像,只显示对我们真正重要的内容。所考虑的图像是矩阵,所使用的滤波器也是矩阵,通常是 3×3 或 5×5。让我们看看卷积如何与下面的内核一起工作,
Convolution filter
6x6px 矩阵代表一幅图像。开始时,卷积核(此处为 3×3 矩阵)位于矩阵图像的左上角,然后该核覆盖该矩阵图像的一部分,然后我们对两个重叠块进行逐个元素(逐元素)的乘积,最后对这些乘积求和,最终结果对应于输出图像的一个像素。
Convolution algorithm
然后,我们将卷积核从水*向右移动一个像素,我们生成一个新的元素乘积,然后相加得到输出图像的新系数。
一旦到了一行的末尾,内核垂直向下移动,然后从左边开始,我们同样迭代,直到内核覆盖了所有的矩阵图像。值得注意的是,内核始终保持在初始矩阵上,不会溢出。
当然,我们不能使用任何过滤器,我们的内核的系数将取决于我们希望过滤器突出的特征。让我们看看一些著名滤波器的卷积结果。
垂直索贝尔滤波器
它的作用是突出显示对象的垂直线。应用到左边的初始图像,这是结果,
Vertical Sobel filter
水*索贝尔滤波器
这次是为了突出图像的水*轮廓。这是应用于左侧图像的结果,
Horizontal Sobel filter
可以组合这些过滤器的动作来执行更复杂的操作。根据要解决的任务,已经列出了几个可以直接以这种方式使用的滤波器:*均滤波器、高斯滤波器等。在深度学习出现之前,人类专家必须计算并确定要使用的正确过滤器,以便执行特定的图像处理操作:人脸检测、照片编辑,像 Snapchat 过滤器等。现在有了深度学习,确定这些过滤器是通过学习自动完成的,模型会根据要解决的问题,从训练数据中找到好的过滤器。例如,在猫或狗的分类问题中,过滤器可以突出分类的决定性特征:耳朵的形状、眼睛的形状、口鼻的形状、轮廓等。
卷积神经网络
卷积神经网络,也称为 CNN 或 Convnets,使用上面介绍的卷积技术来建立模型,以解决在数据集上进行训练的各种问题。让我们看看经典的猫或狗分类问题中卷积网络的细节。
卷积的深度学习方法
在这个分类问题中,我们有两类,即狗和猫。将图像分类为这些类别中的一个类别,取决于诸如头骨形状、耳朵形状、眼睛形状等单一特征。只有这些特征对执行这一分类任务至关重要,其他信息对我们来说并不重要。
因此,理想的情况是从一幅图像开始,能够通过使用适当的过滤器来提取对分类问题感兴趣的主要特征。在深度学习环境中,它将是通过对数据集进行训练来确定这些过滤器的模型。
训练从内核(滤波器)的随机初始化值开始,在训练期间,这些值将通过梯度反向传播来更新。既然我们说的是深度学习,我们可以猜测几层卷积会一层接一层叠加起来,以增加模型性能。
填充和边缘效果
让我们再次以上面的卷积动画为例,看看输出图像的尺寸,也称为特征映射。输入图像是 6x6px 大小的矩阵,滤波器是 3x3 的矩阵。我们可以看到特征图(输出矩阵)是 4x4px 大小的。顺便说一下,一般来说,特征图的大小是,
Feature map size
其中 n 表示输入图像的尺寸,而 p 表示滤波器的尺寸。例如,对于初始 120x120px 图像和 5x5 内核,特色图像的大小为 116x116px。请注意,卷积会减小输入图像的大小。如果我们要输出一个与输入图像大小相同的特征图,我们必须在卷积之前在输入图像周围加零,输入图像是“用零填充”的,因此这种操作的名字, padding。我们来看一个例子。
带 3x3 滤波器的 6x6px 矩阵示例。
我们希望特征图具有与输入图像相同的尺寸,即具有 3x3 卷积滤波器的 6x6px。在上面给出的等式中,p = 3,m = 6,因此 n = 6+3–1 = 8。因此,有必要使输入图像的大小为 8x8px,这意味着我们必须在原始矩阵图像周围添加零,以达到 8x8px 的大小;因此下面的矩阵,
“Padded” matrix
填充不是强制的,一般会碰巧忽略;这可能看起来像轶事,但它确实有实际用途。让我们看看边缘像素,例如最左边的,他们只看到卷积核一次,而大多数其他像素看到它两次以上。因此,边缘像素对特征图的影响较小。为了限制这种副作用,我们用零“填充”原始输入图像,这样边缘的像素就不会被忽略。
激活功能
在训练期间,我们知道滤波器的系数被更新;这些可以是负的,正如我们在上面用 Sobel 滤波器所看到的,然后特征图的系数可以在训练期间保持大的负值。由于我们知道这些值代表像素级别,因此是正值,我们可以应用一个函数用零替换负值,并保持正值不变。这是一个名为 relu 的激活功能。但是请记住,还有其他激活函数,其思想基本上与 relu 相同,以保持特征映射值的合理性。
卷积层
提醒一下,卷积是将过滤器或内核应用于输入图像,然后我们得到一个突出输入图像的特征或“特征”的特征图:轮廓、斑点、形状等。每个过滤器都有一个简单而精确的任务要完成。所以,为了解决我们的分类问题(猫或狗),我们将不得不使用几个过滤器;并且通过组合由那些过滤器突出显示的特征;例如耳朵、眼睛和轮廓的形状,我们的模型将能够被训练来区分狗和猫。因此,我们必须选择要做的卷积的数量,也就是要使用的滤波器的数量,知道我们的滤波器越多,提取的用于分类的细节就越多,要学习的模型的参数就越多,但是模型保证的性能就越好(更高的精度)。之后,我们必须决定是否填充以及使用哪个激活函数。这定义了一个卷积层。使用多少个过滤器?64,128,256 …哪个激活功能?relu,乙状结肠,tanh …有没有垫?
比方说,我们有一个 128 个过滤器的卷积层;它为每个过滤器提供了一个特征映射,因此一个输入图像总共有 128 个特征映射。这些特征图代表了图像中包含的不同信息,所以我们可以把它们看作这个图像的不同通道。由于 rgb 图像包含三个通道(红色、绿色和蓝色),具有 128 个过滤器的卷积层提供了一个具有 128 个通道的单一特征图。如果相同的图像通过另一层 256 个过滤器,它将被输出为 256 通道的特征图,以此类推。
池算法
在自然图像中,像素之间有很强的局部相关性。这意味着,对于一幅图像,如果你知道一个像素是红色的,它的四个最接*的像素很可能也是红色的阴影。在灰度图像的情况下,例如,如果像素具有 180 的强度,则其最*的像素也将具有大约 180 的强度。因此,有可能通过仅保留每个像素局部块的局部代表来减小图像的尺寸,这被称为池化。一般来说,我们会将块中亮度最大(因此值最高)的像素— max pooling —我们也可以将块中像素的亮度*均— average pooling —并将其作为代表。
Max pooling operation
从上面可以看出,池将输入图像的每个维度(高度和宽度)减半。人们可能会认为,池化通过仅用一个像素表示一个像素块而严重降低了初始图像的质量;但实际上输出图像(特征图)当然是一半大,但包含了输入图像的主要特征。
例如,让我们将最大池化应用于水* Sobel 滤波器输出的特征图,“池化”的图像已经被放大用于比较。
Feature map after two max-pooling
请注意,即使经过两次合并,轮廓仍然清晰可见,图像的细节也不太丰富。池化不仅仅是调整大小,还仅仅保留输入图像的有意义的特征。
通常,在卷积网络中,有一系列操作;卷积-池层-卷积-池层等等。通过多次重复这些操作,我们最终获得仅具有输入图像的有意义(根据所解决的问题)特征的特征图。我们现在可以利用多层感知器的能力来完成分类任务。
展*特征图
为了最终将图像分类到一个类别,比如猫或狗,我们将在最后一个卷积层的顶部设置一个多层感知器(多层感知器)。先前的卷积和汇集操作已经极大地减小了输入图像的大小,以唯一地保持分类的有意义的特征。由于供给 MLP 需要输入向量(一维数组或 1d 数组),我们需要“展*”输出特征图。因此,MLP 接收小尺寸的特征地图作为 1d 阵列,并选择关于那些特征地图的相应类别。
Flattening operation
现在你知道了卷积神经网络的所有关键步骤,如果你想更深入地研究卷积神经网络,你可以阅读下面的段落。
卷积的高级方法
在前面的描述中,据说卷积是将滑动矩阵(内核或滤波器)与输入矩阵图像相乘。虽然这种解释在深度学习社区中广泛存在,但实际的解释略有不同,但并没有复杂多少。让我们以我们的第一个卷积(漂亮的 gif)为例,它有一个 3x3 内核和一个 6x6px 矩阵。我们使用上面的公式来预测特征图的大小,4x4px。
Receptive fields of neurons
特征图左上角位置的像素值直接取决于输入图像中的像素值和卷积核的值。该像素的值根据卷积算法,
Feature map pixel value
其中 wi 是卷积核的系数, xi 是绿框中矩阵的系数。让我们提醒一下卷积核,
Convolution kernel
上面,我们有例如 w1 = w2 = w5 = 2 和 w9 = 1,还有 x1 = 0,x2 = 1,x5 = 1。注意像素值表达式中的加权和。这就好像我们有一个神经元,其中 xi 是输入,细胞核的 wi 系数是输入的权重。神经元计算加权和,然后是特征图中像素的值,这里是 5。被框住的区域被称为神经元的感受野;左上角神经元感受野上方的绿色部分。
当内核在卷积过程中在输入图像上移动时, xi 的值发生变化,但内核的权重和的值保持不变。然后,通过梯度反向传播来更新它们。特别地,所有这些神经元共享相同的权重和,这些权重是卷积核的系数,因为它们针对相同的特征(例如眼睛或轮廓的存在)查看输入图像。我们还可以给那些神经元加上一个共享偏置 b 。前面提到的激活函数实际上应用于那些神经元。
可以看出,第二个神经元的感受野与第一个神经元的感受野部分重叠,依此类推。由于这些神经元的感受野相互重叠,如果想要的特征被*移——向上、向下、向左或向右——它必然会在另一个神经元的感受野中,从而被这个神经元检测到。我们说我们通过*移得到了不变性。在不太复杂的情况下,20 世纪 60 年代进行的生物学工作使科学家能够识别一些动物视觉皮层中的相同结构。特别是,视觉过程中涉及的第一批细胞将识别非常简单的几何形状:线、圆、点等。然后,更先进的细胞将使用这些信息来识别一个复杂的模式。类似地,在卷积神经网络中,第一卷积层将检测一般的几何形状:角、圆、斑点、轮廓等。接下来的图层将这些元素结合起来,以识别更具体的形状:头骨、眼睛、耳朵等。
再次从上面的公式开始,我们知道使用 pxp 滤波器对大小为 nxn 的图像进行卷积,输出——没有填充——大小为 mxm 的特征图;已知特征图的每个像素与一个神经元相关联,然后我们使用 m ** 2 个神经元,每个神经元观察大小为 pxp 的场,具有 p ** 2 个权重(每个滤波器系数一个)和一个偏差。由于这些参数是共享的,我们最终得到了 m ** 2 神经元的 p ** 2 + 1 参数。
例如,对于大小为 420x420px 灰度的输入图像和大小为 5 * 5 的内核,我们将得到大小为 m = 420–5+1 = 416 的特征图,因此一个卷积需要 416 * 416 = 173056 个神经元!仅用 26(5*5 + 1)个参数来学习。
这是卷积神经网络的兴趣点。为了执行卷积,换句话说,为了检测模式,神经元共享相同的突触权重和可能的偏差,这大大减少了要学习的参数数量。
结论
本文的目的是介绍卷积神经网络及其主要兴趣。一般来说,这些网络为分类和识别任务提供了极好的结果。它们也用于解释声音、文本和视频数据。如果要解决的问题是在序列中寻找模式,那么卷积网络将是很好的候选。在以后的文章中,我们将详细研究卷积网络的连续层如何在训练阶段演变,我们还将了解如何使用热图让这些网络说话。
蒙特卡罗模拟中 Copula 的引入
原文:https://towardsdatascience.com/introducing-copula-in-monte-carlo-simulation-9ed1fe9f905?source=collection_archive---------9-----------------------
概率油气体积估算的一个演示案例
Source
在石油和天然气行业,从地表到地下,不确定性无处不在。为了在任何估计中嵌入不确定性,需要概率方法。
一个简单的例子是体积估计。估算碳氢化合物(石油/天然气)初始地质储量(HCIIP)的公式如下:
Source
为了对 HCIIP 进行概率估计,使用了蒙特卡罗方法,并遵循以下步骤(来源):
- 定义可能输入的域
- 根据域上的概率分布随机生成输入
- 对输入执行确定性计算
- 汇总结果
概率油气远景评价的一个 Ms Excel 实现可以在这里得到。
如果所有输入都是 独立 随机变量或者 正态分布 ,那么随机抽样就相当简单了。然而,输入,例如孔隙度和碳氢化合物饱和度在某种程度上与 相关,并具有不同的分布。在这种情况下,随机抽样是困难的。这时 系词 来拯救我们了。
介体
根据维基百科,一个 copula 是一个多元的累积分布函数,对于这个函数,每个变量的边际概率分布是均匀的。
上面的定义很抽象,很难理解。然而,实现相当容易。托马斯·威奇写了一篇鼓舞人心的文章,直观地展示了系词。
为了完全掌握 copula 的概念,需要理解随机变量变换。
随机变量变换
让我们从 0 和 1 之间的均匀分布开始采样。
x = stats.uniform(0, 1).rvs(10000)
Uniformly distributed samples
这些样本不是均匀的,而是可以通过累积密度函数(CDF)的倒数转换成任何感兴趣的概率分布。假设我们希望这些样本呈正态分布。我们可以将这些样本传递给正态分布的逆 CDF 函数(例如 ppf 函数在 scipy.stats 中)。我们将得到以下正态分布的样本。
norm **=** stats**.**distributions**.**norm()
x_trans **=** norm**.**ppf(x)
Transformed samples that are normally distributed
如果我们在同一图上绘制均匀样本、变换样本和反向 CDF 曲线,我们得到:
Overlaying uniform and transform (normally distributed) sample along with the CDF curve
当我们想从给定的分布中抽取样本时,计算机会在幕后进行这种转换。
重要的是,这个过程是可逆的;这意味着我们可以通过相同的 CDF 将任何分布的样本转换回统一的分布。
高斯连接函数-添加变量相关性
高斯连接函数的步骤如下:
- 从相关的多元正态分布中抽取样本。变量相关性通过协方差矩阵指定。
- 转换相关样本,使边缘(每个输入)一致。
- 将统一边际转换为任何利益分布。例如,孔隙度服从截尾正态分布,碳氢化合物饱和度服从三角形分布等。
让我们从相关多元正态分布中抽取样本开始。
mvnorm = stats.multivariate_normal([0, 0], [[1., 0.5], [0.5, 1.]])
x = mvnorm.rvs((10000,))
Correlated samples from a multivariate normal distribution with a covariance of 0.5
接下来,我们将边缘转换为均匀分布。
norm = stats.norm([0],[1])
x_unif = norm.cdf(x)
The joint & marginal distributions of X1 and X2
如我们所见,X1 和 X2 的联合分布是相关的,而它们的边际是一致的。
现在,我们可以在保持相关性的同时,将边际转化为任何感兴趣的分布。例如,我们想从三角形分布中得出 X1,从正态分布中得出 X2。
x1_tri = stats.triang.ppf(x_unif[:, 0], c=0.158 , loc=36, scale=21)
x2_norm =stats.norm(525, 112).ppf(x_unif[:, 1])
The transformed marginal of X1
The transformed marginal of X2
The joint distribution of X1 and X2
现在我们从不同的分布中得到 X1 和 X2 的期望的联合分布。
HCIIP 的概率估计
有了 copula ,我们已经准备好将变量相关性引入蒙特卡罗的采样阶段。以下是计算 OIIP 的完整 python 代码:
import seaborn as sns
from scipy import stats
import numpy as np
import matplotlib.pyplot as plt
# HCIIP = GRV*NTG*POR*SHC/FVF
means = [0.]*5
cov = [[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]]mvnorm_std = stats.multivariate_normal(means,cov)
x = mvnorm_std.rvs(10000,random_state=42)
norm_std = stats.norm()
x_unif = norm_std.cdf(x)#create individual distr.
grv = stats.triang(c=0.1 , loc=10000, scale=300).ppf(x_unif[:, 0])
ntg = stats.triang(c=0.2 , loc=0.5, scale=0.5).ppf(x_unif[:, 1])
phi = stats.truncnorm(-2*1.96,1.96,0.2,0.05).ppf(x_unif[:, 2])
shc = stats.norm(0.6,0.05).ppf(x_unif[:, 3])
fvf= stats.truncnorm(-1.96,2*1.96,1.3,0.1).ppf(x_unif[:, 4])stoiip = 7758*grv*ntg*phi*shc/fvf/1e6
sns.distplot(stoiip , kde=False, norm_hist=True)
plt.figure()
sns.distplot(stoiip ,hist_kws=dict(cumulative=True),
kde_kws=dict(cumulative=True))
plt.show()
无变量相关情况
对于没有相关性的情况,协方差矩阵是一个对角矩阵(除了对角单元之外,处处为零)。
cov = [[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 1., 0.],
[0., 0., 0., 0., 1.]]
运行上面的代码,我们得到下面的 OIIP 直方图和累积概率分布。
Histogram of OIIP for no correlation case
Cumulative distribution of OIIP for no correlation case
可变相关情况
为了说明可变相关性的情况,我们任意指定 NTG、POR 和 SHC 之间的正相关性。
cov = [[1., 0., 0., 0., 0.],
[0., 1., 0.7, 0.6, 0.],
[0., 0.7, 1., 0.8, 0.],
[0., 0.6, 0.8, 1., 0.],
[0., 0., 0., 0., 1.]]
Histogram of OIIP for correlation case
Cumulative distribution of OIIP for correlation case
总结
通过观察 OIIP 直方图和累积分布,我们可以看到,包括变量相关性或依赖性扩展了计算 OIIP 的 P10-P90 范围。这是合理的,因为通过包括相关性,采样可以探索极端空间,否则,在没有相关性的情况下可能会被错过。在下一篇文章中,我们将看看贝叶斯下降曲线分析(DCA)。
介绍深层 Java 库(DJL)
原文:https://towardsdatascience.com/introducing-deep-java-library-djl-9de98de8c6ca?source=collection_archive---------11-----------------------
用 Java 构建和部署深度学习模型
我们很高兴地宣布深度 Java 库(DJL) ,这是一个开源库,使用直观的高级 API 来开发、训练和运行 Java 深度学习模型。如果你是一个对学习深度学习感兴趣的 Java 用户,DJL 是一个开始学习的好方法。如果你是一名使用深度学习模型的 Java 开发人员,DJL 将简化你训练和运行预测的方式。在这篇文章中,我们将展示如何在几分钟内用预训练的深度学习模型进行预测。
代表团
在开始编码之前,我们想分享一下我们构建这个库的动机。在调查深度学习领域时,我们发现 Python 用户有丰富的资源。比如数据分析的 NumPy 可视化的 MatplotlibMXNet、PyTorch、TensorFlow 等等框架。但是面向 Java 用户的资源非常少,尽管它是企业中最受欢迎的语言。我们的目标是为数百万 Java 用户提供开源工具,用他们已经熟悉的语言来训练和服务深度学习模型。
DJL 是在现有深度学习框架之上,用原生 Java 概念构建的。它为用户提供了深度学习方面的最新创新,以及使用尖端硬件的能力。简单的 API 抽象出了开发深度学习模型所涉及的复杂性,使它们易于学习和应用。通过 model-zoo 中捆绑的一组预训练模型,用户可以立即开始将深度学习集成到他们的 Java 应用程序中。
- Other frameworks currently not supported.
DJL 的例子
深度学习正在渗透到企业的各种用例中。在零售业,它被用来预测客户需求,分析客户与聊天机器人的互动。在汽车行业,它用于导航自动驾驶汽车,并发现制造过程中的质量缺陷。在体育行业,实时教练和训练洞察正在改变比赛的方式。想象一下,能够使用深度学习模型来模拟对手的移动或确定如何定位您的团队。在这篇文章中,你可以了解西雅图海鹰队如何使用深度学习来告知游戏策略并加速决策。
在本帖中,我们分享了一个让我们队的足球迷们产生共鸣的例子。我们演示了一个异议检测模型,该模型使用来自 DJL 模型动物园的预训练单镜头检测器模型从图像中识别球员。您可以在 Linux 和 macOS 中运行这个示例。
要在应用程序项目中使用 DJL,用 IntelliJ IDEA 创建一个 gradle 项目并将以下内容添加到您的 build.gradle 配置中。
注意:MXNet 的运行时依赖对于 Linux 和 macOS 环境是不同的。参考 GitHub 文档 。
我们用这个足球图像进行检测。
Source: Offered under Apache-2.0 license on Gluon-CV
我们使用下面共享的代码块运行预测。这段代码从 model-zoo 加载一个 SSD 模型,从该模型创建一个Predictor
,并使用predict
函数来识别图像中的对象。然后,辅助工具函数在检测到的对象周围布置边界框。
这段代码识别图像中的三名球员,并将结果作为 ssd.png 保存在工作目录中。
该代码和库可以很容易地修改,以测试和运行 model-zoo 中的其他模型。但乐趣不止于此!你可以使用问题回答模型来训练你自己的文本助手,或者使用图像分类模型来识别杂货店货架上的物品等等。请访问我们的 Github repo 获取更多示例。
了解更多并做出贡献
在这篇文章中,我们介绍了 DJL,这是我们为 Java 用户提供最新、最棒的深度学习开发体验的一份微薄之力。我们用预先训练好的模型演示了 DJL 如何在几分钟内从图像中检测出物体。我们在 DJL GitHub 资源库上提供了更多示例和附加文档。
我们欢迎社区参与我们的旅程。前往我们的 Github 仓库并加入我们的 slack 频道开始吧。让我们开始酝酿吧!☕️
引入 flythub——可扩展的开源“点击式”人工智能。
原文:https://towardsdatascience.com/introducing-flytehub-open-source-click-button-ai-that-scales-ffaeb7ebae44?source=collection_archive---------35-----------------------
好得难以置信?
执行机器学习(尤其是大规模)涉及大量的协调和无数的技术。直到最*,这还需要建立针对特定机器学习任务的定制环境。然而,最*的技术进步已经使得创建复杂的机器学习工作流成为可能,这些工作流可以移植到新的环境中,并且只需点击一个按钮就可以运行。
FlyteHub 是一个新的开源机器学习工作流的免费公共注册表。使用 FlyteHub,您可以点击运行任何开源工作流,并大规模执行强大的机器学习,而无需编写任何代码。由于这些工作流是可移植的,它们可以在您的笔记本电脑上运行,或者跨 1000 台机器的集群运行。
想象以下场景:
- 数据科学家编写工作流来执行图像识别。
- 数据科学家意识到其他人可能会从他们的工作中受益,并将工作流上传到 FlyteHub。
- 由于 flythub 工作流是可移植的,任何安装了 flythub 的人都可以点击导入这个开源工作流,执行图像识别,而无需编写任何代码,也无需安装任何额外的包。
- 这些用户可以对项目做出贡献,为每个人改进工作流程。
事实上,FlyteHub 已经有了图像识别的开源工作流。您可以在 5 分钟内运行它们,而无需编写任何代码,甚至可以训练您自己的模型来识别自定义对象。
FlyteHub 现在之所以成为可能,是因为几个行业的进步,包括几周前在 KubeCon 推出的“Flyte”。现在就试试flythehub吧,或者继续阅读,了解今天使开源工作流成为可能的进步的时间表。
在这个过程中,我们将展示如何使用开源工作流来搜寻和捕获难以捉摸的大脚野人(更好地称为“大脚怪”)。
- the target (not to scale)
类似的工作流程可以用于发现“拉撒路物种”(像大村鲸鱼这样的生物,曾经被认为已经灭绝),或者追踪超稀有的西伯利亚虎,其数量被认为低于 5000 只。
让我们回到 2013 年。
来自 BFRO(大脚野外研究者组织)的数据显示,西雅图郊外的金县出现了多次大脚野人。我们在瞄准点附*的树林里安装了摄像头,每隔几秒钟就会自动拍摄一张照片。
我们没有时间看所有的照片。幸运的是,我们有一位数据科学家,他写了一些 Python 代码,他称之为“大脚探测器”。该代码使用计算机视觉扫描每张照片,并告诉我们它是否包含大脚怪。
我们希望与加利福尼亚的一个团队共享此代码,这样他们也可以使用它。现在是 12 月,报告显示这种生物可能正在向南迁徙。
在 2013 年之前,用户需要在他们的计算机上手动安装所有必要的要求,然后才能使用该代码。
要运行我们的 Python 任务,加州团队必须安装正确版本的 Python,以及所有必需的库。如果任务需要不同的技术,比如 Apache Spark,他们需要确保 Java 和 Spark 已经安装,并且配置正确。
用这种方式创建可移植的“点击式”人工智能是非常困难的,因为每个任务都有一套独特的需求。不同的人工智能任务甚至可能需要同一个库的不同版本。即使对于经验丰富的工程师来说,这也是一种令人沮丧的体验,通常被称为“依赖地狱”。
加州团队没有工程师,我们不想让他们经历依赖地狱。我们需要尽可能多的帮助。世界上的任何人都应该只需点击一个按钮就可以提交他们的照片,并加入追捕大脚怪的行列。
2013:容器彻底改变了我们共享代码的方式
“容器”就像一段代码,捆绑了所有必要的需求。例如,我们的容器可以包含 Python 3.6 版,以及完成我们的大脚探测器任务所需的所有 Python 包。
容器在隔离的环境中运行。如果您在笔记本电脑上启动大脚怪检测器容器,该容器将使用 Python 3.6 运行,即使您的笔记本电脑安装了 Python 2,或者根本没有安装 Python。
当您运行开源 FlyteHub 工作流时,所有代码都在容器内运行。这确保了代码可以在所有环境中可靠地运行。
解决了?没那么快。
某些人工智能任务可能需要很长时间来运行(尤其是在大规模的情况下)。
当我们取回相机时,我们将拥有一百万张照片。如果 AI 代码处理每张图像需要 10 秒,那么计算机完成所有 100 万张图像需要 115 天。
我知道你在想什么:“115 天?!野兽可能在去墨西哥的半路上!”
我们需要更快的反馈。
为了加速这个过程,我们可以使用 100 台计算机,在它们之间分配图像。如果每台机器处理 10000 张图像,1 天就可以完成全部 100 万张照片。
由于代码被打包到一个容器中,您不需要担心在所有这些计算机上安装任何要求,但是,您仍然需要指示 100 台计算机中的每一台运行 Bigfoot 检测器容器。
我们可以编写循环 100 次的代码,告诉每台机器运行容器。但是,如果代码假设正好有 100 台机器,那么代码是不可移植的。
为了让这项人工智能任务具有可移植性,我们的团队应该能够在一天内在 100 台计算机上执行这项任务。加州团队(他们没有 100 台计算机)应该能够在一台笔记本电脑上执行相同的任务,并在 115 天内处理图像。换句话说,代码不需要理解它运行的基础设施。
2015 年:推出 Kubernetes
Kubernetes 是一个在计算机“集群”上启动容器的*台。您的集群可能只有一台机器(您的笔记本电脑),或者 1000 台机器。
当您指示 Kubernetes 启动 100 个容器时,Kubernetes 会尽快将它们安排在您的机器集群上。
Kubernetes 跟踪有多少机器资源可用。如果您的集群只够同时运行 50 个容器,Kubernetes 将立即启动前 50 个容器。一旦其中一个容器运行完毕,Kubernetes 将检测到现在还有空闲空间,并启动第 51 个容器。随着更多容器的完成,Kubernetes 将继续推出新的容器,直到所有容器完成。
如果您只有足够的资源一次启动一个容器,大脚怪探测器工作流程将需要 115 天才能运行,但它最终会完成。
FlyteHub 开源 AI 运行在 Kubernetes 上。Kubernetes 集群可以小到像笔记本电脑这样的单台机器,也可以是 AWS 中的大型集群。Kubernetes 确保工作流在任一场景下都能成功运行。
解决了?没那么快。
一旦所有这些大脚探测器容器完成,我们有一百万个输出(每个图像一个输出)。我们需要把这些结果结合成有用的东西。
为了解决这个问题,我们可以创建另一个容器来组合来自每个图像处理容器的结果,并寻找积极的结果。
问题是,订购对这个容器很重要。
与可以同时运行的大脚探测器容器不同,我们需要等到所有大脚探测器任务完成之后,才能启动最后一个容器。
这不是容器排序很重要的唯一场景。在运行图像处理之前,我们应该将照片分成小批,以便我们可以为每批照片启动一个大脚探测器容器。我们的逻辑流程如下所示:
- 第一步:将照片分成小批。
- 步骤 2:为每批照片启动大脚探测器容器。
- 第三步:结合第二步的结果,并检查任何积极的结果。
(all steps run inside containers)
数据科学过程倾向于采取类似于这样的“任务”的“工作流”的形式。这些工作流程可能会变得非常复杂。工作流中的任务可能包括数据收集、数据预处理、特征提取、模型训练、模型评估等等。
一些任务(如大脚探测器)可以并行运行。其他任务(如“检查阳性”任务)需要等待前面的任务完成后才能启动。
由于 Kubernetes 对我们的排序逻辑一无所知,它不知道要等待一些任务完成后再开始其他任务。
我们需要一个理解我们工作流程逻辑的“工作流程经理”。“工作流管理器”需要在工作流运行时照看它。当前面的所有步骤都完成后,它应该只在 Kubernetes 中启动容器。为了完成我们的工作流,工作流管理器需要做这样的事情:
- 告诉 Kubernetes 启动“分割照片”任务。
- 等待任务完成。
- 告诉 Kubernetes 为每批启动“大脚探测器”任务。
- 等待所有大脚探测器任务完成。
- 告诉 Kubernetes 启动最后一个任务来检查积极的结果。
- 存储结果,并显示给用户。
- 用户捕获大脚怪,并与马戏团环游世界。
2019: Lyft 推出 Flyte
Flyte 是使工作流可移植所需的拼图中缺失的一块。
Flyte 引入的一个关键概念是“工作流规范”。工作流规范提供了一种健壮的方式来表达工作流中的逻辑流。
Flyte 中的所有工作流都必须符合该规范。Flyte 可以阅读这些工作流,理解任务的排序,并以正确的顺序在 Kubernetes 上启动它们。
Flyte 不仅理解排序,还理解工作流中的数据流。通常,一个任务的输出成为下一个任务的输入。从工作流规范中,Flyte 明白这一点。
Flyte 确保一个任务的输出可用于下一个任务,即使这些任务运行在完全独立的计算机上。不管我们是在 1 台笔记本电脑上运行大脚怪检测器,还是在 1000 台机器上运行,这些图像识别任务的输出都可以用于“检查阳性”任务。
当我们将工作流上传到 flythehub 时,flythehub 会存储工作流规范。任何大脚猎人都可以导入工作流,提交他们的照片,并获得结果,而不需要了解它如何工作的任何细节。
事实上,该工作流程最*被蒙大拿州的一名家庭研究员用于制作以下照片:
看着这张照片,很明显这种类型的头发只能来自于…神话本人。
结论
今天的帖子只是触及了这些技术所释放的可能性的表面。在后续文章中,我将进一步描述 Flyte 工作流规范,并展示开发人员如何通过将任务组合成超级工作流来利用彼此的工作。
试试 FlyteHub 吧。我希望通过在开源工作流程上的合作,我们可以创造出更好的产品。
敬请关注更新。
介绍谷歌番石榴
原文:https://towardsdatascience.com/introducing-google-guava-f295d22319f7?source=collection_archive---------5-----------------------
Guava 是一个开源的 Java“收藏库”库,由 Google 开发。
它提供了使用 Java 集合的实用程序。当您深入研究 Guava 时,您会注意到它是如何通过使代码简洁易读来减少编码错误、促进标准编码实践和提高生产率的。
我决定把番石榴教程分解成一系列的帖子。我们将涵盖许多 Guava 概念——Guava 实用程序类,函数式编程,使用集合,以及事件总线。
在这篇文章中,你将了解到:
1。 给你的 Java 项目添加番石榴。
2。Guava 中的基本实用程序—拆分器、地图拆分器、连接程序、地图连接程序和预处理类
1.将番石榴添加到项目中
番石榴有两种口味
- 一个用于 Java 8+ JavaRuntimeEnvironment。
- 另一个用于 Java 7 或 Android *台。
如果您使用的是 Maven,将下面的代码片段添加到 <依赖关系>…</依赖关系> 部分
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>**version**</version>
</dependency>
如果你正在使用 Gradle,添加maven central()到资源库
*repositories {
mavenCentral()
}*
然后将下面的代码片段添加到 build.gradle 文件的依赖项部分。
*dependencies {
compile group:'com.google.guava’, name:'guava', version:**version**
}*
查看链接了解更多版本信息。
对于不使用任何项目管理工具(如 Maven 或 Gradle)的人来说—
- 从 这里 下载一罐谷歌番石榴。
- 如果使用 IDE,将 JAR 文件作为外部库添加。
- 如果您使用文本编辑器,将 JAR 文件添加到您的类路径中。
2.基本的番石榴公用事业
2.1 Joiner 类
它接受任意字符串,并用一些定界符将它们连接在一起。通过为每个元素调用 Object.toString() 来构建结果。
通常你会这样做
*public String concatenateStringsWithDelimiter(List<String> strList, String delimiter) {
StringBuilder builder = new StringBuilder();
for (String str: strList)
if (str != null)
builder.append(str).append(delimiter);
// To remove the delimiter from the end
builder.setLength(builder.length() - delimiter.length());
return builder.toString();
}*
但是在 Joiner 类的帮助下,等价于上面的代码可以写成
*Joiner.on(delimiter).skipNulls().join(strList);*
如你所见,代码变得简洁且易于维护。同样,用番石榴找虫子也相对容易。现在,如果你想添加一个空字符串的替换,该怎么办呢?嗯,Joiner 类也处理这种情况。
*Joiner.on(delimiter).useForNull(replacement).join(strList);*
你可能会想,也许 Joiner 类仅限于处理字符串,但事实并非如此。因为它是作为泛型类实现的,所以也可以传递任何对象的数组、iterable 或 varargs。
Joiner 类一旦创建就不可改变。因此,它是线程安全的,可以用作静态最终变量。
*public static final Joiner jnr = Joiner.on(delimiter).skipNulls();
String result = jnr.append(strList);*
2.2 接合工。MapJoiner 类
它与 Joiner 类的工作方式相同,唯一的区别是它用指定的键-值分隔符将给定的字符串连接成键-值对。
*public void DemoMapJoiner() {
// Initialising Guava LinkedHashMap Collection
Map<String, String> myMap = Maps.newLinkedHashMap();
myMap.put(“India”, “Hockey”);
myMap.put(“England”, “Cricket”);
String delimiter = “#”;
String separator = “=”;
String result = Joiner.on(delimiter).withKeyValueSeperator(separator).join(myMap);
String expected = “India=Hocket#England=Cricket”;
assertThat(result, expected);
}*
2.3 Splitter 类
Splitter 类的作用与 Joiner 类相反。它接受一个带分隔符的字符串(一个字符、一个字符串或者甚至是一个正则表达式模式),并在分隔符上分割该字符串,然后获得一个部分数组。
通常你会这样做
*String test = “alpha,beta,gamma,,delta,,”;
String[] parts = test.split(“,”);
// parts = {“alpha”, “beta”, “gamma”, “”, “delta”, “”};*
你能注意到这个问题吗?你不希望空字符串成为我的结果的一部分。所以,split()方法还有待改进。
但是在 Splitter 类的帮助下,与上面等价的代码可以写成
*Splitter splitter = Splitter.on(“,”);
String[] parts = splitter.split(test);*
split() 方法返回一个 iterable 对象,该对象包含测试字符串中的各个字符串部分。 trimResults() 方法可用于删除结果中的前导和尾随空格。
就像 Joiner 类一样,Splitter 类一旦创建也是不可变的。因此,它是线程安全的,可以用作静态最终变量。
2.4 MapSplitter 类
Splitter 类伴随着 MapSplitter。它接受一个字符串,该字符串中的键值对由某种分隔符(一个字符、一个字符串甚至是一个正则表达式模式)分隔,并以与原始字符串相同的顺序返回带有键值对的 Map 实例。
*public void DemoMapSplitter() {
String test = “India=Hocket#England=Cricket”;
// Initialising Guava LinkedHashMap Collection
Map<String, String> myTestMap = Maps.newLinkedHashMap();
myMap.put(“India”, “Hockey”);
myMap.put(“England”, “Cricket”);
String delimiter = “#”;
String seperator = “=”;
Splitter.MapSplitter mapSplitter = Splitter.on(delimiter).withKeyValueSeperator(seperator);
Map<String, String> myExpectedMap = mapSplitter.split(test);
assertThat(myTestMap, myExpectedMap);
}*
2.5 前置条件类
前置条件类提供了静态方法的集合来检查我们代码的状态。前提条件很重要,因为它们保证成功代码的期望得到满足。
比如:
1。检查空条件。你可以一直写
*if (testObj == null)
throw new IllegalArgumentException(“testObj is null”);*
使用前置条件类使它更加简洁易用
*checkNotNull(testObj, “testObj is null”);*
2.检查有效参数。
*public void demoPrecondition {
private int age;
public demoPrecondition(int age) {
checkArgument(age > 0, “Invalid Age”);
this.age = age;
}
}*
checkArgument(exp,msg)计算作为参数传递给方法的变量的状态。它计算一个布尔表达式 exp,如果表达式计算结果为 false,则抛出 IllegalArgumentException。
3.检查对象的状态
*public void demoPrecondition {
private String name;
public demoPrecondition(String name) {
this.name = checkNotNull(name, “Anonamous”);
}
public void Capitalize() {
checkState(validate(), “Empty Name”);
}
private bool validate() { this.name.length() > 0; }
}*
checkState(exp,msg)计算对象的状态,而不是传递给方法的参数。它计算一个布尔表达式 exp,如果表达式计算结果为 false,则抛出 IllegalArgumentException。
4.检查有效的元素索引
*public void demoPrecondition {
int size;
private int [] price;
public demoPrecondition(int size) {
this.size = checkArgument(size > 0, “size must be greater than 0”);
this.price = new int[this.size];
}
public void updateItem(int index, int value) {
int indexToBeUpdated = checkElementIndex(index, this.size, “Illegal Index Access”);
}
}*
谢谢你的阅读。在下一篇文章中,我们将讨论 Guava 中的函数式编程。
引入 Hoeffding 不等式生成无存储决策树
原文:https://towardsdatascience.com/introducing-hoeffdings-inequality-for-creating-storage-less-decision-trees-b5135e65e51e?source=collection_archive---------15-----------------------
探索 Hoeffding 不等式陈述了什么,以及如何使用它来创建一类特殊的不使用存储的决策树:Hoeffding 树。
© by my lovely wife Tinati Kübler
任务
我想象你有一个巨大的带标签的数据集,你想为一个预测任务建立一个模型。例如,这可以是 Twitter,在那里你有比你可以计算的包括相应的喜欢(标签)数量更多的推文(功能)。现在你想要建立一个模型,可以预测一条推文是否会被喜欢超过 100 次,对去年写的所有推文进行训练,也就是说,我们想要解决一个分类任务。标签为 1 意味着该推文有超过 100 个赞,否则为 0。
Photo by Sara Kurfeß on Unsplash
你决定使用决策树,甚至是从它衍生出来的智能工具,比如随机森林或梯度推进。但是决策树、基于决策树的模型、甚至其他模型都有以下缺点:
您需要在内存中随时可用的训练数据。
问题是
在最好的情况下,完整的训练数据可以放入本地机器的内存中。但是,您意识到 tweets 数据集大于 8–32GB,所以您运气不好。也许您可以访问具有 512 GB RAM 的集群,但这也不够大。
数据集实际上有多大?让我们做一个粗略的估计。推特本身和其他几个来源(这里是这里是和这里是)报告称,每秒大约有 6000 条推文。这意味着每年大约有 6000 * 60 * 24 * 365 =189,216,000,000推文。让我们假设每条 tweet 的大小为 140 字节,每个字节对应于单词包编码中的一个字符。我们忽略了每条 tweet 可能附带了一些元数据,我们也可以使用二元模型、三元模型等。这是一个巨大的 140 *189,216,000,000/10⁹=26,490 GB 的推文数据!
因此,使用 RAM 不是一个选项。即使你碰巧拥有一个足够容纳整个数据集的硬盘,从其中读取数据也会使训练非常缓慢,正如你在这里看到的(图 3) 。
嗯,怎么办呢?
解决方案
来自华盛顿大学计算机科学与工程系的 Pedro Domingos 和 Geoff Hulten 介绍了决策树的一种变体,称为Hoeffding Trees【1】,可以用于流方式。这意味着我们只需解析一次大的训练数据集,并在此过程中构建树。
我们甚至不必存储所使用的样本:我们可以直接从 Twitter(或任何大型数据库)中获取它们,通过增加一些计数器来处理它们,然后再次忘记它们。为什么这是可能的可以用赫夫丁不等式来解释,这就是赫夫丁树的名字。
高层次的想法是,我们不必查看所有的样本,而只需查看决策树算法中每个分裂点的足够大的随机子集。这个子集有多大是下一节的主题。
我写这篇文章是因为 Domingos 和 Hulten 的论文非常专业(因此也非常精确),我想提出一个高级的、易于理解的观点来解释作者的方法为什么有效。
此外,如果您不想在接下来的部分中处理数学问题,至少可以看看最后一部分的一些代码!在那里,我使用 scikit-multiflow 软件包来使用 Hoeffding 树。
赫夫丁不等式
让我们研究一下霍夫丁不等式的内容,以及如何利用它来解决存储问题。
介绍
芬兰统计学家、非参数统计的创始人之一瓦西里·赫夫丁(基于赫尔曼·切诺夫的思想)发现了一个不等式[2],量化了以下陈述:
有界随机变量的和(也是均值)紧紧围绕其期望值。
以一枚公*的硬币(看到正面的概率= 0.5)为例,我们掷 1000 次。定义随机变量 X₁,…,X₁₀₀₀ 用
那么人头的数量——让我们称之为x——正好是 Xᵢ 的总和。我们已经知道,从那以后我们可以预期 500 次人头
The expectation of the Xᵢ’s is the probability of them being equal to 1, which is 0.5 in our case. Furthermore, the expected value is linear, justifying the first equation.
现在赫夫丁不等式把我们覆盖了:我们也知道 X 大概率不会偏离500太多,见下图。我们一会儿就知道“多”和“概率大”是什么意思了。
You can see how concentrated the probability mass is around 500. The probability of seeing exactly 500 times heads is about 0.025.
简化的定理
设 X₁,…,Xₙ是独立的伯努利随机变量,即它们中的每一个都取值 0 或 1。设 X = X₁ + … + Xₙ是他们的和。然后
Hoeffding’s Inequality for sums.
注意:一个更一般的公式成立,其中 Xᵢ 可以在任意实数 a 和 b 之间有界,甚至不必随机独立。但是我们使用这里给出的版本。
直觉上,这个不等式是有意义的:t变得越大,也就是说,我们允许误差变得越大,落在区间或长度 2 t 内的概率就越大。
但是真正有趣的事情是这样的:等式的右边只包括随机变量的数量 n 和允许误差 t. 最重要的事情,Xᵢ等于 1 的概率,在不等式的右边是找不到的。概率对我们来说可以是已知的,也可以是未知的,对所有人来说都是一样的,这并不重要。这就是为什么这种不*等如此多才多艺,如此适合研究。
具有这种性质的其他不等式是更容易的马尔科夫不等式和切比雪夫不等式,但是它们给我们的右边的下界要差得多。*心而论,这两个不等式不需要我们的随机变量有界。然而,赫夫丁不等式利用了这样一个事实:Xᵢ在 0 和 1 之间有界。
取该不等式,用 nt、代替 t ,并将 P(…)内的不等式除以 n 得到*均值的 Hoeffding 不等式:
Hoeffding’s Inequality for the mean.
在哪里
应用程序
现在让我们来看看不*等在起作用。首先,我们将谈论一个非常基本的硬币例子。然后,我们会去第二个非常重要的例子,估计股份,我们需要了解为什么赫夫丁树工作。
回到硬币的例子(总和)
假设我们要计算得到小于等于 450 或者大于等于 550 人头的概率。由于𝔼( X ) = 500,我们可以设置 t =50,最后得到
这意味着偏离期望值小于 50 的概率非常高。头数极度集中在 500 左右。
估计份额(*均值)
假设有一大池 N 个球,其中未知份额 p 为白色,其余为黑色。一个自然的问题可能是:白球的份额 p 有多大?如果池大小 N 足够大(想想几十亿),捡起每个球并检查它不是一个选项。
当然,自然要做的事情是均匀地抽取几个样本——比如说有替换的 n — 球,然后检查它们。如果其中的 w 是白色的,我们就可以断定 p ≈ w/n 。但是我们的子样本应该有多大呢?什么尺寸适合 n ?10 可以吗?100?1000?
嗯,这取决于与 p 的偏差有多大,以及在这个偏差范围内,你需要多大的信心。您可以设置两个参数:
- 误差的上界在 p,让我们再把它叫做 t
- 在以长度为 2 的 p 为中心的区间内概率的一个下界姑且称之为 1- ɛ 对于小的 ɛ > 0 。
这意味着 t 和ɛ是固定的,我们想找到 n 个例子,这样至少在概率为 1-ɛ的情况下,分数 w/n 与 p 的差异不超过 t
我们现在要正式确定这件事。让我们定义 n 个随机变量 X₁,…,Xₙ 为
由于我们随机抽取有替换的球, Xᵢ 为 1 的概率正好是 p ,未知份额。这也正是 Xᵢ.的期望值
让 X̅=w/n 再次成为这些伯努利变量的*均值。然后我们还有
赫夫丁不等式给了我们
现在我们希望右手边大于 1- ɛ,,这给我们一个关于 X̅=w/n 偏离 p 不超过 t 的下限,其概率至少为1- ɛ.因此,我们必须解决这个不等式
对于 n 。使用一些基本运算,我们得到
如果我们容忍概率至少为 99%的 p 的绝对误差至多为 1%,我们必须将 t =0.01,将 ɛ= 设为 0.01,这样我们得到的所需子样本大小至少为
让我们用 Python 来试试吧。我们考虑 30,000,000 个球的池,其中 10,000,000 个球是白色的(标记为 1),20,000,000 个球是黑色的(标记为 0)。所以白球的真实份额是 0.3333……我们假装不知道。
import numpy as npnp.random.seed(0)# Create a pool with 30 million entries, 10 million being a one (white ball) and 20 million being a zero (black ball).
# This means that we have a share of 1/3=0.3333... white balls.
pool = 200000000 * [0] + 100000000 * [1]# Set Hoeffding parameters.
t = 0.01
eps = 0.01
hoeffding_amount = int(np.ceil(np.log(2 / eps) / (2 * t ** 2)))subsample = np.random.choice(pool, size=hoeffding_amount, replace=True)
print(subsample.mean())
# Result: 0.32975992752529065
看起来不错!误差只有 0.0035 < 0.01 = t 左右。但是这种情况发生的概率至少是 99%,所以我们为什么要庆祝呢?;)
注意,不是采样、保存,然后取 26,492 个样本的*均值,我们可以仅仅采样,每当我们画出一个白球(1)时增加一个计数器,然后再次忘记该样本。通过这种方式,我们只需要跟踪计数器和我们查看的球的总数,这使得这成为一种非常高效的内存算法(在我们的子样本大小中为对数 n )。
总的来说,我们可以说一个 26500 左右大小的子样本就足以高置信度地确定白球的份额。
回到机器学习
在最后一个例子中,我们已经看到了如何在一个巨大的黑白球池中计算白球的份额,而无需检查整个池,也不会有很大的误差。
我们将使用这些知识来训练决策树,而不需要在内存中有大量可用的训练数据,这是我们首先要解决的问题。
但是首先,我们必须重复一遍决策树是如何按照通常的方式构建的。
以传统方式构建决策树
在这里,我不会详细讨论决策树算法是如何工作的。在网上和媒体上有很多很棒的视频和文章。
但是,如果完整的训练数据集适合我们的内存,通常这是算法的第一步:
我们计算完整数据集的标签的杂质 I₁ 的度量,例如用于分类任务的香农熵,我们现在也将使用它。
The formula of the Shannon Entropy. p is the share of samples labeled 1. If p is 0 or 1, meaning that the samples all have the same label, the impurity is 0. The entropy function (=impurity) takes its maximum when exactly half of the samples are labeled 1 and the other half labeled 0, which corresponds to p=0.5. As you can see, the formula is symmetric, i.e. I(p)=I(1-p), which means that we can also consider the share of black balls instead of white balls.
然后,我们采用特征 f 和切割点 c. 使用这些,我们将整个数据集划分成两个不相交的子集:
- 其中特征 f 的值小于(或等于)c的所有样本
- 另一个包含所有样本,其中特征 f 的值严格大于 c.
再次测量这两组的杂质,并合并成一个加权*均值,给出两组的单个杂质测量值 I₂ 。则信息增益*计算为 G = I₁ — I₂.*
考虑以下一个拆分示例:
In this small example, we start with five samples with three features each. We start by measuring the impurity, namely I₁. Then we choose Feature 3 and a cut point of 4 to split the node. Doing this, the original five samples are distributed in the two children nodes. We measure the impurities of both nodes and combine them into a single number I₂. The Information Gain is then computed.
对所有特征和所有可能的切割点进行上述操作,选择具有最大信息增益 G 的切割点作为树中的第一个分割点。我们现在对树中的所有叶子递归地重复这一过程,直到满足某个停止标准(节点的杂质小于阈值,树已经达到最大深度,节点中的样本太少等等)。
消除内存需求
现在,我们必须使用更少的样本来模拟行为。正如我们在普通决策树中看到的:
只有标签为 1 的样品的份额 p 与计算杂质有关!
幸运的是,我们可以使用原始训练集的子样本来*似这个份额 p 和因此杂质,正如在关于赫夫丁不等式的部分中所讨论的。在球示例的语言中,带有标签 1 的标签是白球,带有标签 0 的样本是黑球。
考虑到单次分裂,我们仅使用大约 26,500 个样本就可以*似得到 I₁ 。然而,为了估计 I₂ ,我们在每个子节点中需要 **26,500。如果幸运的话,样本被*均分配到两个节点上,那么 226,500=53,000 个样本就足够了。否则,我们可能需要更多,但只要我们需要的样本少于几百万,我们就比以前更好了。即使我们需要一百万个:因为我们可以将它们流式传输到树中并跟踪一些计数器,所以我们不会遇到内存问题。***
这样我们可以安全地训练我们的模型,即使是在 Twitter 上的每条推文中。快乐大练兵!
如果你想详细了解这是如何做到的,请阅读论文[1]。作者用伪代码描述了他们的算法以及所有必要的计数器,并且他们还给出通过流式传输数据来构建多少 Hoeffding 树的证明,并且相应的正常决策树将会偏离。
结论
我们已经看到,在极大的训练集上训练决策树是不可行的。克服这个问题需要对正确数量的训练样本进行子采样,并用不完整但相当准确的信息构建树。这种二次抽样是合理的赫夫丁不等式,给这些特殊的决策树也有他们的名字:赫夫丁树。
此外,我们甚至不必存储子样本,我们只需在扫描训练数据时跟踪我们已经看到了多少标签为 1(白色球)的样本,这是一种简单有效的方法,可以进一步降低存储复杂度。
在本文中,我们只看到了用于分类任务的香草胡夫丁树。还存在用于回归的算法,甚至是对抗所谓的概念转移的方法,即当训练分布随时间变化时。**
幸运的是,这些算法都是由 Python 的 scikit-multiflow 的开发者实现的!让我们做一个快速测试。
四处玩耍
首先,做一个禁食
*pip install scikit-multiflow*
然后,让我们比较在完整的训练集上拟合 Hoeffding 树(=足够的可用 RAM)与逐个传递每个样本。更详细的测试也可以在[1]中找到。
*from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from skmultiflow.trees import HoeffdingTree
import matplotlib.pyplot as pltres = []# Create a dataset.
X, y = make_classification(10000, random_state=123)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)# Define a tree for fitting the complete dataset and one for streaming.
ht_complete = HoeffdingTree()
ht_partial = HoeffdingTree()# Fit the complete dataset.
ht_complete.fit(X_train, y_train)
ht_complete_score = ht_complete.score(X_test, y_test)
print(f'Score when fitting at once: {ht_complete_score}')# Streaming samples one after another.
timer = False
j = 0
for i in range(len(X_train)):
ht_partial.partial_fit(X_train[i].reshape(1, -1), np.array([y_train[i]]))
res.append(ht_partial.score(X_test, y_test))
print(f'Score when streaming after {i} samples: {res[-1]}')
if res[-1] >= ht_complete_score - 0.01:
print(f'(Almost) full score reached! Continue for another {20 - j} samples.')
timer = True
if timer:
j += 1
if j == 20:
break# Plot the scores after each sample.
plt.figure(figsize=(12, 6))
plt.plot([0, i], [ht_complete_score, ht_complete_score], '--', label='Hoeffding Tree built at once')
plt.plot(res, label='Incrementally built Hoeffding Tree')
plt.xlabel('Number of Samples', fontsize=15)
plt.ylabel('Accuracy', fontsize=15)
plt.title('Fitting a Hoeffding Tree at once (enough Memory available) vs fitting it via Streaming', fontsize=20)
plt.legend()*
生成的图形可能如下所示:
We can see that building a Hoeffding Tree H directly yields an accuracy of about 91% (on a test set). If we build another Hoeffding Tree by feeding in each sample one after another, we can see that the performance approaches the performance of H. After about 50 samples, our streaming Hoeffding Tree has an accuracy of about 88% already. If we pass in more samples, 91% is reached at some point (for me it was after about 4000 samples out of the 8000 training samples).
参考
[1] P. Domingos 和 G. Hulten,挖掘高速数据流 (2000),第六届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集
[2] W. Hoeffding,有界随机变量和的概率不等式 (1962),美国统计协会杂志。58 (301)
我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!
作为最后一点,如果你
- 想支持我多写点机器学习和
- 无论如何,计划获得一个中等订阅,
为什么不通过此链接***?这将对我帮助很大!😊*****
说白了,给你的价格不变,但大约一半的订阅费直接归我。
非常感谢,如果你考虑支持我的话!
有问题就在LinkedIn上写我!**
引入 k-最*邻
原文:https://towardsdatascience.com/introducing-k-nearest-neighbors-7bcd10f938c5?source=collection_archive---------20-----------------------
理解这种分类模型的基础
k-最*邻算法基于一个非常简单的前提:距离很*的事物有很多共同点。这个前提全世界都可以看到:
- 大学生最亲密的邻居通常是其他大学生。
- 我们倾向于和我们的浪漫伴侣有更多的共同点,他们和我们共享一个家,而不是和隔壁城镇的人。
- 在杂货店里,每一种产品都储存在一组里,而不是分布在整个商店里。
k-最*邻建模方法使用这一前提来假设我们可以获取关于一个点的知识,并得出关于相邻点的结论。由于相似的事物通常聚集在一起,我们可以利用这种接*性对我们不知道的数据点做出假设。在杂货店里,苹果旁边的商品通常是另一个苹果。更具体地说,节日苹果旁边的物品通常是另一个节日苹果。人们的政治取向相似;随着越来越多的人聚集到政治上两极分化的城镇,如果我们知道一个城市中的一个人是保守派或自由派,我们可以合理地假设他们的邻居也是保守派或自由派。
因为它是基于这样的假设而不是复杂的统计模型,所以 k-最*邻是最简单的预测模型。
k *邻模型是如何工作的?
为了使用 k-最*邻算法,您需要两样东西:
- 相信附*数据点彼此相似的假设。请记住,这并不总是一个有用的假设,你必须小心应用它。例如,如果你想知道口香糖贩卖机中的一个物品是什么,那么知道它旁边的物品是口香糖是非常有用的。然而,如果你想知道相邻的口香糖球是什么颜色,那么知道一个口香糖球是红色是没有用的;每个容器中通常有大约 5 种颜色的口香糖混合在一起。
- 两个数据点间距离的某种*似方法。在最简单的情况下,以及我们到目前为止讨论的所有例子中,这是两个项目之间的实际距离。然而,使用 k-最*邻算法,这也可以是数据集中两点之间的理论距离。例如,如果你想预测不同家庭的卧室数量,你可以使用*方英尺作为你的数据。那么这个距离就是两个不同住宅之间的*方英尺的差异。
通过结合相似项被分组的假设和距离的度量,您可以创建一个算法,通过在数据集中搜索最*的邻居来预测未知事例的事实。一旦找到这些最*的邻居,您就可以得出结论,您的未知点与这些邻居具有相同的特征。
在 k-最*邻模型中,k 是用于定义如何应用该模型的变量。它说明了执行分析时要检查的相邻要素的数量。使用 k-最*邻算法时,您可以更改 k,这可能会产生显著不同的结果。通过尝试不同的值并测试模型的预测能力来选择 k 的值。这意味着您必须开发、验证和测试几个模型。更多信息可以在如何在多个型号中选择中找到。
我怎样才能更好地了解这个算法?
k-最*邻算法是一种常见的分类工具,在互联网上可以找到关于该主题的大量信息。对于那些想要更多信息和高度可信来源的人,我强烈推荐从头开始的数据科学:Python 的基本原理。
关闭
k-最*邻算法是一种常见的分类模型,它基于这样的假设,即数据集中靠在一起的项目通常是相似的。为了使用它,你必须既相信那个假设,又有两个数据点之间距离的度量。然后,该模型使用距离计算来确定与您尝试预测的位置最*的 k 个数据点,并使用来自这些点的信息来得出结论。
介绍车床:朱莉娅的管道
原文:https://towardsdatascience.com/introducing-lathe-pipelines-for-julia-57d7d7c07349?source=collection_archive---------34-----------------------
在 Julia 语言中,我最想念的工具之一是 SKlearn 管道。与 SKlearn 相比,Lathe 本质上是一个非常不同的东西,不仅是基于函数式编程语言构建的,而且还具有像 fit-initialization 这样的初学者友好的属性。我非常想实现的是车床内部 Sklearn 管道的替代方案,随着即将发布的车床 0.0.5,我已经做到了!
笔记本
数据
为了开始我们的小管道演示,我们需要读入一些数据。由于这不一定是一个项目,我将从我的深海相关项目中回收数据。当然,第一步是使用 CSV 读取我们的数据:
using CSV
df = CSV.read("bottle.csv")
然后我们快速清洗!
using DataFrames
df = DataFrame(:TempC => df.T_degC, :Salinity => df.R_SALINITY, :Depth => df.Depthm)
# We're going to drop the missing values now, if we did that prior, # we would
# have likely dropped a-lot more data.
df = dropmissing(df)
轻松点。
现在我们可以进入主题的实质,从选择我们的特性和目标开始。这对我来说并不重要,因为我们不追求准确性,而只是新模块的演示。对于我的特征,我选择了盐度和我的目标温度。让我们对测试和训练集做一个快速分割,然后我们可以设置我们的 x 和 y…
using Lathe.preprocess: TrainTestSplit
train,test = TrainTestSplit(df)
以及 X 和 Y 设置:
trainX = train.Salinity
trainy = train.TempC
testX = test.Salinity
testy = test.TempC
管道
为了在车床中建立管道,首先要建立一个模型。虽然在 Sklearn 中也可以这样做,但是这里的不同之处在于,管道的其他部分依赖于在模型中构造的 X 和 Y。考虑到这一点,我们仍然可以按照 Sklearn 的方式来做,但拟合模型的方式必须与我们在外部做的方式相同。
using Lathe.preprocess: StandardScalar
using Lathe.models: LinearRegression
using Lathe: pipelines
现在我们可以调用函数,它接受一个构造好的车床模型、一个方法或数组中的方法,然后接受一个类型参数。将来,除了原始的管道之外,可能会有不同类型的管道用于不同类型的特性,并且可能到 0.0.5 发布时,会有一个管道能够与其他 Julia 模型通用地工作。现在我们可以构建我们的管道。
pipl = pipelines.Pipeline(LinearRegression(trainX,
trainy),StandardScalar,:CON)
最后一部分,“:CON”告诉 predict 方法要运行哪个算法,这可能会改变,所以我不会太关注这一部分,因为它基本上不重要。
为了预测,我们使用来自车床的函数 pipe _ predict . pipelines:
[@time](http://twitter.com/time) pipelines.pipe_predict(pipl,testX)
恭喜你!
现在我们已经正式创建了一个 fit 管道来保存我们的训练值、预处理方法和模型类型!一个巨大的好处是即将到来的管道系列化。我不仅计划在 Julia 中序列化这些模型,还计划用 PyPi 包将它们读入 Python,以便在 Flask 和 Django 管道和 web 应用程序中使用,这不是很酷吗?
pipelines.save(pipl,"My-Pipeline")
我真的很兴奋的未来,这部分车床,和车床整体举行!车床 0.0.5 中有很多新的统计数据、模型和更多的东西,之后还会有更多!
介绍 Mercury-ML:一个开源的“机器学习之神的使者”
原文:https://towardsdatascience.com/introducing-mercury-ml-an-open-source-messenger-of-the-machine-learning-gods-c571f90e6b36?source=collection_archive---------27-----------------------
在古罗马神话中,墨丘利神被称为“众神的使者”。他穿着带翼的鞋子,戴着带翼的帽子,在奥林匹斯山和人类王国之间飞奔,确保众神的意志被知晓。他不是众神中最强壮、最聪明、最受尊敬或最令人畏惧的,但他脚步敏捷、狡猾,可以依靠他来引导事情朝着他们想要的结果发展。没有他,珀尔修斯不可能打败美杜莎;奥德修斯可能会中了喀尔刻的魔咒;而赫拉克勒斯也不可能将冥府之神地狱犬从冥府中拖出来,从而完成他 12 项神话般的劳动中的最后一项…
在这篇文章中,我想介绍一个名为 Mercury-ML 的新项目,以及开源的“机器学习之神的使者”。
机器学习工作流程看似简单,却依赖于多种工具和技术的复杂组合
机器学习和数据处理工具的最新发展导致了无数的开源库,其中每个库都提供了开发良好的透明 API,并且每个库都在构建健壮的机器学习工作流时发挥作用。经常使用的机器学习库,如 TensorFlow、PyTorch、Keras 或 SciKit-Learn,通常会形成这种工作流的主干,但仍然有来自不同库的无数功能,通常需要串在一起才能完成工作流。
例如,考虑一个图像识别工作流,您需要从 HDFS 获取图像;在这些图像上拟合 Keras 模型;使用 SciKit-Learn 评估模型;在 AWS 上将训练好的模型保存到 S3;在 MongoDB 中存储训练运行的元数据;并最终使用 TensorFlow 服务来服务模型。你如何建立这样的工作流程?
此外,如果您的需求在项目中途发生变化,以至于您需要从其他地方获取数据,或者需要使用不同的机器学习引擎,该怎么办?你将如何拔掉这些组件中的一个并用另一个替换它?您需要引入多少新代码(和测试!)才能让这个正常工作?
机器学习工作流程的上帝使者
这些是我们在 Alexander Thamm 为客户开发机器学习解决方案时经常面临的一些非常现实的问题。
最*,我们很清楚,我们需要一个能够将机器学习项目分解成典型组件(如读取数据、转换数据、拟合模型、评估模型、服务模型等)的库。)足够模块化和通用,允许我们根据需要插入不同的技术。
最初是一个帮助我们更好地完成自己工作的内部项目,现在已经发展成为我们认为值得作为开源库提供给更广泛的社区的东西。因此,我们决定让 Mercury-ML——我们内部开发的“机器学习之神的使者”——在 MIT 许可下在 GitHub 上可用。
最新的稳定版本也将始终在 PyPi 上提供,并且可以使用“pip install mercury-ml”进行安装
(注意,尽管这个库已经有了丰富的特性,但它还远远没有达到特性的完备。我们暂时将它标记为“预发布”,这意味着一些大范围的变化仍然可能发生。
工作原理
Mercury-ML 旨在提供对不同抽象层次功能的简化访问。
作为这种工作方式的一个简单例子,让我们看看通常构成机器学习工作流一部分的两个小组件:保存拟合的模型,然后将保存的对象存储在远程位置(以后可以从该位置提供服务)。为此,我们将考察四个抽象层次:
- 不使用 Mercury-ML(即直接使用底层依赖关系)
- 使用提供者 API
- 使用容器 API
- 使用任务 API(结合容器 API)
这些方法中的每一种都是完全有效的,尽管在某些情况下一种可能比另一种更有意义。让我们来看看:
参数化:
对于这个例子,我们将保存一个 Keras 模型,并将其存储到 AWS 上的 S3 存储桶中。假设我们有以下输入:
model = … # assume a fitted Keras model fetched here
filename = “my_model”
local_dir = “./local_models”
extension = “.h5”
remote_dir = “my-bucket/remote-model”
1。通过直接访问底层库(即不使用 Mercury-ML)的示例
当您希望最大限度地灵活配置如何使用这些库时,使用底层库而不是使用 Mercury-ML API 是有意义的。下面是一个典型的脚本,你可以把它放在一起。
import os**# save model**
if not os.path.exists(local_dir):
os.makedirs(local_dir)filename = filename + extension
local_path = os.path.join(local_dir + "/" + filename)
model.save(local_path)**# copy to s3**
import boto3
session = boto3.Session() #assuming connection parameters are implicit
s3 = session.resource("s3")s3_bucket, s3_partial_key = remote_dir.split("/", 1)
s3_key = s3_partial_key + "/" + filename + extension
s3.Object(s3_bucket, s3_key).put(Body=open(local_path, "rb"))
这里没有什么特别复杂的东西,但是有许多小步骤需要正确执行。您需要手动检查您希望在本地保存您的模型的目录是否存在(并且必须注意 Keras 不会为您这样做)。您必须知道,Keras 将其模型对象保存为 HDF5 文件,扩展名为“. h5”。您必须知道如何打开一个 S3 连接,并且知道保存到 S3 位置的函数调用需要“桶”和“键”输入(这两个输入放在一起可以简化为“路径”)。要做到这一点,你必须处理大量连接和分离字符串路径的调用。
(例如,如果您决定将您的模型对象存储在 Google 云存储中,您将需要再次这样做)。
2。供应商示例
Mercury-ML 中的提供者旨在将大部分内容抽象出来,并在公开一个简单的(但也是高度可配置的)API 的同时处理好细节。
from mercury_ml.keras.providers import model_saving
from mercury_ml.common.providers.artifact_copying import from_disk
import os**# save model**
path = model_saving.save_keras_hdf5(
model=model,
filename=filename,
local_dir=local_dir,
extension=extension
)**# copy to s3**
from_disk.copy_from_disk_to_s3(
source_dir=local_dir,
target_dir=remote_dir,
filename=os.path.basename(path)
)
如果您想要硬编码您想要使用的提供者,使用提供者 API(而不是任务 API 的容器)是最有意义的。例如在上面的代码片段中,你只能使用model _ saving . save _ keras _ HD F5和from _ disk . copy _ from _ disk _ to _ S3。
如果您想要以不同的格式保存模型,或者将它复制到不同的存储中,那么您必须更改您的代码来做到这一点。例如,要存储到 Google 云存储中,您可以将from _ disk . copy _ from _ disk _ to _ S3替换为from _ disk . copy _ from _ disk _ to _ GCS。
3。通过容器的示例
当您希望通过配置文件来控制工作流时,使用容器 API 是最有意义的。
容器只是轻量级的类,允许您从一个位置访问各种类似的提供者。例如,上面使用的函数model _ saving . save _ keras _ HD F5也可以通过容器 ModelSavers.save_hdf5 来访问。使用 getattr 函数,这也可以作为 getattr(ModelSavers," save_hdf5") 访问,使我们可以在配置中轻松地对其进行参数化。
from mercury_ml.keras.containers import ModelSavers
from mercury_ml.common.containers import ArtifactCopiers
import osconfig = {
"save_model": "save_hdf5",
"copy_model": "copy_from_disk_to_s3"
}save_model = getattr(ModelSavers, config["save_model"])copy_from_local_to_remote = getattr(
ArtifactCopiers,
config["copy_model"]
)**# save model**
path = save_model(
model=model,
filename=filename,
local_dir=local_dir,
extension=extension
)**# copy to s3**
copy_from_local_to_remote(
source_dir=local_dir,
target_dir=remote_dir,
filename=os.path.basename(path)
)
想要将模型保存为张量流图吗?而想将其存储在谷歌云存储中?只需更改配置:
config = {
"save_model": "save_tensorflow_graph",
"copy_model": "copy_from_disk_to_gcs"
}
4。示例通过任务(与容器一起)
当您想要使用单个函数来定义涉及多个提供者并需要多个步骤的小型工作流时,使用 tasks API 是有意义的。例如,下面的 store_model 任务被注入了一个 save_model 和一个copy _ from _ local _ to _ remote提供程序,并继续使用这些提供程序首先在本地保存模型,然后将其复制到远程位置。
from mercury_ml.keras.containers import ModelSaversfrom mercury_ml.common.containers import ArtifactCopiers
from mercury_ml.common.tasks import store_modelsave_model = getattr(ModelSavers, config["save_model"])
copy_from_local_to_remote = getattr(
ArtifactCopiers,
config["copy_model"]
)**# save model and copy to s3**
store_model(
save_model=save_model,
copy_from_local_to_remote=copy_from_local_to_remote,
model=model,
filename=filename,
local_dir=local_dir,
remote_dir=local_dir,
extension=extension
)
tasks API 比其他任何东西都更方便,但是对于经常一起出现的小块工作流来说非常有用。
了解更多信息
以上只是一个小例子。完全成熟的示例工作流可以在这里找到。
Mercury-ML 能够促进工作流的一个关键因素也与它在机器学习管道的各个阶段处理数据的方式有关。Mercury-ML 将数据包装成通用的 DataWrapper 对象(例如“特征”和“目标”),并将它们排列成数据集(例如“训练”、“有效”和“测试”),并最终排列成数据组。你可以在这里找到更多关于如何做的信息。
成为投稿人!
这也是对任何对使用 Mercury-ML 感兴趣的开发人员的公开邀请。告诉我们您需要什么功能,让我们知道哪些功能不起作用,或者贡献您自己的更改或添加内容!
引入模型偏差和方差
原文:https://towardsdatascience.com/introducing-model-bias-and-variance-187c5c447793?source=collection_archive---------8-----------------------
模型拟合*衡法
在之前的一篇文章中,我们讨论了模型欠拟合和过拟合的概念。本质上,这两个概念描述了模型无法匹配数据集的不同方式。拟合不足是指建立的模型不够复杂,无法准确地表示数据,并且错过了数据集中的趋势。过度拟合是指模型对于数据集来说过于复杂,并且认为数据集中有趋势,而实际上没有。
思考这些问题的另一种方式是通过偏差和方差这两个术语。这两个术语是数据科学中的附加基本概念,代表了思考模型拟合挑战的另一种方式。理解这两个概念将有助于您创建有用的模拟模型。
什么是模型偏差和方差?
这两个术语都描述了当您使用给定数据集的不同部分重新训练模型时,模型是如何变化的。通过更改用于定型模型的数据集部分,可以更改描述生成的模型的函数。然而,不同结构的模型将以不同的方式响应新的数据集。偏差和方差描述了模型做出反应的两种不同方式。它们的定义如下:
偏差:偏差描述了模型与训练集的匹配程度。具有高偏差的模型不会紧密匹配数据集,而具有低偏差的模型会非常紧密地匹配数据集。偏差来自过于简单的模型,无法捕捉数据集中呈现的趋势。
方差:方差描述了当你使用数据集的不同部分训练一个模型时,它会发生多大的变化。具有高方差的模型将具有匹配提供给它的任何数据集的灵活性,每次都可能导致显著不同的模型。差异来自高度复杂的模型,使用了大量的特性。
通常,高偏差的模型具有低方差,高方差的模型具有低偏差。这是因为两者来自相反类型的模型。不够灵活以正确匹配数据集(高偏差)的模型也不够灵活以在给定不同数据集(低方差)时发生显著变化。
那些读过我之前关于欠拟合和过拟合的文章的人可能会注意到这些概念之间有很多相似之处。欠拟合模型通常具有高偏差和低方差。过度拟合模型通常具有高方差和低偏差。
偏倚和方差之间的权衡是什么?
偏差-方差权衡是数据科学中经常讨论的术语。这是因为您采取的减少偏差的措施(导致更好地拟合训练数据)将同时增加模型中的方差(导致更高的不良预测风险)。反之亦然;你所采取的减少方差的行动将会固有地增加偏差。
关于偏差方差权衡,我能做些什么?
重要的是要记住,增加方差并不总是一件坏事。欠拟合模型是欠拟合的,因为它没有足够的方差,导致持续的高偏差误差。这意味着,当开发一个模型时,你需要找到合适的方差,或者合适的模型复杂度。关键是增加模型的复杂性,从而减少偏差和增加方差,直到偏差最小化,并且在显著的方差误差变得明显之前。
另一个解决方案是增加用于训练模型的数据集的大小。高方差误差,也称为过度拟合模型,来自于创建对于可用数据集来说过于复杂的模型。如果您能够使用更多的数据来训练模型,那么您可以创建一个更复杂的模型,而不会意外地添加方差误差。
不幸的是,这种技巧无助于降低偏置误差。低偏差模型或欠拟合模型对训练数据不敏感。因此,增加数据集的大小不会显著改善模型;它无法对变化做出反应。高偏差的解决方案是更高的方差,这通常意味着添加更多的数据。
我可以在哪里了解更多信息?
我写过几篇类似主题的文章。一篇,在本文中已经链接了几次,讨论了欠拟合和过拟合模型的细节,并给出了相关的例子。第二个从概念上讨论了模型开发、验证和测试的过程,您可以用它来确定模型何时非常适合数据集。此过程将帮助您确定模型中的方差是否正确,并帮助您确定是否需要添加更多数据。
最后,通过阅读 Joel Grus 的书数据科学从零开始:Python 的基本原则,我学到了很多数据科学的概念。他的书介绍了数据科学的许多基本概念,并提供了示例代码来帮助您用 python 开发一些初始函数。
将这一切结合在一起
偏差和方差是数据科学和模型开发中的两个关键术语。它们一起描述了创建模型时可能出现的两个关键错误。偏差指的是所有点上的恒定误差,代表一个不够复杂的模型来捕获数据集。方差是指对于数据集来说过于复杂的模型,通常表现为好像数据集中存在实际不存在的趋势。
这两种误差导致了著名的偏差-方差权衡。模型中高偏差的解决方案是增加更多的方差。但是加太多方差会导致方差误差。因此,创建具有足够方差的模型以捕获数据集并减少偏差误差,而不是创建具有太多方差以至于增加方差误差的模型,就变成了一种*衡行为。
如果不可能找到一个低偏差和低方差误差的解决方案,你需要找到并添加更多的数据。较大的数据集允许您创建更复杂的模型,而不会增加显著的方差误差。通过这种方式,您可以创建一个足够复杂的模型来最小化偏差误差,同时又不会复杂到增加显著的方差误差。
熊猫介绍-日志
原文:https://towardsdatascience.com/introducing-pandas-log-3240a5e57e21?source=collection_archive---------21-----------------------
用于调试 pandas 操作的新 Python 包
Photo by billow926 on Unsplash
熊猫生态系统对于数据科学生态系统来说是无价的,因此今天大多数数据科学任务由熊猫将原始数据转换成可理解/可用格式的一系列步骤组成。
这些步骤的准确性至关重要,因此理解意外的结果也变得至关重要。不幸的是,生态系统缺乏理解这些意外结果的工具。
这就是为什么我创建了熊猫日志,它提供了每个操作的元数据,这将允许查明问题。比如说之后。查询它返回被过滤的行数。
和往常一样,我相信用一个例子更容易理解,所以我将使用口袋妖怪数据集来寻找“谁是最弱的非传奇火口袋妖怪?”。
Photo by Thimo Pedersen on Unsplash
那么谁是最弱的火口袋妖怪呢?
(笔记本代码的链接可在这里找到)
首先,我们将导入相关的包并读取我们的口袋妖怪数据集。
import pandas as pd
import numpy as np
import pandas_logdf = pd.read_csv("pokemon.csv")
df.head(10)
A sample of our dataset
要回答我们的问题,谁是最弱的非传奇火口袋妖怪,我们需要:
- 用
*.query()*
过滤掉传说中的口袋妖怪。 - 只保留火口袋妖怪使用
*.query()*
。 - 降传奇柱
*.drop()*
。 - 使用
*.nsmallest()*
保留其中最弱的口袋妖怪。
在代码中,它看起来像这样
res = (df.copy()
.query("legendary==0")
.query("type_1=='fire' or type_2=='fire'")
.drop("legendary", axis=1)
.nsmallest(1,"total"))
res
It resulted in empty dataframe
哦,NOO!!!我们的代码不起作用!!我们有一个空的数据框!!如果有一种方法来跟踪这些问题就好了!?幸运的是,这就是熊猫日志的作用!
通过在我们的示例中添加一个小的上下文管理器,我们将获得相关的信息,帮助我们找到打印到 stdout 的问题。
with pandas_log.enable():
res = (df.copy()
.query("legendary==0")
.query("type_1=='fire' or type_2=='fire'")
.drop("legendary", axis=1)
.nsmallest(1,"total"))
在阅读输出后,很明显问题出在第 2 步,因为我们还剩下 0 行,所以谓词“type _ 1 = = ' fire '或 type_2=='fire '”是错误的。的确口袋妖怪类型是以大写字母开头的,所以让我们运行固定代码。
res = (df.copy()
.query("legendary==0")
.query("type_1=='Fire' or type_2=='Fire'")
.drop("legendary", axis=1)
.nsmallest(1,"total"))
res
最后,我们得到了我们的结果,我们得到了斯拉格马!!!!!!!!
最后几句话要说
该软件包仍处于早期阶段,所以它可能包含一些错误。请看看 Github 库,并建议一些代码的改进或扩展。我将很高兴地欢迎任何建设性的反馈,并随时为熊猫日志做贡献!😉
使用机器学习推荐 P2P 借贷投资
原文:https://towardsdatascience.com/introducing-peervest-using-machine-learning-to-recommend-investments-in-p2p-lending-d55c07947872?source=collection_archive---------21-----------------------
介绍 PeerVest:一个免费的 ML 应用程序,帮助你在风险回报的基础上选择最好的贷款池
问题
像 LendingClub 和 Prosper Marketplace 这样的 P2P 贷款市场是由连接投资者和借款者的经纪人费用驱动的。他们被激励去增加在他们*台上发生的交易的数量。在易用性的驱动下,他们现成的信用风险评估按分组桶对风险进行评分。在逐笔贷款的基础上,考虑到每笔贷款的独特性和从借款人那里收集的大量数据,这是低效的。在更精细、更连续的基础上对风险进行评分不仅是可能的,而且优于离散的分组桶。
信用风险是所有 P2P 贷款投资者和债券投资者在做出明智决策时必须仔细考虑的问题。包括大型银行在内的机构一直在雇佣研究人员和定量分析师来争论和分析这些数据,希望对自己的风险回报评估更有信心。借款人未能支付所需款项导致本金和利息损失的潜在风险是什么?考虑到贷款的条件,投资者能期待什么样的回报?对于希望超越市场上现成顾问的普通投资者来说,应该有一种更简单、更容易使用的工具。
解决方案:PeerVest
PeerVest 帮助个人投资者扩大他们的投资组合,通过使用基于 LendingClub.com 历史贷款数据训练的机器学习来评估风险和预测回报,智能地将资金分配到 P2P 贷款市场。PeerVest 根据用户的可用资金、最大风险承受能力和最低预期年化回报,推荐最佳投资贷款。有很多机构在利用现代的替代数据集评估信用风险和预测投资潜力方面处于思想领先地位,但我将这个问题简化为两个关键模型:(1)通过预测贷款违约的概率来评估风险,以及(2)预测年化回报。
重要术语和概念
- 点对点借贷(又称 P2P,Crowdlending) :通过在线服务撮合借贷者向个人或企业放贷的行为。由于其纯在线性质和低管理费用,一般来说,与银行提供的储蓄和投资产品相比,贷款人可以获得更高的回报,而借款人可以以更低的利率借钱。
- 人工神经网络:一种计算学习系统,它使用一个函数网络来理解一种形式的数据输入,并将其转换为所需的输出,通常是另一种形式。灵感来自于人类大脑神经元共同运作来理解人类感官输入的方式。在此了解更多信息
- 随机森林模型:一种用于分类、回归和其他任务的集成学习方法,通过在训练时构建大量决策树并输出作为类的模式或个体树的均值预测的类来进行操作。点击此处了解更多信息
- 违约概率:对借款人无法履行债务的可能性的估计。在此了解更多信息
- 年化回报率:按比例缩减至 12 个月的回报率。我使用的公式是:ar =(xTP/xLA)^(365/d)-1,其中 xla 是贷款金额,xtp 是借款人支付的总付款额,d 是贷款资金和最后一次付款日期之间的天数。点击此处了解更多信息
预测违约概率
为了给每笔贷款分配一个数量来衡量其风险水*,或借款人违约的概率,我像处理一个标准的分类问题一样处理这个问题,其中如果每笔历史贷款已全额偿还,则分配 1,如果违约,则分配 0。为了提供比 LendingClub 和类似网站提供的更精细的风险评估,我不是寻找类别(1 或 0),而是寻找每笔贷款预计落入每个类别的概率。我最初的方法是使用逻辑回归,尽管对每笔贷款进行了非常自信的分类,尽管进行了概率校准,但似乎与 sklearn 的没有很好的互动。predict_proba() 函数。此函数返回一笔贷款属于类别 1 的概率,介于 0 和 1 之间。用 1 减去这个数字就可以得到一个可解释的违约概率指标(它越大,违约的可能性就越大)。
给定 1,107 个独特的特征,似乎存在许多非线性关系,并且手动减少维度的努力将是麻烦的。使用主成分分析并没有真正的好处,因为它并没有改善这种情况——它降低了维数,减少了等量的解释方差。我决定保留所有的特性,尽管特性冗余的可能性增加了。知道神经网络能够在许多训练时期处理这种复杂性,我开始使用 Keras 构建一个模型,Keras 是一个基于 TensorFlow 的神经网络库。我通过使用隐藏层大小、丢失正则化、L2 核正则化、早期停止、历元、类权重*衡和 ReLU/Sigmoid 激活函数的不同组合,遍历了许多不同的 Keras 架构。尽管在验证损失方面存在一些停滞,但该模型最终取得了突破,并在几个时期内开始对训练集和测试集进行更显著的改进,同时非常好地校准了预测概率。
表现不佳: 3 个 Scikit-Learn 逻辑回归模型,7 个 Keras 神经网络
表现最佳: Keras 神经网络 v8
最佳神经网络模型架构:
输入层(1107,Sigmoid)>
密集层(1000,Sigmoid,L2)>
密集层(300,Sigmoid)>
密集层(50,Sigmoid,L2)>
密集输出层(1,Sigmoid,L2)
最佳模型参数:
- 损失:二元交叉熵
- 优化器:亚当
- 提前停止
- 等级重量*衡
- 批量:5000 个
最佳模型评估指标(测试误差):
- 完全支付的精确度:0.943
- 召回全额支付:0.979
- F-1 分数完全支付:0.961
- ROC-AUC 评分:0.86
- 预测概率已校准
预测回报
我根据 LendingClub 的可用数据,使用了一个非常简单的年化回报计算方法。由于可解释性,我决定不使用 LendingClub 复杂的调整后净年化回报计算,尽管随着我继续迭代我的模型,我对利用更传统的财务损失估计的精确计算持开放态度。与贷款条款和付款相关的时间因素包含在这一计算中。像联邦利率、通货膨胀和货币的时间价值这样的宏观信息是借款人所报利率中固有的,尽管当然有深入时间序列和生存分析的空间,以增加金融机构生产这种模型的严谨性。
线性回归在训练集上运行良好,但是过度拟合,不能很好地推广到未来集或同一时期的测试集。岭回归,这是类似的,但应用 L2 正则化修复了我的第二次迭代过度拟合的问题。也就是说,我想知道如果使用一些可以做出不同回归决策的东西,我的评估指标是否会有所改善,以及是否有一个模型不那么依赖于总付款,以便我的预测可以用于 LendingClub 上一个没有付款历史的全新列表。考虑到过度拟合的问题,以及其已被证明的引导特征子样本和聚集许多决策树的能力,Random Forest 是完美的候选。简而言之,一个随机森林将能够构建和组合许多彼此不相关的不太好的模型,以创建一个单一的、体面的模型——同时配备处理我的 1,107 个特征,除了找到最佳参数之外,没有太多额外的准备。鉴于 Google Cloud GPU 的强大功能,我让 GridSearchCV 通过搜索最佳组合来处理这个问题。
表现不佳: 1 个线性回归模型,3 个岭回归模型,1 个 Keras 神经网络,4 个随机森林回归模型(使用 Scikit-Learn)
表现最佳:随机森林回归 v5 与 GridSearch 交叉验证
最佳模型参数:
- n _ 估计值= 100
- 最大深度:15
- 最小 _ 样本 _ 叶:4
- 最小 _ 样本 _ 分割:2
最佳模型评估指标(测试误差—不包括支付历史):
- r *方值:0.56
- 均方差:0.02
- 均方根误差:0.16
最佳随机森林回归模型在测试集上实现了 0.16 的均方根误差,这意味着预测的年化回报估计与真实的年化回报相差 0.16。虽然这可能会出现很大的第一,该模型可以非常有用的制定贷款选择策略。贷款违约通常发生在贷款融资后不久,违约的机会随着付款的增加而减少。因此,我推荐年化回报预测高于用户设定的合理阈值的贷款。直观上,阈值可以作为投资者可以根据其投资账户规模进行调整的参数:最小年化回报(较高回报)越大,最大违约概率越小(较低风险),整体贷款选择越严格,因此可以投资的总美元数越少。希望由于更有选择性地投资贷款,年化回报会更高。
也就是说,如果我们对借款人的还款历史有所了解,我们会对自己的预测更有信心,尽管在实践中,作为投资者,我们无法将最初的借款还款行为纳入其中。也就是说,有了一些支付历史记录,这个模型有了很大的改进:
评估指标(测试错误—如果包括支付历史):
- r *方值:0.97
- 均方差:0.001
- 均方根误差:0.04
如何配合 LendingClub.com 使用 PeerVest 应用程序
这个应用程序是免费使用的。如果你决定将我的模型应用到你自己的投资组合中,对我来说没有任何费用或好处。我不是任何形式的注册财务顾问——投资风险自担。
该模型已经作为 Flask 应用程序部署在 web 上,托管在 Amazon Web Services EC2 实例上,使用 HTML、CSS 和 Brython。它可以收集用户的最大风险承受能力和他们相应的最小期望投资组合回报,并根据我的模型的建议,输出目前在 LendingClub.com 生活的贷款的综合列表。
- 访问 peer vest:www . peer vest . online
- 下载推荐 CSV
- 使用下载的 CSV 中的贷款 id 来指导您对 LendingClub.com 的投资!点击路径:点击此处 >登录(或创建账户)>投资>手动投资>更多过滤器>按贷款 ID 过滤>添加美元
关于最优多元化的说明:
- 在任何给定的时间内,LendingClub.com 上的可用投资往往少于 100 项,尽管一个优化的贷款组合应该包含至少 100 项不同的贷款,以充分降低缺乏多样化的风险。实际上,我会在接下来的几周里继续使用这个应用来指导新的投资。尽快找到 100 笔贷款的投资组合,适当分散投资。
- 来自 LendingClub:票据总数少于 100 张的账户更有可能出现负回报
未来的工作——示例用户故事
- 我想知道应用程序的推荐是否一定会比现成的 LendingClub/Prosper 推荐更能让我赚钱
- 我希望所有新上市的产品都出现在推荐集中,这样我的投资决策就可以基于最*的更新
- 我希望能够通过贷款目的进行筛选,这样我就可以策划一个任务驱动的贷款集
- 我想看看 P2P 贷款*台是如何设定利率的
- 我希望看到一个 Python 代码输出,我可以使用它来根据建议集执行我自己的订单,以减少手动分配时间
感谢您的阅读,
亚历克斯
来连线吧!我鼓励你评论、分享或直接给我发消息,告诉我你对这里提出的想法的想法,或者对我今后应该关注的有趣话题的建议。
LinkedIn | GitHub 组合
[## as6140/peervest
(http://www.peervest.online)使用神经网络(分类、概率…
github.com](https://github.com/as6140/peervest)
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指南 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
介绍 SHAP 决策图
原文:https://towardsdatascience.com/introducing-shap-decision-plots-52ed3b4a1cba?source=collection_archive---------3-----------------------
更加详细和灵活地可视化机器学习模型的内部工作方式
SHAP(SHapley Additive exPlanations)框架已经被证明是机器学习模型解释领域的一个重要进步。由 Scott Lundberg 和 Su-In Lee 开发的 SHAP 结合了几种现有的方法,创建了一种直观的、理论上合理的方法来解释任何模型的预测。
SHAP 通过对每一个预测和特征提出同样的问题来建立模型解释:“当特征 j 从模型中移除时,预测 i 如何变化?”所谓的 SHAP 值就是答案。它们量化了特征对预测影响的大小和方向(积极或消极)。正如本文将展示的,SHAP 值可以用线性模型的清晰性来产生模型解释。
由 Scott Lundberg 等人开发的 Python 软件包 shap 提供了计算和绘制 shap 值的工具。项目的主页展示了典型的 SHAP 图,并提供了示例笔记本的链接。
最*,称为决策图的一类新图被添加到形状包中。决策图提供了模型内部工作的详细视图;也就是说,它们展示了模型是如何做出决策的。本文简要介绍了决策图的几个用例:
- 清晰展现大量特色效果。
- 可视化多输出预测。
- 显示互动的累积效果。
- 探索一系列特征值的特征效果。
- 比较和对比几个模型的预测。
- 识别典型的预测路径。
有关更多细节和源代码,请参见决策图文档/插图或下载笔记本。
更新:除了学习 SHAP,我推荐探索 interpretML 包中可解释的助推机器(EBM)(官方文件,视频)。循证医学本身是可以解释的,相关的包包括互动的情节。interpretML 还集成了 SHAP,以及其他方法/模型,便于并行比较。
清晰显示大量特征效果
迄今为止,力图(在自然 BME 中介绍)一直是通过 shap 包可视化单个模型预测的默认方法。考虑以下情节。它显示了根据 UCI 成人收入数据集训练的 LightGBM 模型的预测。预测是个人年收入超过 5 万美元的概率。红色箭头表示提高预测值的要素效果(SHAP 值),而蓝色箭头表示降低预测值的效果。每个箭头的大小代表相应特征的影响程度。“基础值”(见图像左上角的灰色印记)标记了模型对训练集的*均预测。“输出值”是模型的预测:概率 0.64。最大影响的特征值打印在图的底部。总的来说,力图为这个预测提供了一个有效的总结。
将上面的力图与下面的决策图进行比较。决策图的垂直直线标记了模型的基础值。这条彩色的线是预测。特征值打印在预测线旁边,以供参考。从图的底部开始,预测线显示了 SHAP 值(即特征效果)如何从基础值累积到图顶部的模型最终得分。(粗略地说,这类似于统计线性模型,其中效应之和加上截距等于预测。)决策图是 SHAP 值的文字表示,使它们易于解释。
力图和决策图都有效地解释了前述模型的预测。主要影响的大小和方向很容易识别。然而,正如我们接下来将展示的,当涉及许多重要特征时,决策图比力图更有效。
下一个例子使用在 UCI 社区和犯罪数据集上训练的 LightGBM 模型来预测人口中每 10 万人中非暴力犯罪的数量。该模型使用了 101 个特征。使用力图和决策图解释了相同的预测。请注意,力图的水*格式使其无法清晰显示所有重要特征。
相比之下,决策图的垂直格式可以清楚地显示任意数量特征的影响。该图被配置为显示总共 101 个特征中的 30 个最重要的特征。
前面的例子表明,决策图在解释上类似于力图,但是决策图的线性、垂直格式允许描述更多的效果。
可视化多输出预测
决策图可以有效地解释多产出模型。这个例子解释了在 UCI 心脏病数据集上训练的一个分类模型 Catboost 。对于每个观察,有五个等级指示疾病的程度:等级 1 指示没有疾病;5 级表示晚期疾病。
下面的决策图显示了单次观察的模型的多个输出。在这种情况下,x 轴代表原始分数,而不是概率。分数包含在图的图例中,以便于识别。该模型预测类别 4(虚线)。该图显示,该模型自信地预测疾病存在(类别 1 具有非常低的分数),但是该模型不能轻易地区分类别 3、4 和 5。
熟悉 shap 包的人都知道,它为每个模型输出产生一个单独的基值。决策图显示模型基础值的*均值,并相应地移动 SHAP 值,以准确再现模型的得分。这种方法简化了可视化,并允许在相同的比例下绘制和比较任意数量的输出。
显示互动的累积效果
决策图支持 SHAP 相互作用值:从基于树的模型估计的一阶相互作用。与显示许多预测的单个相互作用的依赖图相反,决策图显示所有主要影响和相互作用。
这个决策图使用主效应和交互作用解释了来自 UCI 成人收入数据集的单一预测。它被配置为显示 20 个最重要的效果。该图清楚地表明,几个相互作用推动这一预测的得分更高。
探索一系列特征值的特征效果
决策图可以详细展示模型的行为。在此示例中,我们探讨了在给定的特定情况下,模型的预测如何随着特征值的变化而变化。我们从 UCI 成人收入数据集中的以下记录开始。
Age 56
Workclass Local-gov
Education-Num 13
Marital Status Married-civ-spouse
Occupation Tech-support
Relationship Husband
Race White
Sex Male
Capital Gain 0
Capital Loss 0
Hours per week 40
Country United-States
我们通过多次复制参考记录来创建一个合成数据集,但是以 100 美元为增量从 0 美元到 10,000 美元改变资本增值。这种方法允许我们评估和调试模型。分析师也可能会发现这种方法对提出假设情景很有用。请记住,本例中显示的资本收益的影响是特定于参考记录的,因此不能一概而论。
依赖图可以显示 SHAP 值在特性值范围内的变化。该模型的 SHAP 值代表对数概率的变化。该图显示了 SHAP 值在 5000 美元附*的急剧变化。它还在 0 美元和大约 3,000 美元处显示了一些重要的异常值。
尽管依赖图很有帮助,但在上下文中很难辨别 SHAP 值的实际效果。为此,我们可以用概率标度上的决策图来绘制合成数据集。首先,我们绘制参考记录来建立上下文。这些特征被手动排序以匹配随后的合成数据的绘图。预测是概率 0.76。资本收益为零,这种模式对资本收益的负面影响很小。
现在,我们绘制合成数据。参考记录用虚线突出显示。通过分层聚类对特征进行排序,以对相似的预测路径进行分组。我们看到,在实践中,资本收益的影响在很大程度上是两极化的;只有少数预测介于 0.2 和 0.8 之间。
在进一步检查预测后,我们发现阈值约为 4300 美元,但也有异常情况。0 美元、3,000 美元和 3,100 美元的资本收益有助于出乎意料的高预测;5000 美元的资本利得导致了出乎意料的低预测。这些异常在这里用图例标出,以帮助识别每个预测。3000 美元和 3100 美元的预测路径是相同的。
总的来说,使用决策图很容易解释模型行为,因为可以并排绘制几个预测的全部细节。本文中的其余示例也利用了这一特性。
比较和对比几个模型的预测
决策图对于比较不同模型的预测或解释模型集合的预测非常有用。
五个 LightGBM 模型的预测结果绘制如下,这些模型是在 T2 UCI 成人收入数据集中训练出来的。如果概率 0.5 是这个二元分类任务的阈值,我们看到这个观察值很难分类。然而,Model 2 确信个人年收入低于 5 万美元。如果这是一个典型的观察,那就值得研究一下为什么这个模型是不同的。
识别典型的预测路径
决策图可以展示模型的典型预测路径。在这里,我们将来自 UCI 成人收入数据集的所有预测绘制在概率区间【0.98,1.0】中,以查看高分预测的共同点。使用分层聚类对特征进行排序,以对相似的预测路径进行分组。该图显示了两条不同的路径:一条是由资本收益主导的,另一条是由资本损失主导的。与关系、年龄和教育相关的影响也是显著的。Alpha 混合(部分透明)用于指示高密度和低密度区域。
为了比较,这里显示了多预测力图。它是许多旋转 90 度并水*堆叠的单个力图的组合。这些情节之间有几个不同之处;我们将指出几个。力图显示,大约四分之三的预测遵循资本收益主导的预测路径。决策情节无法传达这种比例感。在力图中,左侧的预测并不明显是由资本损失主导的,除非在交互模式下查看,在这种模式下,鼠标悬停时会显示功能标签。此外,年龄和关系的一般模式并不突出。决策图更有效地揭示了这些方面。
结论
决策图是对形状包的自然补充。它们通过 SHAP 框架提供的简单性和清晰性有效地交流模型决策。它们也很灵活,允许从单一预测解释到模型诊断的各种用例。如果您发现了使用决策图的新方法,请发表评论。
向学生介绍自动化和机器人
原文:https://towardsdatascience.com/introducing-students-to-automation-robotics-a88dd9cecee0?source=collection_archive---------17-----------------------
Photo by Andy Kelly on Unsplash
这个领域没必要那么可怕
自动化很快就成了人们谈论的话题。政客们现在正围绕它展开竞选活动。整个公司都是建立在人工智能(AI)和机器人算法之上的。相关技术甚至已经开始渗入国内领域。一二十年后,我们与机器人和人工智能互动的频率可能会与我们与人类的互动相当。
然而,随着教育的发展,高中生所学的内容和工程领域的实用知识之间存在着差距。虽然有专门的学校致力于在计算机科学原理方面教育学生,早熟的学生组成了涉及现代领域的俱乐部,但大多数年轻人直到大学晚期才接触到高级课题。这是基于他们的大学有如此先进的领域的假设,而许多并没有。
令人担忧的是,就读 STEM 学院的学生对技术领域了解不足。他们可能会进入一个就业增长有限的领域。此外,未知的领域或主题可能会让人望而生畏。如果没有中学的初步介绍,学生可能会被阻止进入一个令人生畏的领域。老师也没有错。没有人能指望数学老师会熟悉机器人学中的数学。
为了向年轻人介绍这个领域,机器人技术可以大大简化。在大学里,我们学习开发机器人系统数学模型的最正规的方法。这样做主要是为了使分析策略能够被推广并应用到各种系统中。这样做,该领域需要彻底的线性代数和微分方程的先决知识。然而,许多基本的机器人系统可以简化成三角原理。
我想用一个简单的例子来证明这一点(如果数学很可怕,可以跳过图像)。也许一个雄心勃勃的数学老师可以找到在教案中实现这个概念的方法。在机械臂建模中,有正向和反向运动学的概念。当我们知道机器人关节之间的角度时,就可以使用正向运动学。知道了这些角度,我们就可以计算出手臂末端,也就是末端执行器,在三维坐标空间中的位置。这有助于检查机械臂是否处于预期位置。反向运动学可能更有用。反向运动学是指我们知道末端效应器在三维坐标空间中的位置。基于这个位置,我们想要计算手臂必须配置的关节角度,以实现这样的坐标。
一个典型的机械臂,一个具有三个旋转关节的三自由度机械臂,将是我们的测试示例。这个机器人有三个关节,每个关节都沿着一个轴旋转。我们通常将这个机器人简化为三个圆柱体,代表旋转关节,两个杆,代表实际的手臂。如果我们知道末端效应器需要的位置,那么我们可以很容易地使用三角形的切线属性(记住,SOH-CAH-TOA)找到第一个关节的角度(俯视图)。其他两个关节角度的值是使用机器人手臂的已知尺寸和末端执行器的位置的三角关系来求解的。
It’s just a bunch of triangles!
对于长期放弃数学的读者来说,上述内容可能令人望而生畏。然而,在一个上三角函数课的高中生的头脑中,上述内容并不陌生。除了向学生介绍机器人技术,上面的例子还回答了老生常谈的课堂问题:“我们什么时候会在现实生活中使用它?”。给学生一个任意科目的实际应用。
我的意思不是用上面的例子来概括机器人和自动化的整个领域。理解上述概念并不能使一个人成为机器人专家。然而,它可以激发学生的好奇心。
随着社会走向一个更加自动化的世界,预测什么将构成“现实生活”是一件棘手的事情。虽然不是每个学生都会继续从事自动化研究,但可能会需要相当于现代汽车修理工的机器人技术人员。在波士顿的一个机器人展示会上,我有幸听到波士顿动力公司的首席执行官马克·雷伯特博士展示他的机器狗。据雷伯特博士的技术员转述,他的预测之一是,机器人浪潮将创造我们尚未想象的工作岗位。
Would you like ice with that?
spot mini 等机器人被设计为室内家用机器人。也许一个网络工程师找到了一个聪明的方法,将齿轮控制的猎犬连接起来,递送食物和包裹。也许一个电机和嵌入式硬件的修补匠会发现机械狗有一个臭名昭著的小故障。像手机屏幕更换店一样频繁的维修店将会发展起来。这些知识中的大部分需要理解相当复杂的机制是如何运作的。
我们不应该回避复杂,以此作为避免阐述材料的理由。在以大猩猩玻璃产品闻名的陶瓷公司康宁公司实习时,我有幸与康宁创新部门的负责人交谈。该小组负责监控康宁公司哪些技术领域被低估了。
在我们的谈话中,我们谈到了人工智能和机器学习的话题。部门负责人向我解释说,公司已经在使用高中实习生通过张量流库实现机器学习算法。虽然一位资深的机器学习科学家可能会嘲笑张量流绝不是黑盒的概念,但孩子们能够操作工具的事实证明了他们的能力。为什么要浪费一个推动 STEM 感兴趣的学生超越教育部门构建的限制的机会呢?
介绍人工智能项目画布
原文:https://towardsdatascience.com/introducing-the-ai-project-canvas-e88e29eb7024?source=collection_archive---------2-----------------------
人工智能项目管理
使用调整后的商业模式画布来推销你的下一个人工智能项目。
创造一个人工智能项目总是涉及到回答同样的问题:你增加的价值是什么?需要什么数据?客户是谁?预期的成本和收入是多少?
2008 年,Alexander Osterwalder 开发了商业模式画布,该画布在解释世界各地的商业模式方面取得了巨大成功。过去需要 30 页的商业计划来详述一个商业想法,现在可以在一页上完成。它与精益启动方法配合得很好,使您能够专注于增值活动,并快速创建 MVP 驱动的产品。
精益启动周期由构建-测量-学习反馈回路组成。作为一名数据科学家,你会接受这种精益方法。建立解决方案的原型并不断迭代直到达到关键指标是任何成功的人工智能项目的核心。因此,调整人工智能项目的商业模型画布是很自然的。
作为一名前管理顾问和数据科学的现任项目负责人,我的背景帮助我设计了 AI 项目画布。人工智能项目画布将帮助您回答关于您的人工智能项目所需的成果和资源的最紧迫的问题。这篇文章解释了人工智能项目画布以及真实世界的例子。在此下载可编辑的或空白画布。
Photo by rawpixel on Unsplash
我们开始吧。🖌 ⬜️
人工智能项目画布
想象以下场景:你对一个新的人工智能项目有一个绝妙的想法。要实现它,你需要说服管理层为你的想法提供资金。你需要向利益相关者和管理层推销你的人工智能项目想法。呸。
这是 AI 项目画布发挥作用的第一步。虽然 Louis Dorard 已经创建了 ML Canvas ,但 AI 项目 Canvas 的重点是解释你的 AI 项目的商业价值。人工智能项目画布帮助你构建并向他人传达你的人工智能项目的整体思想。
人工智能项目画布由四个不同的部分组成:作为项目中心部分的价值主张,左侧的成分,右侧的客户集成,以及底部的融资。所有这些部分都是任何人工智能项目的重要方面。让我们看一下每一部分,从价值主张开始。
人工智能项目画布的核心是价值主张。它解释了项目将为您的组织增加的价值。增值可以是一种新的人工智能产品,以产生收入,或改善现有流程以降低成本。AI 项目在解决什么客户痛点?您添加了哪些维生素来改善顾客的生活?理想情况下,您可以用一个简洁的要点来描述价值主张。列出许多价值主张可能会淡化影响,或者未能关注最重要的价值主张。
旁注:尝试一种听起来很酷的新论文不会让你走得很远。你的 AI 项目的附加值是什么?充分回答这个问题有助于你专注于手头的任务,并让你为你的人工智能项目获得一半的资金。接下来让我们看看配料块。
成分部分由数据、技能和输出块组成。
数据是每个人工智能项目所依赖的主要元素。你越能解释你需要什么数据来创造价值主张,对你的人工智能项目就越好。你需要多少数据?您是否已经有一个准备好的数据集,或者您是否需要获取它?一定要贴标签吗?你期望什么样的数据格式?
在技能模块中,您将定义您需要的专业技能。是计算机视觉还是自然语言理解任务?需要数据工程师帮你写高效软件吗?甚至可能是一个产品经理和一个 UX 设计师来收集客户需求并设计一个工作流程?
输出块显示了您正在评估的单个关键指标。吴恩达在他的书机器学习的渴望第八章中建议在项目开始前定义一个单一数字的评估指标。这有助于您首先选择一个好的模型,然后根据这个指标比较不同模型的性能。输出指标可以是准确度、f1 分数、精确度或召回率、使用服务的时间等。可以用足够的度量来补充输出度量,例如,精度必须超过 95%(关键度量),而推理时间不超过 1 秒(足够的度量)。
在解释了你的 AI 项目的成分部分之后,接下来我们来谈谈你将如何把你的 AI 项目带给客户。
AI 项目画布的右边部分涵盖了将您的项目集成到当前的基础设施中,供利益相关者和客户使用。
人工智能产品很少生活在一个孤立的世界中,几乎没有在 Jupyter 笔记本中。它们总是需要集成到现有的架构中。解释项目将用于何处以及如何使用。它在后端的什么位置?客户将如何使用您的模型?在流式传输期间,您会使用微服务、整体服务还是动态预测?回答这些问题将使人们清楚这个项目将如何投入生产。
列出关键利益相关者会让你对重要的决策者有一个大致的了解。关键利益相关者可以是法律、UX、管理等内部部门,甚至是承包商、所有者、政治或非盈利组织等外部利益相关者。
最右边的部分是价值主张之后第二重要的部分。你为谁设计项目?很多时候,数据科学家爱上了他们模型的技术细节,但却不知道他们在为谁开发模型。客户真的关心准确性从 99.2%提高到 99.3%吗?还是更快的推断时间更适合他们?详细描述您的不同客户群,以指导您在整个过程中的决策。
在定义了如何将项目带给客户之后,我们最后来探讨一下你的 AI 项目的财务要求。
任何项目都需要有良好的财务基础。回答关于成本和收入的问题将使你处于一个强有力的位置来解释为什么你的人工智能项目应该得到资助。
成本块详细列出了将要发生的成本。需要外包贴标吗?您会产生计算成本吗?不要忘记提及你的团队成员花费的时间或薪水。你不必写下绝对成本,给出成本类别的概述就足够了。
最后,收入块显示你的人工智能项目将如何使公司获得新的收入。该产品将作为一项服务出售,还是作为用户的新功能类别出售?该项目是否会通过自动化流程降低内部成本或支持创新计划?提及收入类型是任何人工智能项目的重要组成部分。
总结一下 AI 项目画布,看看上图中的循环依赖。为了达到目标产量,你需要花费成本来与关键技能争论数据。有了这个模型,你将为组织提出新的价值。然后,在与涉众沟通的同时,将产品整合到现有的架构中。客户将从您的项目中受益,从而为您的公司创造收入。
理论够了。在解释了 AI 项目画布背后的理论之后,接下来让我们看一个真实世界的例子。
人工智能项目画布示例
在之前的帖子中,您了解到了真实世界的数据科学项目,该项目对汽车记录的面部进行匿名处理,以保护个人隐私。让我们为这个项目创建 AI 项目画布。
价值主张很简单:保护个人隐私。这将建立信任,缓解法律担忧,并仍然使该公司能够收集开发自动驾驶汽车所需的数据。
接下来,我们将了解创建价值主张所需的要素。找出数据块是配料管道中最重要的部分。由于我们将使用预先训练的模型,我们至少需要一个现实的验证和测试集来评估不同的模型。比方说,我们需要 10k 张从汽车视角拍摄的带标记人脸的图像。我们决定获取一个特定于我们用例的新数据集。
在技能模块中,我们列出了计算机视觉技能。我们将在 Python 中实现模型,可能需要数据工程技能来生产模型。
输出模块的关键指标已由 OKRs 定义,如本帖子中所定义。我们需要在检测 IoU 为> 0.5 的人脸时达到 95%的准确率。现在不需要足够的度量。
接下来,我们进入价值创造部分。
该项目将通过微服务整合到当前的视频提取服务中。开发者可以调用 API 来匿名化他们的图片。
关键利益相关者是法律部门,因为他们必须决定服务何时提供法律利益。其他利益相关者是一般管理人员,因为他们赞助这个项目。
谁将是这个项目的客户?数据驱动的汽车功能开发人员从匿名化中获益,因为他们可以访问自己的数据集,也可能访问其他人的数据集。工程师是我们最有价值的客户。
最后但同样重要的是,我们将描述我们项目的财务状况。
对于成本模块,我们需要一名数据科学家三个月的时间。我们还需要签约一家标签公司来收集和标记我们的训练数据。此外,我们还会产生云计算成本。
为了获得收入,这种匿名化微服务可以在软件即服务的基础上获得许可。
恭喜你,我们已经创建了我们的第一个人工智能项目画布!你看到这些部分是如何很好地组合在一起来展示这个项目的吗?
如果某些块在您的项目中不如其他块重要,请不要担心。重要的是,你已经考虑了这些块。
因此,我们对我们提出的人工智能项目有了一个全面的了解。我们知道我们试图创造什么价值。我们可以展示我们需要哪些数据和技能来创建一个输出。我们知道最终的模型将如何集成到现有的架构中,以及谁是我们的利益相关者和客户。最后,我们展示了我们预期的成本和收入。
关键要点
就像商业模型画布一样,人工智能项目画布是一个方便的工具,可以快速解释你的人工智能项目的附加值。它旨在用于向管理层、风险承担者和新团队成员解释项目的范围、目的和内容。使用人工智能项目画布来构建人工智能初创公司、人工智能产品和人工智能项目。它有助于你从客户的角度思考问题,设计出真正有影响力的人工智能项目。
- 使用人工智能项目画布向利益相关者和同事解释你的人工智能想法
- 重温人工智能项目画布,以客户为中心关注价值主张
- 确保考虑人工智能项目画布的所有区域
在这里下载 AI 项目画布。当决定接下来支持哪些人工智能项目时,我们将使用人工智能项目画布。你会吗?🖌 ⬜️
这篇文章是正在进行的系列文章的一部分,旨在教育数据科学家以客户为中心的思维和商业敏锐度。我们鼓励数据科学家摆脱“让我们实现这篇论文,看看会发生什么”的态度,转向“我们能产生什么价值”的态度。正如李开复指出的,我们正在进入人工智能实施的十年,需要冠军来生产机器学习模型。
如果你想了解最新消息,请考虑在 Medium 或 LinkedIn 上关注我。你也可能喜欢 这些 帖子。如果您认为应该在 AI 项目画布上添加一些内容,请发表评论。干杯!☮️
为文本分类模型引入“香蕉测试”
原文:https://towardsdatascience.com/introducing-the-banana-test-for-near-perfect-text-classification-models-ee333abfa31a?source=collection_archive---------10-----------------------
结合拼写纠正、术语过滤和“香蕉测试”来构建弹性文本分类模型。
Source: https://pixabay.com/photos/bananas-fruits-food-grocery-store-698608/
介绍
有 数百万 的实例表明,企业已经在他们的系统中收集了自由格式的文本。为了自动化利用这些数据的业务流程,自由格式的文本通常需要被划分到更高级别的类别中。文本分类模型能够快速有效地对这种自由形式的文本进行分类……在很大程度上。
不管报告的验证/测试准确性如何,有许多陷阱会导致即使是训练最良好的文本分类模型也无法进行准确的分类。特别是,文本分类模型在面对从未见过的文本时往往会失败。
如果您的目标是最大化新文本分类模型的准确性,您应该考虑使用香蕉测试。尽管名字很傻,但这是一种非常真实的技术,可以用来提高模型的质量。
什么是香蕉测试?
香蕉检验旨在作为一个决定因素(通常与置信区间相结合)来判断给定的分类是否可信。由于机器学习模型在默认情况下总是会对数据进行分类,并且它提供的置信区间只不过是对概率(而不是准确性)的一种度量,因此香蕉测试有助于确保模型只在有足够的训练数据来做出自信的决策时才对新数据进行分类。它是如何工作的以及它为什么重要都是非常简单的概念。
解释一下测试的名字,“香蕉”这个词从来没有和我工作过的任何公司有过关联。由于我在进入数据科学之前曾是一名产品负责人,我开始相信定义适当的验收标准对于开发一个好的产品至关重要。因此,作为正在构建的任何新文本分类模型的一种接受标准,我强制要求我的模型应该 从不 自信地对包含单词“banana”的文本字符串进行分类。
为什么不呢?嗯…
- 一个理想的文本分类模型应该在一个巨大的文本语料库上进行训练,这个语料库包含了在生产中出现的几乎每一个术语。
- 如果一个模型已经在一个非常大的数据堆上训练过,那么文本语料库中不存在的任何术语几乎肯定是奇怪或不寻常的。这表示术语可能与未经训练的类别、拼写错误或完全不符/错误的数据(例如,文本输入到错误的字段)相关联。
- 为了避免错误,模型应该只在它对正在查看的数据训练有素并且对答案非常有信心时才对文本进行分类。
- 如果一个模型从未在一个提供的文本字符串中看到一个或多个术语,那么就没有办法保证它有信心进行分类。在许多情况下,它仍然会得到正确的答案,但也有很大的机会,未经训练的术语可能会改变答案。为了追求完美,当面对从未见过的文本数据时,模型应该自我报告它不知道答案。理想情况下,模型还会对它未能识别的术语进行自我报告。
因此,香蕉测试就是将输入数据中要分类的术语列表与模型已训练的术语列表进行比较,并确定是否完全覆盖。如果有些术语不包含在定型数据中,则输入数据无法通过香蕉测试,可能不应该由模型进行分类。在 Python 中,使用集合交集(或许多其他解决方案)可以非常容易地做到这一点;具体实现看你了。
这种策略导致了精确和可靠的文本分类模型,代价是被分类记录的百分比略有降低。
实际例子
假设您正在训练一个 tensorflow 模型来区分啤酒和葡萄酒,输入数据以自由格式文本的形式提供。我们还假设您的模型接受最多五个术语(单词)作为基于记号化器和单词索引的填充数组。
在对一些训练数据进行预处理和标记后,您的单词索引可能看起来像这样:
{
"beer": 1,
"wine": 2,
"pinot": 3,
"noir": 4,
"chardonnay": 5
"lager": 6,
"cabernet": 7,
"cab": 8,
"rose": 9,
"ipa": 10,
"pilsner": 11,
"zinfandel": 12,
"chianti": 13,
"porter": 14,
"stout": 15,
"sauvignon": 16,
"red": 17,
"blend": 18,
"merlot": 19,
"ale": 20,
"mead": 21
}
根据上面的单词索引…
- 如果您向模型提供文本
"pinot noir"
,那么得到的数组将是[3, 4, 0, 0, 0]
。 - 如果您提供文本
"red blend"
,得到的数组将是[17, 18, 0, 0, 0]
。 - 如果您提供文本
"ipa"
,得到的数组将是[10, 0, 0, 0, 0]
。
这听起来不错。但是,您可以向这样的模型提供许多值,这会导致错误分类。例如…
- 如果您提供了文本
"banana"
,那么得到的数组将是[0, 0, 0, 0, 0]
。这个术语根本没有出现在单词 index 中,但是数组仍然是基于用来填充输入序列的函数创建的。对于在训练数据中出现频率最高的两个类别(啤酒或葡萄酒),生成的分类将显示较高的置信区间。解决这个问题的一个办法是在分类之前把所有的空数组都踢出去,然后就到此为止,但是… - 如果您提供了文本
"neither wine nor beer"
,那么得到的数组将是[0, 2, 0, 1, 0]
。假设您决定剔除空数组,模型仍然会有把握地错误分类这个记录。分类的置信区间也可能出人意料地高,这取决于两个类中的每一个有多少训练数据(即,如果有 300 条关于葡萄酒的训练数据记录,而只有 20 条关于啤酒的训练数据记录,则模型可能非常确信该输入属于葡萄酒类)。 - 如果您提供文本
"this is a beer"
,得到的数组将是[0, 0, 0, 1, 0]
。这个模型仍然可能正确地分类这个记录,但是输入可能会说"definitely not a beer"
,结果得到的数组会是完全相同的。 - 如果您提供了文本
"bourbon"
,那么得到的数组将是[0, 0, 0, 0, 0]
。这大概应该是一个全新的类(白酒)。
根据上面的例子,如果您的模型能够自我报告它看到了从未训练过的新术语,并避免对这些不一致的记录进行分类,这不是最好的吗?
通过在进行预测之前应用香蕉测试,您的模型将能够剔除上面的每一条记录,并提供一组未通过测试的术语,如bourbon
、banana
、definitely
等。这种方法可以让你创建一个非常有意义的反馈循环。这也意味着您可以将您的模型投入生产,并且知道它只会在识别每个术语时对记录进行分类。
香蕉测试的先决条件
应用香蕉测试时会出现一些问题。也就是说,香蕉测试可以标记在训练过程中被过滤掉的术语和/或不能识别拼写错误的术语。
以下步骤是我认为应用香蕉测试的先决条件,这样你就可以避免这样的问题。无论您决定如何对数据进行预处理,在训练过程和分类过程中都应该应用完全相同的步骤。
案例规范化
在训练文本分类模型或向其输入新数据进行分类之前,您几乎应该始终将文本规范化为单个大小写(通常为小写)。我说“几乎总是”是因为我确信有一些例外,其中大小写可能对模型有意义。
术语过滤
术语过滤并不总是必需的,但通常是推荐的。有些术语,甚至是停用词,对于提供长短期记忆(LSTM)层这样的东西的上下文可能仍然很重要。在从文本语料库中过滤太少或太多的术语之间,你需要找到一条微妙的界限。祝你好运。
拼写纠正
拼写纠正有助于规范化术语的变化,以便香蕉测试(以及一般的模型)尽可能有效。我过去使用的一种方法是使用字符串距离函数将文本语料库中最常出现的术语与文本语料库中的每一个其他术语进行比较。通过基于字符串距离分数过滤结果,数据中存在的许多拼写错误将会暴露出来。这种技术需要手动检查,但如果数据中的术语/拼写错误比一般的拼写自动纠正算法能够可靠处理的要复杂一些,通常会产生很好的结果。
香蕉船
香蕉船是对香蕉测试的可选增强(正如你现在所知道的,我喜欢为严肃的事物取愚蠢的名字)。简单地说,香蕉分裂是在执行香蕉测试之前,从文本语料库(基于 TF/IDF)中分离出总术语的前 N %的实践。
香蕉分裂很重要,因为文本语料库中最不常用的术语可能具有最少的与之相关联的训练数据。通过将香蕉分割应用到香蕉测试的实现中,您可以控制模型在对数据进行分类时的保守程度。模型见过(但可能很少见到)的术语可以被踢出去,就好像模型以前从未见过它们一样。
结论
尽管名字很有趣,方法也很简单,但这种技术对于制作能够有效处理新数据且错误最少的文本分类算法来说至关重要。到目前为止,它已经帮助我和我的团队大大提高了几十个模型的准确性和可靠性,并且已经成为我们的标准做法。我希望它也能让你受益,也许有一天我会听说其他人也在使用香蕉测试!
介绍四方模型:为了更精确的线性回归
原文:https://towardsdatascience.com/introducing-the-four-square-model-for-more-accurate-linear-regression-24c3192b5022?source=collection_archive---------24-----------------------
为数据科学铺*道路是如此迷人。我认为创建一个模型来提高你的准确性,哪怕只是一点点,都是令人惊讶的。对我来说,我发现很少有事情比使用复杂的条件和数学公式来创建一些可以循环用来训练模型的东西更有趣。不仅如此,获得比传统模型更高的精度让它更加令人兴奋。
我觉得好像应该建立一些东西,不管有多好;事情总是要改进的,这在机器学习中尤其普遍。我喜欢数据科学的一点是,我可以在数学上、精神上有创造力和激情,同时还可以玩一些我最大的爱好。所以我向你们介绍:四方模型。在实践中,这是一个非常简单的模型,但在我迄今为止的经验中,这是一个非常有用的模型。
是什么样的?
如果您已经在数据科学领域工作过一段时间,您可能会想到所有的模型都是特定于案例的。为了选择一个模型,你首先需要知道你想要这个模型做什么。这类似于在软件工程的任何夸克中要求机器做某件事;如果你执行一行代码,你期望得到一定的回报。回报可能不总是我们想象的那样,但是,嘿,这就是编程。
所以,当然,我不能为不特别的用例推荐这个模型,我会为你解释这个模型背后的数学和软件。
这个模型,就像我说的,很简单。它使用第一、第二、第三和第四季度以及最小和最大数据将数据分类到不同的范围。然后用简单的线性模型来拟合这些范围。将来,我计划根据所述数据的计算方差来改变模型。该模型的用例正是具有高方差的数据。单价就是一个很好的例子。线性回归模型不太擅长预测单位数据,因为它受到线性度的限制。想象四条独立的线,四个独立的模型,每一个模型对应一个季度的数据。不用说,在某些情况下,对于连续特征,该模型比线性回归更准确。
它是机器学习算法的终极目标吗?不。但这就是数据科学的意义,实验。
当然,我将在本文中排除线性回归的使用。但这个实验是基于相同的数据,如果你想查看文章,这里是。一如既往,笔记本可以在这里买到。此外,我应该注意,如果您想使用该型号,它仅在不稳定的 0.0.2 版本中可用。优势当然是存在的,增加了更多的统计数据,标量,更多的验证,更多的模型。您可以通过以下方式添加它:
using Pkg
Pkg.add(url="[https://github.com/emmettgb/Lathe.jl](https://github.com/emmettgb/Lathe.jl)#Unstable")
要获得最新的稳定版本,只需移除#Unstable,或者放入#master
using Pkg
Pkg.add(url="[https://github.com/emmettgb/Lathe.jl](https://github.com/emmettgb/Lathe.jl)")
在不久的将来(未来几天),您将能够:
using Pkg
Pkg.add("Lathe")
安装和使用
那么这种模式有实际的需求吗?与传统的线性或逻辑模型相比,它有什么样的改进?嗯,我继续进行测试,当然是在我之前的努力中使用的相同的纽约市数据上,拟合线性回归。
我们可以像拟合线性回归一样拟合模型。
model = models.FourSquare(df.LotArea,df.SalePrice)
这将返回以下输出:
Lathe.models.FourSquare(Int64[8450, 9600, 11250, 9550, 14260, 14115, 10084, 10382, 6120, 7420 … 9000, 9262, 3675, 17217, 7500, 7917, 13175, 9042, 9717, 9937], Int64[208500, 181500, 223500, 140000, 250000, 143000, 307000, 200000, 129900, 118000 … 136000, 287090, 145000, 84500, 185000, 175000, 210000, 266500, 142125, 147500])
或者类似的东西。当然,我还拟合了一个线性回归模型来比较两者的准确性。
using Lathe: models
model = models.LinearRegression(df.LotArea,df.SalePrice)
太棒了,4 个系列中的 2 个合身款。
在用我的两个模型预测后,
testdf.linearreg = models.predict(model,testdf.LotArea)
testdf.foursqu = models.predict(model,testdf.LotArea)
我们有两个数组,最后可以比较一下,看看分数如何。到目前为止,我们仍然坚持使用 MAE,然而,0.0.2 将承诺 r2 也可以进行验证。这是我们得到的!:
linearacc = validate.mae(testdf.SalePrice,testdf.linearreg)
输出为:
173848.28232265453
173,000 并不是那么糟糕,考虑到这些数据只是被清理了一点点,然后直接扔进了模型。此外,在接下来的文章中,我计划实际上为此建立一个非常棒的模型,并使用车床获得相当高的精度,所以请继续关注。当然,你会想知道四方模型的精确度是多少?
foursqacc = validate.mae(testdf.SalePrice,testdf.foursqu)
我们高兴地迎接:
104892.39723066095
我当然会四舍五入这些数字,174 对 105。总误差在 65 左右。所以:不一定不可思议,但正如数据科学人士会注意到的那样,如此大的跳跃可能意义重大。当然,在我看来,对于这种比较,r 验证会更好。
但是…它是如何工作的?
该模型将从获取数据的长度开始,并比较适合的数组的长度。
x = m.x
y = m.y
# Go ahead and throw an error for the wrong input shape:
xlength = length(x)
ylength = length(y)
if xlength != ylength
throw(ArgumentError("The array shape does not match!"))
end
这只是为了确保数组形状是相同的,因为如果不是这样,模型就不会像我们希望的那样顺利。这是预测方法中最重要的等式:
# x = q1(r(floor:q1)) |x2 = q2(r(q1:μ)) |x3 = q3(r(q2:q3)) |x4 q4(r(q3:cieling))
# y' = q1(x * (a / x)) | μ(x * (a / x2)) | q3(x * (a / x3) | q4(x * (a / x4))
这到底是怎么回事?嗯,由于该模型专用于预测连续数据,所以我们根据数据排序时它所在的四分位数来拆分数据。因此,第一个范围是数据到第一个四分位数的最小值,这是数据的四分之一标记,第二个范围是第一个四分位数到第二个四分位数(中位数),以此类推。有几种方法可以做到这一点,我们可以使用 Lathe.stats.firstq 计算四分位数在哪里,当数据在较低范围内时,使用条件将数据追加到列表中,或者我们可以使用 Lathe.preprocess 中一个名为 SortSplit 的方法。SortSplit 自动对数据进行排序,取指定的最大百分比(默认为 0.25)并将其分成两个新数组。
# Quad Splitting the data ---->
# Split the Y
y2,range1 = Lathe.preprocess.SortSplit(y)
y3,range2 = Lathe.preprocess.SortSplit(y2)
y4,range3 = Lathe.preprocess.SortSplit(y3)
range4 = y4
# Split the x train
x1,xrange1 = Lathe.preprocess.SortSplit(x)
x2,xrange2 = Lathe.preprocess.SortSplit(x1)
x3,xrange3 = Lathe.preprocess.SortSplit(x2)
xrange4 = x3
本质上,我们把 x 和 y 分成下端,中下端,中上端和上端。SortSplit 方法是这样做的:
function SortSplit(data, at = 0.25, rev=false)
n = length(data)
sort!(data, rev=rev) # Sort in-place
train_idx = view(data, 1:floor(Int, at*n))
test_idx = view(data, (floor(Int, at*n)+1):n)
return(test_idx,train_idx)
end
它取数据的长度并将其相乘,然后用百分位倒数返回两个数据。
接下来,我们拟合出线性回归模型,每个季度一个数据。
# Fitting the 4 linear regression models ---->
regone = LinearRegression(xrange1,range1)
regtwo = LinearRegression(xrange2,range2)
regthree = LinearRegression(xrange3,range3)
regfour = LinearRegression(xrange4,range4)
# Split the train Data
xt1,xtrange1 = Lathe.preprocess.SortSplit(xt)
xt2,xtrange2 = Lathe.preprocess.SortSplit(xt1)
xt3,xtrange3 = Lathe.preprocess.SortSplit(xt2)
xtrange4 = xt3
# Get min-max
xtrange1min = minimum(xtrange1)
xtrange1max = maximum(xtrange1)
xtrange2min = minimum(xtrange2)
xtrange2max = maximum(xtrange2)
xtrange3min = minimum(xtrange3)
xtrange3max = maximum(xtrange3)
xtrange4min = minimum(xtrange4)
xtrange4max = maximum(xtrange4)
# Ranges for ifs
condrange1 = (xtrange1min:xtrange1max)
condrange2 = (xtrange2min:xtrange2max)
condrange3 = (xtrange3min:xtrange3max)
condrange4 = (xtrange4min:xtrange4max)
我们还获取了每个四分位数的范围,以便对我们的训练数据中的每个 x 进行分类。此外,我们必须创建一个空数组来追加数据。
e = []
然后,我们可以根据我们的迭代在 X 序列的哪个四分位数上继续使用预测方法:
for i in xt
if i in condrange1
ypred = predict(regone,i)
end
if i in condrange2
ypred = predict(regtwo,i)
end
if i in condrange3
ypred = predict(regthree,i)
end
if i in condrange4
ypred = predict(regfour,i)
end
append!(e,ypred)
end
return(e)
结果呢
当然,我们已经比较了结果,但如果我们将结果与我们的朋友线性回归进行比较,我们会发现,当关系发生变化时,FourSquare 模型能够发生变化。在某些类型的数据中肯定可以看到好处,包括我最初下载到来看看线性回归的随机数据。
以下是这些模型的可视化效果对比:
Linear Regression
Four-Square
这告诉我们什么?
如我们所见,我们有两条不同的线。如果我们使用线性回归,正如我们在上面看到的,方差较高的区域,也就是更接*底部的区域,完全被排除在方程之外,不会被忽略,但会稍微移动最佳拟合线。通过这个模型,我们得到了一条 4 向量自适应线。数据初始部分的斜率要陡得多,与数组其余部分相对*缓的性质相比,y 截距将直线推到了荒谬的水*。当接*下一个季度的数据时,我们看到预测突然转变。看起来前两个回归模型在一开始就出现了,在*方英尺的价格下降之前,斜率在接*结束时有一个相当大的弯曲。这是因为一次购买更多的土地当然总是更便宜。他们都出现在开始的原因很简单;我们的大部分数据都在那里。我们数据的中位数最有可能在 2000 点左右。
你可能会对自己说“哇,这太棒了,但它确实看起来很像逻辑回归。”虽然它是相似的,但这种模型在技术上是线性的,尽管它实际上是多线性的。
最后
虽然模型会有变化,也许会增加更多的划分,超参数来调整它们等等。我有兴趣听听其他数据科学家对这个模型的想法。
最后,我真的很享受扩展 Julia 包注册表的时光。如果你想通过 Github fork 学习更多知识或为车床做贡献,请点击这里的。我真诚地希望像我一样的其他人会觉得这个包有用。我当然很高兴能继续发展到测试版,甚至更高。
介绍 schrute 软件包:办公室的全部记录
原文:https://towardsdatascience.com/introducing-the-schrute-package-the-entire-transcripts-from-the-office-cfc13fe1e769?source=collection_archive---------26-----------------------
文本数据集的集锦
Github 回购
这是一个只有一件事的软件包:办公室所有剧集的完整副本!(美版)。
使用这个数据集来掌握自然语言处理或文本分析。让我们从茱莉亚·西尔格和大卫·罗宾逊所著的优秀的《用 R 进行文本挖掘的 T4》一书中的几个例子来了解一下这个主题。
首先,从 CRAN 安装软件包:
# install.packages("schrute")
library(schrute)
schrute 包只有一个数据集;将它赋给一个变量
mydata <- schrute::theoffice
看一下格式:
dplyr::glimpse(mydata) #> Observations: 55,130 #> Variables: 7
#> $ index <int> 1, 358, 715, 1072, 1429, 1786, 2143, 2500, 2857... #> $ season <chr> "01", "01", "01", "01", "01", "01", "01", "01",... #> $ episode <chr> "01", "01", "01", "01", "01", "01", "01", "01",...
#> $ episode_name <chr> " Pilot", " Pilot", " Pilot", " Pilot", " Pilot...
#> $ character <chr> "Michael", "Jim", "Michael", "Jim", "Michael", ...
#> $ text <chr> " All right Jim. Your quarterlies look very goo... #> $ text_w_direction <chr> " All right Jim. Your quarterlies look very goo...mydata %>%
dplyr::filter(season == '01') %>%
dplyr::filter(episode == '01') %>%
dplyr::slice(1:3) %>%
knitr::kable()
所以我们有的是季节,集数和名字,人物,说的台词和跟舞台方向(cue)说的台词。
我们可以用 tidytext 包中的几行来标记所有的行:
token.mydata <- mydata %>%
tidytext::unnest_tokens(word, text)
这将我们的数据集增加到 575146 条记录,其中每条记录包含脚本中的一个单词。
token.mydata %>%
dplyr::filter(season == '01') %>%
dplyr::filter(episode == '01') %>%
dplyr::slice(1:3) %>%
knitr::kable()
如果我们想分析整个数据集,我们需要先删除一些停用词:
stop_words <- tidytext::stop_words tidy.token.mydata <- token.mydata %>% dplyr::anti_join(stop_words, by = "word")
然后看看最常见的单词是什么:
tidy.token.mydata %>%
dplyr::count(word, sort = TRUE)
#> # A tibble: 19,225 x 2
#> word n
#> <chr> <int>
#> 1 yeah 2895
#> 2 hey 2189
#> 3 michael 2054
#> 4 dwight 1540
#> 5 uh 1433
#> 6 gonna 1365
#> 7 jim 1345
#> 8 pam 1168
#> 9 time 1129
#> 10 guys 933
#> # ... with 19,215 more rowstidy.token.mydata %>%
dplyr::count(word, sort = TRUE) %>%
dplyr::filter(n > 400) %>%
dplyr::mutate(word = stats::reorder(word, n)) %>% ggplot2::ggplot(ggplot2::aes(word, n)) +
ggplot2::geom_col() +
ggplot2::xlab(NULL) +
ggplot2::coord_flip() +
ggplot2::theme_minimal()
你可以继续这样做。现在你已经有了时间线(剧集,季节)和剧中每一行每一个词的角色,你可以进行无限的分析。一些想法:—逐角色感悟—逐角色感悟—逐季节自恋(咳咳..Nard Dog 第 8-9 季)——角色台词——等等。
原载于 2019 年 12 月 15 日https://technistema.com。
介绍
原文:https://towardsdatascience.com/introducing-theto-1db9bfbb8d69?source=collection_archive---------28-----------------------
设计和数据科学
地理空间数据探索的工作流自动化
我最*开源了一个 Python 库,名为 Theto,用来自动化我的一些工作流程。这篇文章是关于我设计这个工具的过程。如果你只是想跳到工具本身,你可以在这里看到一个演示笔记本。否则,通读帖子,我会在最后发布笔记本和其他资源的链接。
大约一年半以前,我写了一篇关于的文章,这是一个工具的前身,并解释了我在创建这个工具时试图遵循的一些原则。我想在这里展开讨论:在编写和组织代码的过程中,我需要系统地思考我试图实现什么目标,尤其是哪些事情会阻止我实现这些目标,以及我如何以避免这些陷阱的方式进行构建。换句话说,我需要修改工具的设计,而代码的修改是从这项工作中产生的。
加入设计工作使得代码更容易修复和改进,但更重要的是,它让我可以花更多的时间使用工具,而不是维护它。现在的设计比过去好,但这在很大程度上是更好的设计而不是更好的代码的结果。(要更完整地讨论应用于数据科学的设计,请阅读我在这里写的内容)。
所以我想谈谈我经常做的工作,我觉得我需要一个工具来帮助我。然后我想谈谈好的设计原则是如何帮助我组织创建这个工具的。然后,我将介绍一下机器人能做的一些事情。
我的目标:探索地图上的形状(有背景)
我在 Valassis 的大部分工作都与理解移动定位数据有关。当您在地标(建筑物、道路、行政边界、水体等)的背景下查看位置数据时,会更容易理解。将所有的上下文数据转换到一个位置和格式,以便与移动 GPS 信号等进行有意义的比较,这既困难又昂贵。在一张有许多这些背景信号的图片上绘制这些 GPS 信号,然后使用我的人脑来理解一切,这要容易得多。例如:
数据有效性
A few of the parcel shapes we don’t want
当我们能够将位置信号附加到有意义的空间时,我们的客户通常会觉得很有价值。例如,知道一个位置信号是在一个独户住宅或一个家得宝所在的建筑中通常是有用的。背景帮助我们做出更好的决定。为了获得这种背景,我们购买了从城市和县评估办公室、基于卫星图像的图像识别和其他来源获得的地块数据集。
上图左上角显示了一个细分。白线划定了住宅用地。深蓝色的线划分细分。我们的数据不包含区分这两个界限的元数据;较大的边界完全包含所有较小的边界,并且较大的边界没有被较小的形状完全填充—存在间隙。
左下方的图像显示了商店的边界。数据没问题。如果你仔细观察图像的中间,你会看到一个黑色的正方形。那是个垃圾箱。如果你从垃圾箱的左上看得更*,你会看到一个蓝色的形状。据我所知,那是垃圾箱里的包裹。我不知道它为什么会在那里,但它就是在那里。
中间的图像是河流的包裹。有意思,但对我们的生意没什么价值。我也见过这样的情况,城市里的每条路都有一个巨大的包裹。
最右边的图像是错误的。这些包裹甚至不接触他们的建筑,似乎旋转不当。
我构建了识别上述所有条件以及更多条件的过程。在某些情况下,我们会标记它们以便修复它们。在其他情况下,我们标记它们以便我们可以删除它们。在所有情况下,我们根本不知道我们需要修复或删除任何东西,直到我们把形状放在地图上,并理解我们在看什么。
Mobile location data can be wrong in a lot of different ways
形状不是我们业务中唯一有问题的数据。有时位置数据本身是错误的。
比如看左边上图。你可以看到很多橙色的点。这些小点中的大部分都聚集在图像顶部的房子上。如果你仔细看,你甚至可以看到这些点的大部分都在车道后面的房子上,这意味着那个人在上车或下车时更有可能使用他们的手机。看起来车库旁边有一点活动,大概是厨房,然后在房子的另一头有一点,大概是卧室。所有这些都有道理。
现在看图像的底部。在邻居的前院,你可以看到两个大点,实际上是一个在另一个上面。从上下文来看,这些看起来有点奇怪。点的大小反映了一周内在每个位置报告的设备数量:顶部的每个点是由单个设备报告的,而右侧的两个点是由数百个设备报告的。太奇怪了。
我称右边的图片为麦田怪圈。我不知道这是什么。每个方块大致是两个并排的足球场边上的一块土地,但我只展示这些方块,因为你无法同时看到问题的性质和范围。每个正方形本身包含一个完美的网格,每个网格点之间只有几码远。所以每个方块包含几百个网格点。蓝色方块包含一个完整的网格。沿边缘的黄色方块仅包含部分网格。换句话说,有一个巨大的网格。
每个网格点都来自假定的有机移动定位数据。这些数据形成了一个完美的网格,网格点之间的间隔只有几米,它横跨了一个直径约为 2.5 英里的完美圆形。据我所知,美国只有六家这样的公司。其中大部分发生在市中心附*——在阿拉巴马州伯明翰市中心就有一个——但上图中的这个是在俄勒冈州的一块空地上。
每个人都知道手机定位数据不能只看表面。我们需要在很多很多不同的背景下,实际上观察移动位置,以找出哪些信号我们可以相信,哪些不可以。
A couple post-analysis sanity checks
有时我们需要在分析之后而不是之前检查数据。上面的左图显示了当我们重新设计一个为物理位置分配 IP 地址的算法时发生的变化。蓝色表示重新设计导致分配更多 IP 地址的地方。红色表示分配的 IP 数量减少的地方。
右图显示了类似的分析后健全性检查。我们一直在寻找销售类似产品或服务的商店。黑色曲线的宽度显示了我们认为某些商店有多相似。这让我们可以查看商店名称,看看我们是否得到了正确的相似性分数。
算法开发
What makes sense for a county assessor doesn’t make sense for us.
我不仅仅使用可视化来计算我正在处理的数据或结果。我经常用它来迭代我正在构建的算法的不同设计选项。
上图显示了一些宗地数据。左边的图像显示了我们从县评估员那里收到的数据。白线表示不同地块之间的分界线。很明显,那些对角线并没有划分出真正怪异的公寓。查看分配给该建筑的邮寄地址,我们认为县评估员试图找出如何解释该建筑有三个公寓*面图,但有四层。对于我们来说,不知道移动信号在几楼有点问题,但如果它出现在某人的客厅,那么将它分配给一个公寓,如果它出现在他们的卧室,那么将它分配给另一个公寓,这确实是个问题。
因此,我编写了一个过程,从一个地块开始,爬行到相邻的地块,在每个阶段检查不同的度量——例如,查看爬行的总空间有多大。这里没有正确的答案——在某些情况下,很难准确说出正确的组合是什么,即使直视它。我甚至使用可视化来尝试不同的指标:
Screen shot of me trying to undo a county assessor’s good intentions
鉴于我几乎总是处理没有可获得的基本事实来验证模型的问题,我很少开发一种算法而不开发一种方法来可视化该算法的结果。这是另一个例子:
红点是一个企业的位置。我们没有为那家商店(和许多其他喜欢它的商店)留下建筑足迹。因此,我们查看了商店附*的移动设备,并计算出它们还去了附*的其他地方。我们能够利用这一点来对地块进行评分,确定出现在给定地块上的人出现在离商店质心更*的地方的概率。我们能够利用这种概率云来构建一个建筑足迹,不仅捕捉到了商店,还捕捉到了商店前门外的专用停车场。
好的设计产生好的代码
以上所有的例子实际上只是一个简单目的的不同版本:我需要在地图上以一种我可以看到上下文的方式放置形状。这就是我需要一个工具来实现的目的。一个好的设计不应该分散我对那些可能妨碍我实现目标的事情的注意力,而且应该尽量减少我在其他事情上花费的精力。我会回到那一点。
设计是一件有趣的事情。许多好的设计原则适用于你正在设计的任何东西,无论是软件、机器还是建筑:
Vitrivius 是一位罗马设计师,他写了“十本关于建筑的书”,现在通常简称为“建筑论”。在那部作品中,维特鲁威提出了优秀设计的三个品质:
- 有用
- 坚定
- 高兴
前两个是不言自明的——尤其是第一个。一个好的设计应该是有用的,因为它首先实现了一个目的。我经常看到数据科学家,尤其是初级数据科学家,设计复杂的工作流和流程来适应他们想要使用的特定方法,而没有首先确认该方法比(通常更简单的)替代方法更好地实现了分析目的。我自己做过的次数比我愿意承认的要多。
无论你是在建造一栋建筑还是一个软件,你都希望它“坚固”到不容易损坏。实际上,这种品质很难达到。在我自己的经验中,我经常发现我写代码是为了在一定条件下适应某种输入,并提供某种输出。然后输入发生变化,或者我需要不同的输出,或者基础条件发生变化,一切都崩溃了。我重新设计了可视化代码,因为我厌倦了保持相同过程的多个版本,或者每当一个旧的需求重新出现时就搜索旧版本的代码。我之前写的代码不牢。这一目标还有一段路要走,但它已经稳固得多了。
最后一个品质——愉悦——是最不直观的,但在我看来,却是最重要的。在设计建筑时,这个概念更加直观:建筑不应该只是挡雨。应该很好看。但这就提出了一个问题,一个算法或一个软件“看起来不错”意味着什么?
弗雷德里克·布鲁克斯(Frederick Brooks)最出名的可能是写了《人月神话》,并监督了 IBM 的 System/360 系列计算机的设计,这是第一个支持小写字母表示的系统。布鲁克斯已经写了很多关于设计的文章。他认为维特鲁威的快乐概念是一种“逻辑美”。如果一个设计减少了脑力劳动,那么它在逻辑上就是美丽的——它让我们很容易注意到需要我们注意的事情,也很容易忽略甚至完全意识不到那些不需要我们注意的事情。Books 将逻辑美的概念分为三个部分:
- 礼义廉耻。布鲁克斯将此描述为“不要介绍不重要的东西”。我们制造东西是因为我们有任务要完成。任何与完成任务直接相关的事情都适合于该任务。任何不直接相关的东西——如果有必要的话——都是不合适的。一个好的设计应该让适当的任务变得容易,让不适当的任务变得不可见。
- 正交性。布鲁克斯将此描述为“不要链接独立的东西”。我们也可以将其描述为模块化。一个好的设计不应该让设计的不同方面互相依赖,除非它们真的总是需要一起发生。如果他们可以分别快乐,他们应该被建造成彼此独立。
- 共性。布鲁克斯将此描述为“不要限制固有的东西”。一个好的设计不应该为了使用这个设计而一遍又一遍地让人们去做同样的事情。设计应该只是做那件事。
那么,让我们回到作为一名数据科学家,我真正想要完成的事情上来。我的目标:探索地图上的形状以理解背景。不是我的目标:得到形状,得到地图,把形状放在地图上。这些事情都不适合我的任务,尽管它们显然需要发生才能让我完成任务。事实上,当我想得更多的时候,我发现大量的任务是必要的,但并不恰当:
- 存储默认值
- 摄取数据
- 验证数据
- 过程数据
- 追加元数据
- 获取地块大小和边界
- 获取缩放级别
- 检索地图切片
- 项目数据
- 添加形状
- 将数据映射到形状
- 格式化形状
- 连接形状
- 批注形状
- 添加互动
- 设置交互工具
- 添加/格式化图例
- 渲染图
- 重复
一个好的设计应该尽量减少我在上面任何一项任务上花费的脑力。它们应该尽可能高效地发生,尽可能减少我的工作量。这就是得体的原则。
所以现在我们得到了正交性原理。如果我想最大限度地减少我花在上述任务上的注意力,我需要以一种最大限度减少依赖性的方式来组织它们。我需要对任务进行足够的划分,这样,如果一个东西出现故障或未能满足需求,就不会影响到工具的其他部分。有很多方法可以分解这些任务。这是我选择的:
- 设置默认值
- 添加来源
- 添加互动
- 创建绘图
- 添加层
- 渲染图
这些是我与设计的互动点:我不需要对所有那些必要但不恰当的任务做出决定,我只需要做出以上六个决定。这样更省力。
我的最后一个目标是将这六项任务尽可能分开。这就是展示比讲述容易得多的地方。
建筑师可以做的几件事
上面文章中几乎所有的图片都是用这个工具创建的,但是在这里我将介绍所有的主要功能。该工具构建在散景库之上,该库具有一定的内置交互性,例如*移和缩放图形的能力。的其他部分提供了更高级的交互性。Medium 没有提供任何直接嵌入 Javascript 的方法,所以如果你想看到交互式部分,可以向下滚动到文章的底部,点击笔记本的链接。
输入格式
计算器可以自动处理以下类型的输入:
- Geohashes
- 知名正文
- 经度/纬度对
- 匀称的物体
- 乔森
Shapes on maps!
散景能够渲染字形(其中形状的边界映射到实际的地图坐标,因此如果您缩放图像,形状也会放大)和标记(映射到地图上单个点并且无论您如何缩放都保持不变的点或其他形状)。这个工具将接受上面的任何输入,并将它们格式化为一个字形或一个标记——随你怎么想。
这个工具还可以自动追加元数据。您可以将所有想要的数据作为 Pandas dataframe 加载,并指定包含形状的列,或者您可以将形状作为值列表加载,然后通过将元数据作为关键字参数包含在add_source
方法中来追加元数据。您可以加载任意数量的源,并以多种方式渲染单个源。
视觉造型
为形状边框、形状表面或同时为两者指定颜色提供了多种方法:
如果您将单一颜色名称或十六进制颜色代码传递给add_layer
方法,所有形状都将是该颜色。或者传递一个值列表来分别分配给每个形状。如果您在数据源中传递一个列的名称,并且该列包含字符串值,则将自动从分类调色板中分配颜色。(您可以在实例化调色板时指定哪个调色板,但它也有一个缺省值)。如果列包含数值,则将创建一个颜色渐变(包括具有正值和负值的列的中点颜色渐变)。所有的颜色映射都在幕后进行。
还提供了几种地图类型:
只需使用适当的关键字来获得您想要的地图类型。另外,如果在实例化一个 Theto 实例时输入一个 Google API 键,那么可以使用任何 Google Maps 地图类型(“卫星”、“路线图”、“地形”或“混合”)。只是要小心:Bokeh 将 API 键存储在用于渲染图的 Javascript 对象中,因此任何查看您渲染图的页面的源代码的人都可以看到您的 API 键。
这个工具还有一个add_path
方法,可以让你在形状之间添加线条(曲线或直线)。它可以处理一对一的关系来显示从一个位置到另一个位置的旅行,或者处理多对多的关系来显示其他类型的连接。
交互性
正如我之前提到的,由于是建立在散景的基础上的,所以它可以获得一些开箱即用的交互性。除了*移和缩放,你还可以在add_layer
方法中的legend
关键字参数中加入一个标签,这将创建一个图例,点击标签将打开和关闭相关层。
此外,还有一种add_widget
方法,允许更复杂的交互来动态过滤地图上显示的形状:
如何自己使用计算器
如果你只是想开始使用它:
pip install theto
您可以在这里看到所有功能的演示:
[## nbviewer 笔记本
Geohashes 是划分地球表面的长度为 1 到 12 的字符串。该工具将转换这些…
nbviewer.jupyter.org](https://nbviewer.jupyter.org/github/Valassis-Digital-Media/theto/blob/master/theto_demo_notebook.ipynb)
您可以在这里查看代码、文件问题和创建拉取请求:
[## valassis-数字媒体/the
任何可视化都需要大量琐碎的决策,这些决策加起来会对…产生重大影响
github.com](https://github.com/Valassis-Digital-Media/theto)
介绍 tsviz,R Studio 中的交互式时间序列可视化
原文:https://towardsdatascience.com/introducing-tsviz-interactive-time-series-visualization-in-r-studio-a96cde507a14?source=collection_archive---------15-----------------------
我们为什么以及如何开发 R Studio 插件
tsviz logo
上下文:R 数据可视化工具
我们都知道。r 非常适合数据可视化。
Hadley Wickham 的 ggplot2 提供了一个简单而优雅的语法来创建非常有效的图表。此外,万一 ggplot2 不支持一些奇特的图表,R 提供了许多有效的替代方法,如点阵。
在这种场景下,2016 年初,发布了新的包。随着 JavaScript 库的开源发布,R 的 Plotly 在 CRAN 上可用。Plotly 允许创建交互式图表,用户可以缩放,*移,选择数据,并通过悬停在数据点上查看附加信息。
交互性可能只是一个花哨的功能。在学术著作中,数据是已知的,真正重要的是为出版物制作清晰和信息丰富的图表。
但是…
对于从业者来说,交互性是一件大事。它有助于接*数据并获得早期洞察力,从而加快数据探索的整个过程。
毫不奇怪,Plotly 立即获得了成功,随着新功能的增加,它越来越受欢迎,比如与 ggplot2 的集成。
然而,即使是 Plotly 和 ggplot2 也是要付出代价的。
Plotly R package daily downloads. Data from rpackages.io.
动机:寻求早期洞察力
Plotly 和 ggplot2 未能提供一个通用的语法:将纯 plotly 中的图表与用 ggplot2 创建的 plotlified 图形混合在一起是很棘手的。即使有了库的帮助,创建有效的可视化仍然需要时间。
大多数数据科学家喜欢创建图表。图表是我们交流的方式,是分享我们从数据中获得的信息的最有效的语言。
但是,创建图表来共享结果不同于创建图表来浏览和调查数据。
在第一种情况下,我们很乐意在一个数字上花很多时间,但在第二种情况下,我们就不乐意了。我们想尽快获得知识,这样我们可以做出更好的决定,避免危险的误解。
幸运的是,R and R 工作室为这种需求提供了答案。2016 年初,R Studio 宣布支持插件。作为 IDE 的有效扩展,外接程序可能有助于与开发相关的任务,但也为数据分析提供支持。例如,一些加载项简化了数据子集设置,而其他加载项则帮助选择图表的颜色。
因此,为什么不创建一个插件来简化交互式图表的使用呢?
在过去的几个月里,在 xtream 中,我们参与了几个涉及时间序列分析的项目。我们多次重复同样的过程:
- 绘制时间序列
- 检查目标系列和特征之间的散点图
- 建立和分析自相关、偏自相关和周期图
当然,我们构建并使用了函数,但是创建一个脚本或一个 R Markdown 文档来一直使用它们是很乏味的。
因此,我们决定将最有用的功能封装在一个插件中。
创造:站在巨人的肩膀上
由于有很多有用的资源,开发 R Studio 插件的过程非常快。以下是清单:
- 使用这个包:一个易于使用的工具,在 R 包的基础上构建框架并添加元素,比如许可证、测试、CI 配置。
- styler 包:实现 tidyverse 风格导轨的棉绒。它可以通过其插件运行。
- hexSticker package :为包创建六边形标志的工具。
- Hadley Wickham 的 R 包:创建 R 包的严谨而易懂的指南。
- R Studio 关于插件的教程:对于从未创建过插件的开发者来说是一个很棒的资源。
- GitLab 和 GitLab CI:起初,插件托管在 xtream 的私有 GitLab 存储库中。本教程帮助我们配置持续集成管道。
- GitHub 和 Travis CI:社区维护的 Travis 的 R 映像提供了与 GitHub 的无缝 CI 集成。
结果:tsviz
tsviz 是一个 R 包,其中包含 tsviz 插件和一个样本数据集。
您可以通过运行以下命令从曲柄安装 tsviz:
或者可以从 GitHub 下载开发版。确保安装并运行 devtools 包:
安装后,您可以尝试加载项:
您应该能够做这样的事情:
tsviz usage example
tsviz 也可以随时从 R Studio 中的 add-ins 菜单运行:不需要用library()
加载包。
当然,你可以在自己的数据上尝试 tsviz。
启动时,加载项会自动在全球环境中查找合适的数据框。如果满足以下条件,可以使用 tsviz 分析数据帧:
- 它至少有一个类型为
Date
的列 - 它至少有一个
numeric
类型的列
参考
tsviz 在 GitHub 上:https://github.com/xtreamsrl/tsviz。它仍处于早期开发阶段:欢迎每一个反馈或错误报告!
我的读者,感谢你来到这里!
如果你喜欢这篇文章,你可能会感兴趣:
- 真实机器学习项目的经验,第 1 部分:从 Jupyter 到 Luigi
- 真实机器学习项目的经验,第二部分:数据探索的陷阱
如果你对 me 或xtream有什么好奇的话,上领英看看吧!
Xverse 介绍!—用于要素选择和变换的 python 包
原文:https://towardsdatascience.com/introducing-xverse-a-python-package-for-feature-selection-and-transformation-17193cdcd067?source=collection_archive---------3-----------------------
节省数据科学家 80%的时间
Credits: Pixabay
Xverse 是 X Uni verse 的缩写,是一个用于机器学习的 python 包,用于协助数据科学家进行特征转换和特征选择。在我们谈论这个包的细节之前,让我们理解为什么我们需要一个。
背景
Credits: Geeksta
我看到了这张图片,我觉得没有更好的方式来解释这个项目。虽然听起来很有趣,但它发生在数据科学生命周期的大部分时间里。数据科学家 80%的时间花在处理特性(X)上,因此得名 XuniVerse 又名“X verse”。
另外,整个项目是基于我 2018 年在 Medium 上发表的作品。根据我从读者那里得到的反馈,我想改进代码的功能。与其把它作为一个更新的功能发布,我认为把它作为一个 python 包发布会更好。嗯,《xverse》就是这么诞生的。
此包的早期作品
下面显示的文章现在是这个包的一部分。
[## 使用 Python 的证据权重和信息价值
证据权重(WOE)和信息价值(IV)是简单的,但强大的技术来执行可变…
medium.com](https://medium.com/@sundarstyles89/weight-of-evidence-and-information-value-using-python-6f05072e83eb)
“证据权重(WOE)和信息价值(IV)是执行变量转换和选择的简单而强大的技术。这些概念与逻辑回归建模技术有着巨大的联系。它被广泛用于信用评分,以衡量好客户与坏客户的区分。”
[## 使用 Python 的变量选择—基于投票的方法
变量选择是预测建模过程中的关键步骤之一。这是一门艺术。简单来说…
medium.com](https://medium.com/@sundarstyles89/variable-selection-using-python-vote-based-approach-faa42da960f0)
“这个想法是应用各种技术来选择变量。当一个算法选择一个变量时,我们给这个变量投票。最后,我们计算每个变量的总投票数,然后根据投票选出最佳变量。这样,我们就能在变量选择过程中以最少的努力挑选出最好的变量。”
功能
[## Sundar0989/XuniVerse
xverse (XuniVerse)是用于特征工程和特征选择的转换器的集合
github.com](https://github.com/Sundar0989/XuniVerse)
下面显示的所有示例使用的数据集都在“data”文件夹中。此外,您可以参考此链接中的 Jupyter 笔记本代码“Xverse.ipynb”。
1.单调宁滨
单调宁滨是记分卡开发中广泛使用的数据准备技术。它试图通过创建与目标具有单调关系的箱来将数值变量转换为分类变量。下面给出的例子将演示它是如何工作的。
Balance vs Target (Monotonic Relationship)
上面显示的特征“余额”的范围从$3,313.001 到$71,188。我们都同意这是一个非常广泛的范围。如果我们必须基于领域知识绑定这个变量,那么我们就不必担心单调关系。然而,当没有先验知识存在时,则很难确定容器类别。这是一个理想的情况,单调宁滨可以帮助。
它从 20 个箱开始(默认值,可以随时更改),然后减少箱数,直到发现 X 变量和目标 y 之间的单调关系(增加或减少)。如果它没有建立单调关系,则使用 force_bins 选项强制在 X 变量上创建箱数。一直以来,它使用 斯皮尔曼相关 来验证 X 和 y 变量之间是否存在单调关系。
单调宁滨的优点:
- 处理异常值
- 在特征和目标变量之间建立单调关系
单调宁滨的缺点:
- 在可变宁滨期间,我们会丢失信息
- 没有处理缺失值的正确方法
如何用“Xverse”演奏单调的宁滨?
from xverse.transformer import MonotonicBinning
clf = MonotonicBinning()
clf.fit(X, y)
print(clf.bins)
output_bins = clf.bins *#will be used later in this exercise*
这里 X 表示特征数据集,它是一个熊猫数据框架,y 是目标列的 numpy 数组。我们还可以使用预计算的单调条柱应用于新数据集,如下所示。
clf = MonotonicBinning(custom_binning=output_bins) *#output_bins was created earlier*
out_X = clf.transform(X)
out_X.head()
2.证据权重和信息价值
WOE 包在 transformer 函数中可用。WOE 转换的优点是
- 处理缺失值
- 处理异常值
- 该变换基于分布的对数值。这与逻辑回归输出函数一致
- 不需要虚拟变量
- 通过使用适当的宁滨技术,可以在自变量和因变量之间建立单调关系(增加或减少)
- IV 值可用于快速选择变量。
计算 WOE 和 IV 的公式如下。
或者简单地说,
如何使用“Xverse”执行 WOE?
from xverse.transformer import WOEclf = WOE()
clf.fit(X, y)**clf.woe_df # weight of evidence transformation dataset. This dataset will be used in making bivariate charts as well.** clf.iv_df #information value dataset
要选择功能,请使用下面的规则
+-------------------+-----------------------------+
| Information Value | Variable Predictiveness |
+-------------------+-----------------------------+
| Less than 0.02 | Not useful for prediction |
+-------------------+-----------------------------+
| 0.02 to 0.1 | Weak predictive Power |
+-------------------+-----------------------------+
| 0.1 to 0.3 | Medium predictive Power |
+-------------------+-----------------------------+
| 0.3 to 0.5 | Strong predictive Power |
+-------------------+-----------------------------+
| >0.5 | Suspicious Predictive Power |
+-------------------+-----------------------------+
要基于之前计算的 WOE bins 转换变量 X,请使用下面的代码。
clf.transform(X) #apply WOE transformation on the dataset
如何在未来数据集上应用 WOE 转换?
output_woe_bins = clf.woe_bins #future transformation
output_mono_bins = clf.mono_custom_binning #future transformationclf = WOE(woe_bins=output_woe_bins, mono_custom_binning=output_mono_bins) #output_bins was created earlierout_X = clf.transform(X)
WOE 包中可探索的其他功能:
*treat_missing: {‘separate’, ‘mode’, ‘least_frequent’} (default=’separate’)**This parameter setting is used to handle missing values in the dataset.
‘separate’ — Missing values are treated as a own group (category)
‘mode’ — Missing values are combined with the highest frequent item in the dataset
‘least_frequent’ — Missing values are combined with the least frequent item in the dataset*
3.二元分布的条形图
二元分布帮助我们探索 X 和 y 变量之间的关系。这个选项在“xverse”中也是可用的。
如何使用“Xverse”制作图表?
为了制作二元图表,我们需要从上面显示的 woe 选项生成的“WOE _ df”数据集。
woe_df = clf.woe_dffrom xverse.graph import BarCharts
clf = BarCharts(bar_type='v')
clf.plot(woe_df)
要在条形图中探索的其他功能:
*plot_metric: 'count' or 'mean' (default='mean')
Metric to be used while plotting the bivariate chart.
'count' - Event counts in the particular bin
'mean' - Mean event rate in the particular bin**bar_type: 'horizontal' or 'vertical' (default='vertical')
Type of bar chart.**fig_size: figure size for each of the individual plots (default=(8,6))**bar_color: CSS color style picker. Use it with the hashtag in the front. (default='#058caa')
Bar color
num_color: CSS color style picker. Use it with the hashtag in the front (default='#ed8549')
Numbers color. It represents the numbers written on top of the bar.*
4.变量选择的投票选择器
变量选择是预测建模过程中的关键过程之一。这是一门艺术。简单地说,变量选择就像挑选一支足球队赢得世界杯。你需要在每个位置都有最好的球员,你不希望两个或多个球员踢同一个位置。
在 python 中,我们有不同的技术来选择变量。其中一些包括递归特征消除、基于树的选择和基于 L1 的特征选择。
这里的想法是应用各种技术来选择变量。当一个算法选择一个变量时,我们给这个变量投票。最后,我们计算每个变量的总票数,然后根据投票选出最好的变量。这样,我们就可以在变量选择过程中以最小的努力挑选出最好的变量。
from xverse.ensemble import VotingSelectorclf = VotingSelector()
clf.fit(X, y)
现在,让我们用下面的代码来看看特性的重要性。
clf.feature_importances_
clf.feature_votes_
clf.transform(X).head()
投票选择器中可探索的其他功能:
*selection_techniques: 'all', 'quick' or list(default='all')
List of selection techniques to be applied on the data.
Available techniques - Weight of evidence ('WOE'), Random Forest ('RF'), Recursive Feature Elimination ('RFE'), Extra Trees Classifier ('ETC'), Chi Square ('CS'), L1 feature selection ('L_ONE').
'all' - Apply all selection techniques ['WOE', 'RF', 'RFE', 'ETC', 'CS', 'L_ONE']
'quick' - ['WOE','RF','ETC']
list - user provided list of feature selection techniques from available techniques
no_of_featues: 'auto', 'sqrt' or int(default='auto')
Number of features to be selected by each selection technique.
'auto' - len(features)/2
'sqrt' - sqrt(len(features)) rounded to the lowest number
int - user provided number in integer format
handle_category= 'woe' or 'le' (default='woe')
Handle category values transformation using Label encoder or Weight of Evidence option. Takes care of missing values too. It treats missing values as separate level.
'woe' - use weight of evidence transformation
'le' - use label encoder transformation
numerical_missing_values= 'median', 'mean' or 0 (default='median')
Handle numerical variable missing values.
'median' - use median of the column
'mean' - use mean of the column
0 - use 0 to impute the missing values
minimum_votes = int (default=0)
Minimum number of votes needed to select a variable after feature selection. Only used in the transform process. Default value is set to 0 to select all variables.*
5.管道特征
最后,关于“Xverse”的一件重要事情是管道功能。我们可以将所有步骤作为流水线的一部分,让我们的生活变得更加轻松。
下面的代码展示了管道特性。
from sklearn.pipeline import Pipelineclf = Pipeline(steps=[('split_x_y', SplitXY(['target'])),('feature_votes', VotingSelector())])
clf.fit(df, df['target'])
最后,为了在新的数据集上进行转换,
clf.transform(df)
为 Xverse 做贡献
XuniVerse 正在积极开发中,如果你想参与其中,我们欢迎你的加入。请在这篇文章中留下回应,我们可以谈论下一步。
代码在这里的一个笔记本中给出,供您在自己的数据集上进行实验。
[## Sundar0989/XuniVerse
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Sundar0989/XuniVerse/blob/master/Xverse.ipynb)
玩得开心!
分层聚类简介
原文:https://towardsdatascience.com/introduction-hierarchical-clustering-d3066c6b560e?source=collection_archive---------7-----------------------
揭示 R 州级人口统计数据的结构
聚类试图通过创建具有相似特征的数据分组来发现数据中的结构。最著名的聚类算法可能是 K-means,但是有许多方法可以对观察值进行聚类。分层聚类是一类可生成 1 到 n 个聚类的聚类算法,其中 n 是数据集中的观察值数量。当您从 1 个分类(包含所有数据)到 n 个分类(每个观察值都是自己的分类)时,分类会变得越来越相似(几乎总是如此)。有两种类型的层次聚类:分裂型(自上而下)和聚集型(自下而上)。
分裂的
分裂式层次聚类从包含整个数据集的 1 个聚类开始工作。具有最高*均不相似性的观察值(离聚类最远的某个度量)被重新分配给它自己的聚类。旧聚类中更靠*新聚类的任何观测值都被分配给新聚类。对最大的聚类重复这个过程,直到每个观察值都是它自己的聚类。
结块的
凝聚聚类从每个观察值作为自己的聚类开始。两个最接*的集群被结合成一个集群。下一个最接*的聚类被分组在一起,并且该过程继续,直到只有一个聚类包含整个数据集。
亲*是什么意思?
在上一节中,我忽略了定义“接*”是什么意思。有各种可能的度量标准,但我将列出 4 个最受欢迎的:单连接、完全连接、*均连接和质心连接。
单连杆机构
单链(最*邻)是两个聚类中一对观测值之间的最短距离。它有时可以生成这样的聚类,其中不同聚类中的观测值比它们自己的聚类中的观测值更接*。这些集群可能看起来很分散。
完全连锁
完全关联(最远邻居)是两个聚类中最远的一对观察值之间的距离。这种方法通常会产生比单一链接更紧密的集群,但是这些紧密的集群最终可能会非常紧密。与*均链接一起,它是更受欢迎的距离度量之一。
*均连锁
*均关联是指将每个聚类中每对观察值之间的距离相加,然后除以对的数量,以获得*均聚类间距离。*均连接和完全连接是层次聚类中两种最流行的距离度量。
质心连杆
质心连接是两个簇的质心之间的距离。当质心随着新的观测值移动时,较小的星团可能更类似于新的较大的星团,而不是它们各自的星团,这导致了树状图中的反转。这个问题在其他链接方法中不会出现,因为被合并的聚类总是更类似于它们自己,而不是新的更大的聚类。
在 R 州级人口统计数据上使用层次聚类
在我们对美国各州进行分类时,地区的概念非常重要。区域是由地理定义的州的集群,但是地理导致了州之间额外的经济、人口和文化相似性。例如,佛罗里达州南部非常靠*古巴,这使得它成为古巴难民通过海路前往美国的主要目的地。因此,南佛罗里达是古巴裔美国人最集中的地方。
为了研究今天(实际上是在 2017 年)各州之间的相似程度,我下载了包含 2017 年美国社区调查信息的数据,并使用分层聚类对它们进行分组。数据集有许多变量,所以我使用了“特征向量分解,这是一个来自量子力学的概念,以梳理“人口统计数据”中重叠的“笔记”(我知道我迟到了,但我必须告诉大家,我也上过线性代数课)。生成的树状图(带有 R 代码)如下。
完全链接的凝聚层次聚类
HC . complete = hclust(dist(PC . state . full $ x[,1:5]),method='complete ')
plot(hc.complete,labels = X_state$State,main= '使用 2017 年 ACS 数据的区域聚类的树状图(聚合)',xlab= ' ',sub= ' ',cex=0.7)
Dendrogram created using Agglomerative Hierarchical Clustering with Complete Linkage on 2017 ACS data’s first 5 principal components
分裂层次聚类
库(集群)
div.hc = diana(pc.state.full\(x[,1:5],diss = inherits(pc.state.full\)x[,1:5]," dist "),metric = "euclidean ")
plot(div.hc,labels = X_state$State,,main= '使用 2017 年 ACS 数据的区域聚类的树状图(divide)',xlab= ' ')
Dendrogram created using Divisive Hierarchical Clustering on 2017 ACS data’s first 5 principal components
聚集和分裂方法产生的集群之间存在一些差异。聚集法将乔治亚州和北卡罗来纳州与伊利诺伊州、特拉华州、宾夕法尼亚州和罗德岛州归为一组,而分裂法将它们与南俄亥俄州、密歇根州、密苏里州和印第安纳州归为一组。大体上,它们是相同的,这是我们所期望的。
从这些树状图中有一些发现:
弗吉尼亚离大西洋中部比离南部更*
-阿拉斯加最靠*上*原州(农村、白人、土著人口相对较多)
-俄亥俄州、密歇根州、密苏里州和印第安纳州比其他中西部州更靠*南方
-夏威夷州和 DC 与其他州非常不同
我希望您学到了一些新东西,并看到了在 R 中实现这些技术是多么容易。 hclust() 在 base R 中可用,而 diana() 在集群库中。
我的数据和代码可以在这里找到。
强化学习中的演员评论介绍
原文:https://towardsdatascience.com/introduction-to-actor-critic-7642bdb2b3d2?source=collection_archive---------10-----------------------
直观的方法理解强化学习中最重要的方法之一。
Photo by Fatih Kılıç on Unsplash
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
概观
在深入探讨演员评论家的细节之前,让我们提醒自己一下政策梯度。
基于策略的强化学习意味着什么?简单地说,想象一个机器人发现自己处于某种状况,但这种状况似乎与它以前经历过的事情相似。
因此,基于策略的方法说:既然我过去在这种特定情况下采取了行动 (a) ,那么让我们这次也尝试同样的行动。
PS。不要把相似的情况和相同的状态混为一谈,在相似的情况下,机器人或智能体处于一些新的状态,类似于它以前经历过的,而不一定是完全相同的状态。
Left: The robot faces a barrier, but he has seen something like that before and it knows what to do in this situation. Middle: The robot took the same action it took in such situation. Right: The robot is wondering hindsight if there were more efficient way to overcome the barrier.
在上面的图像中,一个机器人面对着一个壁垒,但它似乎以前见过这种情况,所以像以前一样,它用火箭跳过它。
然而,这一次可能不是完美的行动!
可能发生的情况是,有一个简单的触发器来打开门,从而节省宝贵的能量,这些能量可能在以后被使用。
基于这个概念,机器人必须做一些回顾性的回顾,以检查那个动作(使用他的火箭)有多有用。
现在我们需要把它转化成一个数学方程。
目标
请记住,我们的目标是始终获得最高的回报。
为了能够做到这一点,我们必须定义一个收集这些奖励的函数,并对其进行优化,以最大化这些奖励。
另一个同样重要的点是,我们将使用神经网络来完成这项工作。
所以我们要做的是找到神经网络的一组权重𝜽,帮助我们最大化目标函数。
重要!注意以下陷阱:如果你熟悉深度学习和神经网络,你更习惯于寻找使误差最小的权重。在这种情况下,我们不这样做,相反,我们希望最大化一个目标函数。意识不到这一点会让你陷入困惑。
从基于政策的梯度中,我们找到了一个目标函数,并按如下方式计算其梯度(有关该等式如何形成的详细信息,请查看政策梯度逐步):
J(𝜽)是依赖于𝜽的目标函数
m 是执行的情节(这里称为轨迹)的数量
𝛑是由𝜽参数化的政策,这意味着当𝜽变化时,政策将受到影响。请记住,策略给出了当代理处于特定状态时采取特定操作的概率。
𝞽ⁱ是执行的第 I 集或轨迹。
R(𝞽ⁱ)是轨迹𝞽ⁱ.的回报(总报酬)
T 是轨迹𝞽ⁱ.的步数
这个方程告诉我们的是,J(𝜽的梯度是所有 m 个轨迹的*均值,其中每个轨迹是组成它的步骤的总和。在每一步,我们计算保单𝛑对数的导数,并将其乘以回报 R(𝞽ⁱ).
换句话说,我们正试图找出𝜽.之后政策的变化返回 R(𝞽ⁱ的使用)是为了放大(或减小)这些变化。这意味着如果 R(𝞽ⁱ)很高,它将提高结果,并使神经网络确信𝜽在正确的方向上前进。
然而,返回 R(𝞽ⁱ).有一个问题
退货问题
假设我们在一个轨迹中,早期的回报是负的,而接*轨迹末端的回报是正的,这样总 R = 0!
在这种情况下,∇J(𝜽)将为 0,并且神经网络将不会从这种情况中学习𝜽的任何新值。
为了解决这个问题,我们在每一步都使用了折扣奖励,从当前状态开始,直到轨迹结束。
这将给我们一个新版本的∇J(𝜽):
现在神经网络将能够从轨迹中学习。还有更大的改进空间,但我们需要做更多的数学计算。
数学来了
如果我们深入思考呢?
Rt(从步骤 t 开始返回)还不错,但是我们不确定 Rt 的值是多少,好到可以考虑?!
以文章开头的机器人为例,使用火箭跳跃是一个好的解决方案吗?我们怎么知道?有多好?
同样,如果你拿 100 米短跑运动员 10 秒的成绩举例,他做得好还是不好?如果它是好的,那么它有多好?
赋予这个数字意义的一种方法是将其与一个参考值进行比较,或者我们称之为基线。
基线可以有几种形式,其中一种是预期绩效,或者说是*均绩效。如果短跑运动员得了 10 分,但*均分是 12 分,那么他做得很好,相反,如果*均分是 8 分,那么他做得很差。
让我们将基线表示为 b 𝑡,目标函数的梯度变为:
现在让我们想一想,R𝑡是在步骤 t 采取行动 的回报,另一方面 b 𝑡代表所有行动结果的*均值。
这看起来很奇怪地类似于 Q(s,a)是在状态采取的行动的值,以及 V(s)是状态的值,或者是在状态采取的所有行动(引起的)的*均值。****
该等式可以改写为
如果我们仔细观察上面的等式,我们会看到𝛑(a|s)是执行动作的(记住𝛑是动作的概率是在状态时获得的),而 Q(s,a)-V(s)告诉我们它有多有价值。****
换句话说,𝛑(a|s 是演员,Q(s,a)-V(s)是评论家。
批评家的计算可以有不同的味道:
- 演员兼评论家
- 优势演员兼评论家
- TD 演员兼评论家
- 演员兼评论家
- 天生的演员兼评论家
相关文章
- 政策梯度循序渐进
- 强化学习中的函数逼*
- 基于策略的强化学习
使用 Python3 介绍 AWS Lambda、Layers 和 boto3
原文:https://towardsdatascience.com/introduction-to-amazon-lambda-layers-and-boto3-using-python3-39bd390add17?source=collection_archive---------1-----------------------
面向数据科学家的无服务器方法
Photo by Daniel Eledut on Unsplash
Amazon Lambda 可能是当今最著名的无服务器服务,提供低成本,几乎不需要云基础设施治理。它提供了一个相对简单明了的*台,用于在不同的语言上实现功能,比如 Python、Node.js、Java、C#等等。
亚马逊 Lambda 可以通过 AWS 控制台或者 AWS 命令行界面进行测试。Lambda 的一个主要问题是,一旦函数和触发器变得更复杂,设置起来就变得很棘手。本文的目标是向您展示一个易于理解的教程,让您用外部库配置第一个 Amazon Lambda 函数,并做一些比打印“Hello world!”更有用的事情。
我们将使用 Python3、boto3 和 Lambda 层中加载的其他一些库来帮助我们实现我们的目标,将 CSV 文件加载为 Pandas 数据帧,进行一些数据辩论,并将报告文件中的指标和图表保存在 S3 存储桶中。虽然使用 AWS 控制台来配置您的服务不是在云上工作的最佳实践方法,但我们将展示使用控制台的每个步骤,因为这对初学者来说更便于理解 Amazon Lambda 的基本结构。我相信在阅读完这篇教程之后,你会对将部分本地数据分析管道迁移到 Amazon Lambda 有一个很好的想法。
设置我们的环境
在我们开始使用 Amazon Lambda 之前,我们应该首先设置我们的工作环境。我们首先使用 conda (也可以使用 pipenv )(2)为项目(1)和环境 Python 3.7 创建一个文件夹。接下来,我们创建两个文件夹,一个保存 Lambda 函数的 python 脚本,另一个构建 Lambda 层(3)。我们将在本文后面更好地解释 Lambda 层的组成。最后,我们可以创建文件夹结构来构建 Lambda 层,这样它就可以被 Amazon Lambda (4)识别。我们创建的文件夹结构将帮助您更好地理解 Amazon Lambda 背后的概念,并组织您的函数和库。
# 1) Create project folder
**mkdir medium-lambda-tutorial**# Change directory
**cd medium-lambda-tutorial/**# 2) Create environment using conda **conda create --name lambda-tutorial python=3.7
conda activate lambda-tutorial**# 3) Create one folder for the layers and another for the
# lambda_function itself
**mkdir lambda_function lambda_layers**# 4) Create the folder structure to build your lambda layer
**mkdir -p lambda_layers/python/lib/python3.7/site-packages
tree** .
├── lambda_function
└── lambda_layers
└── python
└── lib
└── python3.7
└── site-packages
亚马逊 Lambda 基本结构
在尝试实现我的第一个 Lambda 函数时,我遇到的一个主要问题是试图理解 AWS 调用脚本和加载库所使用的文件结构。如果您按照默认选项“从头开始创作”(图 1)来创建 Lambda 函数,那么您最终会得到一个文件夹,其中包含您的函数名称和名为 lambda_function.py 的 Python 脚本。
Figure 1. Creating a Lambda function using Author from scratch mode.
lambda_function.py 文件结构非常简单,代码如下:
import jsondef lambda_handler(event, context):
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
这 8 行代码是理解 Amazon Lambda 的关键,所以我们将逐行解释它。
import json
:你可以导入 Python 模块在你的函数上使用,AWS 为你提供了一个已经在 Amazon Lambda 上构建的可用 Python 库的列表,比如json
等等。当你需要不可用的库时,问题就出现了(我们稍后将使用 Lambda 层来解决这个问题)。def lambda_handler(event, context):
这是主函数当你运行服务时,你的 Amazon Lambda 会调用这个函数。它有两个参数event
和context
。第一个用于传递可以在函数本身上使用的数据(稍后将详细介绍),第二个用于提供运行时和元数据信息。- 这里就是奇迹发生的地方!您可以使用
lambda_handler
函数的主体来实现任何您想要的 Python 代码。 return
函数的这一部分将返回一个默认字典,其中statusCode
等于 200,而body
则返回一个“Hello from Lambda”。您可以在以后将这个返回更改为任何适合您需要的 Python 对象。
在运行我们的第一个测试之前,有必要解释一下与 Amazon Lambda 相关的一个关键话题: 触发器 。触发器基本上是调用 Lambda 函数的方式。有很多方法可以使用事件来设置触发器,比如将文件添加到 S3 桶,更改 DynamoDB 表上的值,或者通过 Amazon API Gateway 使用 HTTP 请求。你可以很好地集成你的 Lambda 函数,以供各种各样的 AWS 服务调用,这可能是 Lambda 提供的优势之一。我们可以这样做来与你的 Python 代码集成的一个方法是使用 boto3 来调用你的 Lambda 函数,这是我们将在本教程后面使用的方法。
正如您所看到的,AWS 提供的模板结构非常简单,您可以通过配置一个测试事件并运行它来测试它(图 2)。
Figure 2. Running your first Amazon Lambda test.
由于我们没有对 Lambda 函数的代码做任何修改,测试运行了这个过程,我们收到了一个绿色的警告,描述了成功的事件(图 3)。
Figure 3. A successful call of our Lambda Function.
图 3 展示了 Lambda 调用结果的布局。在上面部分,您可以看到返回语句中包含的字典。下面是摘要部分,我们可以看到一些与 Lambda 函数相关的重要指标,如请求 ID、函数持续时间、计费持续时间以及配置和使用的内存量。我们不会深入讨论 Amazon Lambda 定价,但重要的是要知道它的收费依据是:
- 功能运行的持续时间(四舍五入到最接*的 100 毫秒)
- 使用的内存/CPU 数量
- 请求的数量(调用函数的次数)
- 进出 Lambda 的数据传输量
总的来说,测试和使用它真的很便宜,所以在小工作负载下使用 Amazon Lambda 时,您可能不会有计费问题。
与定价和性能相关的另一个重要细节是 CPU 和内存的可用性。您选择运行您的函数的内存量,并且“ Lambda 与配置的内存量成比例地线性分配 CPU 能力”。
在图 3 的底部,您可以看到日志输出会话,在这里您可以检查 Lambda 函数打印的所有执行行。在 Amazon Lambda 上实现的一个很棒的特性是它与 Amazon CloudWatch 集成在一起,在那里你可以找到你的 Lambda 函数生成的所有日志。关于监控执行和日志的更多细节,请参考 Casey Dunham great Lambda 文章。
我们已经介绍了 Amazon Lambda 的基本功能,因此在接下来的几节课中,我们将增加任务的复杂性,向您展示一个真实世界的使用,提供一些关于如何在日常基础上运行无服务器服务的见解。
增加层次,拓展可能性
使用 Python 的一个好处是可以获得大量的库,帮助您实现快速解决方案,而不必从头开始编写所有的类和函数。如前所述,Amazon Lambda 提供了一个 Python 库列表,您可以将其导入到您的函数中。当您不得不使用不可用的库时,问题就出现了。一种方法是将这个库安装在你的lambda_function.py
文件所在的文件夹中,压缩这些文件,然后上传到你的 Amazon Lambda 控制台。在本地安装库并在每次创建新的 Lambda 函数时上传库,这个过程可能是一项费力且不方便的任务。为了让您的生活更轻松,亚马逊为我们提供了将我们的库作为 Lambda 层上传的可能性,它由一个文件结构组成,您可以在其中存储库,将其独立加载到 Amazon Lambda,并在需要时在您的代码中使用它们。一旦你创建了一个 Lambda 层,它可以被任何其他新的 Lambda 函数使用。
回到我们组织工作环境的第一个会话,我们将使用在lambda_layer
文件夹中创建的文件夹结构在本地安装一个 Python 库 Pandas。
# Our current folder structure
.
├── lambda_function
└── lambda_layers
└── python
└── lib
└── python3.7
└── site-packages# 1) Pip install Pandas and Matplotlib locally
**pip install pandas -t lambda_layers/python/lib/python3.7/site-packages/.**# 2) Zip the lambda_layers folder
**cd lambda_layers**
**zip -r pandas_lambda_layer.zip ***
通过使用带参数-t
的pip
,我们可以指定要在本地文件夹(1)上安装库的位置。接下来,我们只需要压缩包含库(2)的文件夹,我们就有了一个准备作为层部署的文件。保持我们在开始时创建的文件夹的结构(python/lib/python 3.7/site-packages/)是很重要的,这样 Amazon Layer 就可以识别您的压缩包中包含的库。点击 AWS Lambda 控制台左侧面板上的“层”选项,然后点击“创建层”按钮创建一个新层。然后我们可以指定名称、描述和兼容的运行时(在我们的例子中是 Python 3.7)。最后,我们上传我们的压缩文件夹并创建层(图 4)。
Figure 4. Creating a Lambda Layer.
这花了不到一分钟的时间,我们的 Amazon 层已经准备好用于我们的代码了。回到 Lambda 函数的控制台,我们可以通过点击图层图标,然后点击“添加图层”(图 5)来指定要使用的图层。
Figure 5. Adding a layer to a Lambda function.
接下来,我们选择我们刚刚创建的层及其各自的版本(图 6)。从图 6 中可以看出,AWS 提供了一个 Lambda 层,其中包含随时可以使用的 Scipy 和 Numpy,因此如果您只需要这两个库中的一个,就不需要创建新的层。
Figure 6. Selecting our new Pandas Layer.
选择我们的熊猫层后,我们需要做的就是把它导入你的 Lambda 代码,因为它是一个已安装的库。
最后,我们开始编码吧!
现在我们已经准备好了环境和熊猫层,我们可以开始编写代码了。如前所述,我们的目标是创建一个 Python3 本地脚本(1),它可以使用定义的参数(2)调用 Lambda 函数,在位于 S3 (3)上的 CSV 上使用 Pandas 执行简单的数据分析,并将结果保存回同一个桶(4)(图 7)。
要让 Amazon Lambda 访问我们的 S3 存储桶,我们只需在控制台上的会话 执行角色 中添加一个角色。尽管 AWS 为您提供了一些角色模板,但我的建议是在 IAM 控制台上创建一个新的角色,以准确地指定 Lambda 函数所需的权限(图 8 的左侧面板)。
Figure 8. Defining the role and basic settings for Lambda function.
我们还将可用内存量从 128MB 更改为 1024MB,并将超时时间从 3 秒更改为 5 分钟(图 8 中的右图),以避免内存不足和超时错误。亚马逊 Lambda 限制RAM 内存总量为 3GB,超时为 15 分钟。因此,如果您需要执行高度密集的任务,您可能会发现问题。一种解决方案是将多个 Lambdas 链接到其他 AWS 服务,以执行分析管道的步骤。我们的想法不是对 Amazon Lambda 进行详尽的介绍,所以如果你想了解更多,请查看这篇来自艾毅的文章。
在展示代码之前,描述我们将在小项目中使用的数据集是很重要的。我选择了来自 Kaggle 的 Fifa19 球员数据集,这是一个 CSV 文件,描述了游戏中出现的球员的所有技能(表 1)。它有 18.207 行和 88 列,你可以从每个球员那里得到国籍,俱乐部,薪水,技能水*和更多的信息。我们下载了 CSV 文件,并上传到我们的 S3 桶(重命名为 fifa19_kaggle.csv )。
Table 1. The fifa19_kaggle.csv 20 first rows.
所以现在我们可以专注于我们的代码了!
正如我们在上面的脚本中看到的,前 5 行只是导入库。除了熊猫,其他所有的库都可以使用,而不必使用层。
接下来,我们有一个名为write_dataframe_to_csv_on_s3
(第 8 到 22 行)的附属函数,用于将熊猫数据帧保存到一个特定的 S3 桶中。我们将使用它来保存在分析过程中创建的输出数据帧。
我们代码中的另一个函数是 main lambda_handler,
,当我们调用 Lambda 时,这个函数将被调用。我们可以看到,lambda_handler
上的前 5 个赋值(第 28 到 32 行)是传递给event
对象的变量。
从第 35 行到第 41 行,我们使用 boto3 下载 s 3 存储桶上的 CSV 文件,并将其作为熊猫数据帧加载。
接下来,在第 44 行,我们使用 Dataframe 上的 group by 方法来聚合GROUP
列,并获得COLUMN
变量的*均值。
最后,我们使用函数write_dataframe_to_csv_on_s3
在指定的 S3 桶上保存df_groupby
,并返回一个以 statusCode 和 body 为键的字典。
正如之前在 Amazon Lambda 基本结构会话中所描述的,事件参数是一个对象,它携带了可用于lambda_handler
函数的变量,我们可以在配置测试事件时定义这些变量(图 9)。
Figure 9. Defining the variables on the test event.
如果我们运行这个测试,使用与测试 JSON 的 5 个键相关的正确值,我们的 Lambda 函数应该处理来自 S3 的 CSV 文件,并将结果 CSV 写回到桶中。
尽管在测试事件中使用硬编码的变量可以展示我们的 Lambda 代码的概念,但这不是调用函数的实际方法。为了解决这个问题,我们将创建一个 Python 脚本(invoke_lambda.py
)来使用 boto3 调用我们的 Lambda 函数。
我们将只使用三个库: boto3 、 json 和 sys 。从第 5 行到第 10 行,当通过命令行运行脚本时,我们使用sys.argv
来访问参数。
**python3 invoke_lambda.py <bucket> <csv_file> <output_file> <groupby_column> <avg_column> <aws_credentials>**
我们提供给invoke_lambda.py
的最后一个参数(aws_credentials)是一个 JSON 文件,其中包含我们访问 aws 服务的凭证。您可以使用 awscli 配置您的凭证,或者使用 IAM 生成密钥。
在我们的主函数invoke_lambda
中,我们使用 boto3 客户端来定义对 Amazon Lambda 的访问(第 38 行)。下一个名为payload
的对象是一个字典,包含了我们想要在 Lambda 函数中使用的所有变量。这些是可以使用event.get('variable').
访问的 Lambda 变量
最后,我们简单地用目标 Lambda 函数名、调用类型和携带变量的有效负载来调用client.invoke()
(第 54 行)。调用类型有三种 : 请求响应(默认)、到同步调用函数。保持连接打开,直到函数返回响应或超时";事件,异步调用 Lambda 或者当您需要验证用户信息时 DryRun 。对于我们的主要目的,我们将使用默认的 RequestResponse 选项来调用我们的 Lambda,因为它等待 Lambda 流程返回响应。由于我们在 Lambda 函数上定义了一个 try/except 结构,如果流程运行时没有错误,它将返回一个状态代码 200,并显示消息“Success!”,否则它将返回状态代码 400 和消息“错误,错误的请求!”。
当使用正确的参数运行时,我们的本地脚本invoke_lambda.py
需要几秒钟才能返回响应。如果响应是肯定的,状态代码为 200,那么您可以检查您的 S3 存储桶来搜索由 Lambda 函数生成的报告文件(表 2)。当我们使用“俱乐部”和“总体”两列进行分组以获得*均值时,我们显示了*均玩家总体技能水*最高的 20 个俱乐部。
Table 2. The first 20 rows of the output CSV file generated using our Lambda function.
最终考虑
希望这个快速介绍(没那么快!)帮助你更好地理解这种无服务器服务的具体细节。它可以帮助您在数据科学项目中尝试不同的方法。有关使用 AWS 的无服务器架构的更多信息,请查看 Eduardo Romero 的这篇精彩文章。
如果你觉得你需要更深入地了解 AWS Lambda,我最*发表了一篇文章,描述了 Lambda 背后的基础设施和它的一些其他功能。
非常感谢你阅读我的文章!
- 你可以在我的个人资料页面 找到我的其他文章🔬
- 如果你喜欢它并且想成为中级会员,你可以使用我的 推荐链接 来支持我👍
更多资源
** [## 为什么需要 Python 环境以及如何使用 Conda-protostar . space 管理它们
我不应该只安装最新的 Python 版本吗?
medium.com](https://medium.com/@gergoszerovay/why-you-need-python-environments-and-how-to-manage-them-with-conda-protostar-space-cf823c510f5d) [## 使用 Python 的 AWS Lambda:完全入门指南
在这篇文章中,我们将了解什么是亚马逊网络服务(AWS) Lambda,以及为什么它可能是一个好主意,用于您的…
stackify.com](https://stackify.com/aws-lambda-with-python-a-complete-getting-started-guide/) [## 用 AWS S3 兰巴和 DynamoDB 构建无服务器数据管道
AWS Lambda plus Layers 是管理数据管道和实现无服务器管理的最佳解决方案之一
medium.com](https://medium.com/hackernoon/build-a-serverless-data-pipeline-with-aws-s3-lamba-and-dynamodb-5ecb8c3ed23e) [## 无服务器架构模式
构建在 AWS 无服务器堆栈之上的云架构模式。
medium.com](https://medium.com/@eduardoromero/serverless-architectural-patterns-261d8743020) [## 深入探究 AWS Lambda
了解 Lambda 的基本基础设施,如何运行可执行文件和解析 CloudWatch 日志
towardsdatascience.com](/diving-deeper-into-aws-lambda-a52b22866767)**
Scala Apache Spark 简介
原文:https://towardsdatascience.com/introduction-to-apache-spark-with-scala-ed31d8300fe4?source=collection_archive---------4-----------------------
本文是 3 月份 Scala-Lagos 会议的后续笔记,在该会议上,我们讨论了 Apache Spark、它的功能和用例,以及一个简单的例子,其中 Scala API 用于 Tweets 上的样本数据处理。它旨在很好地介绍 Apache Spark 的优势以及这些优势背后的理论。
Spark——一个包罗万象的数据处理*台
“如果有一个收获的话,那就是小赢也没什么。小胜是好事,他们会复合。如果你做得对,最终结果将是巨大的。”—安迪·约翰斯
Apache Spark 是一个高度开发的引擎,用于在数千个并行计算引擎上进行大规模数据处理。这允许最大化这些计算引擎的处理器能力。Spark 能够处理多种数据处理任务,包括复杂的数据分析、流分析、图形分析以及对大量数据进行可扩展的机器学习,这些数据的数量级为 TB、Zettabytes 等等。
Apache Spark 的成功得益于其开发背后的基本理念,即打破 MapReduce 的限制,MapReduce 是 Hadoop 的一个关键组件,迄今为止,其处理能力和分析能力比 MapReduce 好几个数量级,100 倍,并且具有内存处理能力的优势,因为它能够将其数据保存在计算引擎的内存(RAM)中,并对存储在内存中的数据进行数据处理,从而消除了从磁盘写入/读取数据的连续输入/输出(I/O)需求。
为了有效地做到这一点,Spark 依赖于使用一种称为弹性分布式数据集(RDD) 的专门数据模型,它可以有效地存储在内存中,并允许各种类型的操作。RDD 是不可变的,即存储在内存中的数据项的只读格式,并且有效地分布在机器集群中,人们可以将 RDD 视为原始数据格式(如 String、Int)的数据抽象,这使得 Spark 可以很好地工作。
除了 RDD,Spark 还利用直接无环图(DAG)来跟踪 rdd 上的计算,这种方法通过利用作业流来适当分配性能优化来优化数据处理,这还有一个额外的优势,即通过有效的回滚机制帮助 Spark 在作业或操作失败时管理错误。因此,在出现错误的情况下,Spark 不需要从头开始计算,它可以很容易地利用错误之前计算的 RDD,并通过固定操作传递它。这就是 Spark 被指定为容错处理引擎的原因。
Spark 还利用集群管理器在一个机器集群上正确地运行它的作业,集群管理器以一种主-工的方式帮助分配资源和调度作业。主设备为集群中的工人分配作业和必要的资源,并协调工人的活动,以便在工人不可用的情况下,将作业重新分配给另一个工人。
凭借使用 RDD 抽象、DAG 计算范式、资源分配和集群管理器调度的内存处理理念,Spark 已成为快速大数据处理领域不断进步的引擎。
星火数据处理能力。
使用基本 SQL 进行复杂分析的结构化 SQL
Apache Spark 一个众所周知的功能是,它允许数据科学家轻松地以类似 SQL 的格式对大量数据进行分析。利用 spark-core 内部和底层 RDD 上的抽象,spark 提供了所谓的 DataFrames,这是一种将关系处理与 Spark 的函数式编程 API 集成在一起的抽象。这是通过使用具有列名的模式向数据添加结构信息以向数据提供半结构或完整结构来实现的,并且通过这种方式,可以使用列名直接查询数据集,从而为数据处理打开了另一个级别。
从 Spark 1.6 版开始,结构化 SQL API 提供了数据集 API,它为 Spark-core 的低级 RDD 提供了类似 SQL 的高级功能。从字面上看,数据集 API 是一种抽象,它通过使用优化的 SQL 执行引擎为 spark RDD 提供了 SQL 感觉和执行优化,同时也不会失去 RDD 附带的功能操作。数据集 API 和数据帧 API 都构成了结构化 SQL API。
用于实时分析的火花流
Spark 还提供了一个扩展,通过以离散流的形式提供底层 RDD 的抽象,可以轻松地操作流数据。使用底层 RDD Spark 内核有两个主要优势;它允许 Spark 的其他核心功能在流数据上得到利用,并有利于可以在 rdd 上执行的数据核心操作。
离散化数据流是指实时小批量获得的 RDD 数据。
用于预测建模的 MLLib/ML 机器学习
Spark 还通过提供机器学习算法、数据特征化算法和流水线功能来提供机器学习功能,这些功能经过优化,可以在大量数据上进行扩展。Spark 机器学习库的目标概括如下:
让实用的机器学习变得可扩展和简单。
GraphX 图形处理引擎。
第四种数据处理能力是其固有的对图形数据进行分析的能力,例如在社交网络分析中。Spark 的 GraphX API 是 ETL 处理操作和图形算法的集合,针对数据的大规模实现进行了优化。
初始化火花
根据使用情况,有多种方法可以初始化 Spark 应用程序,应用程序可以利用 RDD、Spark 流、带有数据集或数据帧的结构化 SQL。因此,理解如何初始化这些不同的 Spark 实例非常重要。
- RDD 与星火语境:
spark-core 的操作是通过创建一个 spark context 来启动的,该 context 是通过许多配置来创建的,例如主位置、应用程序名称、执行器的内存大小等等。
这里有两种启动 spark 上下文的方法,以及如何使用创建的 spark 上下文创建 RDD。
2。带 Spark 会话的数据帧/数据集:
如上所述,Spark 的入口点可能是通过使用 Spark 上下文,然而,Spark 允许通过 Spark 会话与结构化 SQL API 直接交互。它还包括指定 Spark 应用程序的配置。
下面是启动 Spark 会话并使用该会话创建数据集和数据帧的方法。
3。带火花流的数据流:
Spark 的另一个入口点是在与实时数据交互时使用流上下文。流式上下文的实例可以从 Spark 配置或 Spark 上下文中创建。如下所示
对 RDD、数据集和数据帧的操作
已经很好地了解了 spark 的功能,展示一些可以应用于各种 Spark 抽象的操作是很重要的。
1。RDD
RDD 是 spark 的主要抽象,也是 Spark 核心的核心,它有两个基本操作。
转换 —转换操作应用于现有的 RDD,以创建新的和已更改的 rdd。这种操作例子包括 映射过滤 和 *面映射 等等。spark 中转换操作的完整列表可以在这里找到
一旦 spark 上下文用于创建 RDD,这些操作就可以应用于 RDD,如下面的代码示例所示。值得注意的是,这些操作是延迟计算的,因为它们在应用操作之前不会被直接计算。
动作 —动作操作触发 Spark 中的实际计算,它驱动计算向驱动程序返回值。动作操作的思想是将集群中的所有计算返回给驱动程序,以产生一个实际数据类型的单一结果,而不是 spark 的 RDD 抽象。启动动作操作时必须小心,因为驱动程序有足够的内存来管理这些数据是很重要的。动作操作的例子包括 【减少】收集取 等等。完整列表可在这里找到
2。数据集/数据帧
如前所述,数据集是结构化 SQL 的类似 RDD 的优化抽象,既允许 SQL 中的关系操作,也允许函数操作,如 映射 、 过滤 和许多其他类似的操作,这些操作在 RDD 中都是可能的。需要强调的是,并不是所有的 DataFrame 类似 SQL 的功能都完全适用于 Dataset,但是有许多基于列的函数仍然非常适用于 Dataset。此外,在特定于领域的对象中编码数据集还有一个额外的优势,即把数据集映射到一个类型 T 这有助于扩展 Spark Dataset 可能实现的功能,还增加了执行强大的λ操作的能力。
Spark DataFrame 可以进一步视为以命名列组织的数据集,并呈现为一个等效的关系表,您可以使用类似 SQL 的查询甚至 HQL。因此,在 Spark DataFrame 上,执行任何类似 SQL 的操作,例如 SELECT COLUMN-NAME 、 GROUPBY 和 COUNT 等等变得相对容易。关于 Spark DataFrame 的另一个有趣的事情是,这些操作可以使用任何可用的 spark APIs 以编程方式完成——Java、Scala、Python 或 R,以及将 DataFrame 转换为一个临时 SQL 表,在该表中可以执行纯 SQL 查询。
结论。
总结一下 Spark 的介绍,一个示例 scala 应用 tweets 上的字数统计是提供的,它是在 scala API 中开发的。该应用程序可以在您喜欢的 IDE 中运行,如 InteliJ 或笔记本电脑,如 Databricks 或 Apache Zeppelin。
在本文中,涵盖了一些要点:
- Spark 作为下一代数据处理引擎的描述
- 赋予 spark 能力的非延迟技术
- Spark 中存在的数据处理 API
- 关于如何使用数据处理 API 的知识
- 体验 spark 处理能力的一个简单例子。
本文原载 此处
人工神经网络导论——解释、公式和推导
原文:https://towardsdatascience.com/introduction-to-artificial-neural-networks-5036081137bb?source=collection_archive---------19-----------------------
Photo by Billy Huynh on Unsplash
神经网络处于机器学习的前沿。他们正在接受训练,以完成各种可以想象的任务。通过这篇文章,我们试图看看神经网络的公式,推导。我们也着眼于神经网络学习的实际方面。
来自生物学的动机
大脑是我们身体中支持学习的重要组成部分。它有大约 100 亿个相互连接的神经元。一个神经元从它的突触接收来自其他神经元的输入。输入发生总和,当总和超过特定阈值时,神经元通过轴突向另一个神经元发送电尖峰。
感知器
P erceptron 是机器学习中用于二元分类器监督学习的算法,即确定输入向量所属类别的函数。
可以写成:
走向神经网络
基本的人工神经网络是感知器的自然扩展。我们可以说,一个基本的神经网络是一个多层感知器,称为前馈神经网络。它将包含:
- 隐藏层
- 偏差单位
- 神经元(输入、输出和感知器)
- 突触权重
- 激活功能
前馈神经网络
任何神经网络的目标都是估计一个函数 f,该函数对给定的一组输入给出一组输出的估计。
上面提到的神经网络被称为前馈,因为没有输出反馈给输入(不同于递归神经网络)。
输入时间权重,添加偏差并激活
我们可以说:
where f is the activation function
我们可以进一步说:
where nH represents the number of perceptrons in the hidden layer & w0 are the bias units.
因此,输出神经元 z 可以导出为:
但是人工神经网络是怎么学习的呢?
对于每个神经网络,我们都有一个与其预测相关的成本函数。我们称这个成本函数为损失函数。该损失函数将根据输入和隐藏权重进行优化。现在,我们可以计算关于每个权重的成本函数偏导数,并更新最优成本函数的权重。
注意:在这种方法中,我们将单个输入样本多次(等于权重的数量)传递给神经网络,用于计算和优化单个输入的所有权重。这在计算上非常昂贵。
反向传播是来拯救我们的
Geoff Hinton 于 1986 年在其 论文 中提出了反向传播。当时它被高度低估,但后来逐渐成为前馈神经网络的主干。
本质上,反向传播只是链式法则的一个巧妙应用。
反向传播使我们能够在一次反向传递中计算每个重量的偏导数。我们可以说:
where J(w) represents the loss function, c = total number of output & t is the given output and z is the predicted output.
我们可以说:
where eta is the learning rate.
类似地,对于其他重量,
在我们获得由于后向传递中的误差函数(误差函数中每个权重的贡献)引起的权重变化之后,我们可以如下更新它们:
我们可以通过 随机梯度下降 或其变体反向传播来计算权重。
反向传播的实际问题
激活功能
激活函数的主要目的是将输入信号转换为神经网络中某一节点的输出信号。没有激活函数的神经网络只是一个线性回归模型。因此,为了学习复杂的非线性曲线,我们需要激活函数。
激活函数应遵循的属性:
- 非线性为了生成非线性输入映射,我们需要一个非线性激活函数。
- 饱和一个饱和的激活函数挤压输入,把输出放在一个有限的范围内;因此,没有一个重量会对最终输出产生显著影响。
- 连续和*滑对于基于梯度的优化,更*滑的函数通常显示出更好的结果。因为输入取连续范围,所以输出也应该取节点的连续范围。
- 可微正如我们在推导 f 的反向传播导数时所看到的,应该定义。
- 单调如果激活函数不是单调递增的,则神经元的权重可能会使其影响较小,反之亦然;这与我们想要的正好相反。
- 对于小值是线性的如果对于小值是非线性的,我们需要在神经网络的权重初始化时考虑约束,因为我们可能会面临消失梯度或爆炸梯度的问题。
消失和爆炸渐变
V
正如我们之前讨论的,饱和激活函数将输入压缩到一个小值,因此输入的显著变化将导致输出的小变化,因此导数更小。
ReLU 是一个没有消失梯度问题的激活函数。大多数深度学习模型都以此为激活函数。
但是如果你仍然坚持使用 tanh 或 sigmoid,你可以选择批量标准化。它只是把输入保持在导数不小的绿色区域。
E 在极端情况下,权重值可能会溢出,从而导致 NaN 权重。因此,这些 NaN 权重不能被进一步更新,导致学习过程停止。
有许多方法来处理爆炸式渐变,如渐变剪辑(如果范数超过特定阈值则剪辑渐变)和权重正则化(对大权重值的损失函数进行惩罚)。
损失函数
成本函数或损失函数本质上计算神经网络输出和目标变量之间的 差 。它们可以分为三种分类:
回归损失函数:当目标变量为连续回归损失函数时使用。最常用的是均方差。其他名称包括绝对误差和*滑绝对误差。
分类损失函数:当输出变量是一个类的概率时,我们使用分类损失函数。大多数分类损失函数倾向于最大限度地增加利润。著名的名字包括分类交叉熵,负对数似然,边缘分类器。
嵌入损失函数:当我们必须测量两个或多个输入之间的相似性时,我们使用嵌入损失函数。一些广泛使用的嵌入损失函数是 L1 铰链误差和余弦误差。
优化算法
优化算法负责更新神经网络的权重和偏差,以减少损失。它们可以主要分为两类:
恒定学习率算法:其中学习率 η 对于所有参数和权重都是固定的。最常见的例子是随机梯度下降。
自适应学习率算法:Adam 等自适应优化器具有每参数学习率方法,该方法提供了更直接的启发式方法,而不是手动处理超参数。
以上让你开始学习神经网络。保持文章简短,我将在后续文章中讨论 CNN 和 RNN。请关注此空间了解更多信息。
上一篇: 人工智能中的统计方法介绍
参考
- https://machine learning mastery . com/expanding-gradients-in-neural-networks/
- https://medium . com/data-science-group-iitr/loss-functions-and-optimization-algorithms-demystified-bb 92 daff 331 c
- https://towards data science . com/the-vanishing-gradient-problem-69 BF 08 b 15484
增强随机搜索简介。
原文:https://towardsdatascience.com/introduction-to-augmented-random-search-d8d7b55309bd?source=collection_archive---------10-----------------------
让 MuJoCo 学习快速有趣的方法
Photo by jean wimmerlin on Unsplash
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
本文基于加州大学伯克利分校的 Horia Mania、Aurelia Guy 和 Benjamin Recht 于 2018 年 3 月发表的一篇论文。
作者声称,他们已经建立了一种算法,在 MuJoCo 运动基准上,该算法比最快的竞争对手无模型方法至少高效 15 倍。
他们将这种算法命名为增强随机搜索,简称 ARS。
问题是
正如在每个 RL 问题中一样,目标是找到一个策略来最大化代理在给定环境中遵循该策略时可能获得的期望回报。
方法
本文提出的解决方案是增强一种称为基本随机搜索的现有算法。
基本随机搜索
基本随机搜索的想法是挑选一个参数化的政策𝜋𝜃,通过对所有𝜹应用+𝛎𝜹和-𝛎𝜹(其中𝛎< 1 is a constant noise and 𝜹 is a random number generate from a normal distribution).
Then apply the actions based on 𝜋(𝜃+𝛎𝜹) and 𝜋(𝜃-𝛎𝜹) then collect the rewards r(𝜃+𝛎𝜹) and r(𝜃-𝛎𝜹) resulting from those actions.
Now that we have the rewards of the perturbed 𝜃, compute the average
δ= 1/n *σ[r(𝜃+𝛎𝜹)-r(𝜃-𝛎𝜹)]𝜹来冲击(或扰动)参数𝜃,并且我们使用δ和学习率来更新参数。𝜃ʲ⁺=𝜃ʲ+𝝰.δ
增强随机搜索(ARS)
ARS 是 BRS 的改进版本,它包含三个方面的增强功能,使其性能更高。
除以标准偏差𝞼ᵣ
随着迭代的进行,r(𝜃+𝛎𝜹和 r(𝜃-𝛎𝜹之间的差异可以显著变化,学习率𝝰固定,更新𝜃ʲ⁺=𝜃ʲ+𝝰.δ可能大幅振荡。例如,如果𝝰 = 0.01,δ= 10,那么𝝰.δ就是 0.1,但是如果δ变成 1000,𝝰.δ就变成 10。这种残酷的变化伤害了更新。请记住,我们的目标是让𝜃向回报最大化的价值观靠拢。
为了避免这种类型的差异,我们将𝝰.δ除以𝞼ᵣ(所收集奖励的标准差)。
使状态正常化
国家的正常化确保政策对国家的不同组成部分给予同等的重视。例如,假设一个状态分量取值范围为[90,100],而另一个状态分量取值范围为[1,1]。然后,第一个状态分量将支配计算,而第二个不会有任何影响。为了获得一个直觉,考虑一个简单的*均值,假设 C1 = 91,C2 = 1,*均值将是(C1 + C2) / 2 = 92 / 2 = 46。现在假设 C2 急剧下降到最小值,C2 = -1。*均值将是(91–1)/2 = 45。
注意,相对于 C2 的大幅下降,它几乎没有移动。
现在让我们使用规范化。对于 C1 = 91,NC1 =(91–90)/(100–90)= 0.1,
对于 C2 = 1,NC2 = (1 - (-1))/(1-(-1)) = 2/2 =1。
归一化*均值将为(0.1 + 1)/2 = 0.55。
现在如果 C2 下降到-1,NC2 = (-1-(-1))/2 = 0,归一化的*均值变成(0.1 + 0)/2 = 0.05。
如你所见,*均值受到了 C2 急剧变化的极大影响。
ARS 中使用的标准化技术包括从状态输入中减去状态的当前观察*均值,然后除以状态的标准偏差:
(state _ input-state _ observed _ average)/state _ STD
使用最佳表现方向
记住我们的目标是最大化收集到的奖励是很有用的。然而,我们在每次迭代中计算*均奖励,这意味着在每次迭代中,我们在𝜋(𝜃+𝛎𝜹和𝜋(𝜃-𝛎𝜹之后计算 2N 集,然后我们对所有 2N 集收集的奖励 r(𝜃+𝛎𝜹和 r(𝜃-𝛎𝜹进行*均。这就带来了一些隐患,因为如果一些奖励相对于其他奖励来说很小,它们就会压低*均值。
解决这个问题的一个方法是根据 max(r(𝜃+𝛎𝜹、r(𝜃-𝛎𝜹)).键将奖励按降序排列然后只使用排名前的 b 和的奖励(以及它们各自的摄𝜹)来计算*均奖励。
注意,当 b = N 时,算法将与没有此增强的算法相同。
例如,假设我们有以下扰动及其各自的回报,如下表所列。
我们按照键 max([r(𝜹i)、r(-𝜹i)])的降序对表进行排序,结果如下表所示:
我们假设 b = 3,那么我们在*均计算中考虑这些数字:
【𝜹9,r(𝜹9】,r(-𝜹9)],【𝜹5,r(𝜹5】,r(-𝜹5)],【𝜹1,r(𝜹1】,r(-1)]
ARS 算法
最后,ARS 算法变成:
简单来说,它会变成如下形式:
Let 𝛎 a positive constant < 1
Let 𝝰 be the learning rate
Let N the number of perturbations
Let 𝜃 a (p x n) matrix representing the parameters of the policy 𝜋
Let 𝜹i a (p x n) matrix representing the ith perturbation1\. While end condition not satisfied do:
2\. Generate N perturbations 𝜹 from a normal distribution
3\. Normalize 𝜋i+ = (𝜃+𝛎𝜹i)ᵀx and 𝜋i- = (𝜃-𝛎𝜹i)ᵀx for i = 1 to N
4\. Generate 2N episodes and their 2N rewards using 𝜋i+ and 𝜋i- and collect the rewards ri+ and ri-
5\. Sort all 𝜹 by max(ri+, ri-)
6\. Update 𝜃 = 𝜃 + (𝝰/(b*𝞼ᵣ)) Σ(ri+ - ri-)𝜹i (where i = 1 to b)
7\. End While
实施和演示
下面是标准的 ARS 实现,很容易在互联网上找到。
运行代码将产生不同的学习阶段。
在最初的几次迭代之后
在第 100 次迭代之后
在第 300 次迭代之后
AWS EC2 和数据科学中的命令行简介
原文:https://towardsdatascience.com/introduction-to-aws-ec2-and-the-command-line-in-data-science-6de2a9aa8d8e?source=collection_archive---------11-----------------------
这个帖子的灵感来自于一个从来没有听说过命令行的朋友。这并不令人惊讶,因为我大约两年前才开始。现在,我每天都用它。
数据科学中最重要的工具之一是命令行(同义短语包括终端、shell、控制台、命令提示符、Bash)。尤其是在使用亚马逊网络服务(AWS)和弹性计算云(EC2)时,熟悉命令行是一个必须做的事情。
你可能会问,“为什么我不能用我自己的电脑呢?”答案很简单——随着数据量的增加,仅靠 8 或 16 GB 的 RAM 处理数 TB 的数据变得不可能。使用 AWS 可以在处理大数据时实现可扩展性。你不再使用的一台本地计算机,而是可能使用云上的 40 台计算机,这一概念被称为并行处理。简而言之(一语双关),你是在付钱给亚马逊借他们的电脑。
命令行的目的是与计算机(本地或远程)及其文件系统进行交互。它提供了一个纯文本界面(是的,不再需要点击)来为你的操作系统运行提供命令。
一些使用案例:
- 读取、写入、编辑、查找、移动、复制、删除、下载文件
- Git/Github
- 基本数据探索/操作
- 登录到远程计算机,也称为 SSH-ing(安全外壳)
- 观看《星球大战》(打开终端,输入 telnet towel.blinkenlights.nl)
一些危险用例:
- 拒绝服务(DoS)攻击
- 黑客攻击和窃取人们的信息
Source: https://xkcd.com/196/
本教程旨在给出一个简短的介绍,首先是 AWS EC2 入门(我们将使用自由层规范),然后是在命令行上使用的重要语法。
AWS 入门
首先要做的是去https://aws.amazon.com/创建一个账户。然后,按照这个简短的 GIF。
Launching an AWS instance
喝杯咖啡,等一两分钟,让 AWS 实例启动。一旦准备好,它应该显示正在运行。
EC2 Management Console
注意右下角的公共 DNS (IPv4)。
打开您的终端,键入以下命令:
chmod 400 <<name_of_pem_file>>
ssh -i <name_of_pem_file> [ubuntu@<<](mailto:ubuntu@ec2-54-213-153-185.us-west-2.compute.amazonaws.com)Public DNS (IPv4)>>
例如,我会键入:
chmod 400 chris_medium.pem
ssh -i "chris_medium.pem" ubuntu@ec2-54-213-153-185.us-west-2.compute.amazonaws.com
Inside an AWS instance
Source: https://xkcd.com/908/
恭喜你!您现在已经准备好在 AWS 上开始云计算了。
命令行入门
现在您已经进入了 AWS 实例,您需要知道如何通过终端输入文本命令来提供指令。
让我们从古腾堡计划中抓取一些文本(《傲慢与偏见》,简·奥斯汀)开始:http://www.gutenberg.org/files/1342/1342-0.txt
wget: 从网站下载文件
wget [http://www.gutenberg.org/files/1342/1342-0.txt](http://www.gutenberg.org/files/1342/1342-0.txt)
ls: 列出当前工作目录下的文件
当输入 ls 时,您的终端应该显示一个名为1342-0.txt
的文件。
前缀为的文件。是隐藏的文件。参数-a
将显示它们。有些参数是必选的,而有些像-a
是可选的。
男人: 查看命令手册页
键入man ls
(或者 help 前面加两个连字符,由于某种原因 Medium 不断将两个连字符转换成长破折号)将为您提供每个参数的信息。多个参数可以通过连续输入来完成,例如,ls -ltr
将以一个长列表的格式显示你的文件,并按修改时间排序,最早的条目最先出现。
头: 打印前 10 行
尾: 打印最后 10 行
你在屏幕上看到的被称为标准输出。让我们将三个命令合并成一个。
猫: 打印文件的内容
|: 将一个命令的输出作为输入传递给另一个命令的管道运算符
WC:字数
首先,文本内容将被打印到标准输出。然后,标准输出将被传递给wc
命令,该命令将提供文件的行数、字数和字符数。
mv: 移动文件(可以用来重命名)
mkdir: 创建目录/文件夹
cp :复制一个文件
rm :删除一个文件
光盘: 更改目录
让我们将文本文件重命名为pride_and_prejudice
,创建一个名为books
的目录,将pride_and_prejudice
文件复制到books
。
mv 1342-0.txt pride_and_prejudice
mkdir books
cp pride_and_prejudice books/
grep: 基于模式的过滤器
> : 将标准输出写入一个文件(如果已有同名文件则覆盖)
>>:将标准输出追加到文件末尾
触摸: 创建空文件
回显: 打印消息到标准输出
- 让我们将包含单词“happy”的所有行存储到一个名为 happy.txt 的文件中。
- 接下来,让我们将包含单词“sad”的所有行存储到一个名为 sad.txt 的文件中
- 然后,创建一个名为 subset 的空文件,并将这两个文件组合在一起。
- 在子集的末尾添加一条消息,说明“完成!”
cat pride_and_prejudice | grep happy > happy.txt
cat pride_and_prejudice | grep -sw sad > sad.txt
touch subset
cat *.txt >> subset
echo "Finished" >> subset
在第二行中,使用了可选参数-sw
,这样 dis sad vantage 这样的词也不会被捕获。您可以使用星号*
对所有以扩展名.txt
结尾的文件执行操作。
假设您的任务是从古腾堡项目网站下载 100 个文件(书籍 1000–1099 ),并将文件名更改为书名。这似乎是一个非常单调的任务,但是使用命令行,只用几行就可以完成!
我们需要学习如何做循环。
Source: https://www.cyberciti.biz/faq/bash-for-loop/
for i in 1 2 3 4 5
do
echo "Hi Person $i"
done
输出将是:
Hi Person 1
Hi Person 2
Hi Person 3
Hi Person 4
Hi Person 5
一个稍微复杂一点的例子:
for i in $( ls )
do
echo file: $i
done
输出将是:
file: books
file: happy.txt
file: pride_and_prejudice
file: sad.txt
file: subset
$
使您能够在另一个命令中使用一个命令。
从古腾堡网站上看,这些文件将会是http://www.gutenberg.org/files/1/1-0.txt或http://www.gutenberg.org/files/1/1.txt(它们的文件名中是否有-0
并不一致。
考虑到这两种情况,我们可以使用||
命令,如果第一个命令失败,它将只触发第二个命令。
tr: 翻译一个字符(使用-d 会删除字符)
代码如下(一步一步的细节可以在下面看到):
mkdir gutenberg
cd gutenbergfor i in {1000..1099}
do
wget -O file "[http://www.gutenberg.org/files/$i/$i.txt](http://www.gutenberg.org/files/2/2.txt)" ||
wget -O file "[http://www.gutenberg.org/files/$i/$i-0.txt](http://www.gutenberg.org/files/2/2-0.txt)"
name=$(cat file | head -n 1 | tr -cd "[:alnum:][:space:]")
name="${name/$'\r'/}"
mkdir "$i"
mv file "$i/$name"
done
键入ls
应该会得到这样的结果:
要查看文件夹中的文件,您可以使用ls -R
:
创建一个名为 gutenberg 的文件夹,并将目录更改为该文件夹
mkdir gutenberg
cd gutenberg
开始 for 循环,其中 I 将是一个从 1000 到 1099(包括 1000 和 1099)的数字
for i in {1000..1099}
do
参数-O
会将文件重命名为名称file
。它将首先尝试下载<number>.txt
,如果失败,它将尝试<number>-0.txt
。
wget -O file "[http://www.gutenberg.org/files/$i/$i.txt](http://www.gutenberg.org/files/2/2.txt)" ||
wget -O file "[http://www.gutenberg.org/files/$i/$i-0.txt](http://www.gutenberg.org/files/2/2-0.txt)"
这将获取文本文件,检索第一行(标题所在的位置),只保留字母数字和空格,并将字符串存储为一个名为name
的变量。[:alnum:]
和[:space:]
分别是字母数字和空白的字符集。下一行将删除剩余的奇怪的、bash 特有的字符,例如将'The Project Gutenberg EBook of the Riverman by Stewart Edward White'$'\r'
转换为'The Project Gutenberg EBook of the Riverman by Stewart Edward White'
。这使用了变量替换、的概念,并使用了以下语法:${parameter//patern/string}
。在这一部分中,/string
组件是空的,所以它不用任何东西替换\r
。
name=$(cat file | head -n 1 | tr -cd "[:alnum:][:space:]")
name="${name/$'\r'/}"
最后一部分将通过创建一个具有适当编号的文件夹并将文件移动到其中来结束 for 循环。
mkdir "$i"
mv file "$i/$name"
done
结论
本教程中还有许多我没有涉及到的工具,它们也被广泛使用。其中包括:
- Git/Github
- 精力
- Bash 脚本
- Bash 配置文件
感谢您的阅读!这是我的第一篇博文——欢迎留下评论,提供任何建设性的反馈。你也可以建议我将来写的主题。我会试着每周发一次帖子。
回溯测试交易策略简介
原文:https://towardsdatascience.com/introduction-to-backtesting-trading-strategies-7afae611a35e?source=collection_archive---------6-----------------------
Source: pixabay
学习如何使用zipline
建立和回溯测试交易策略
在这篇文章中,我想继续量化金融系列。在第一篇文章中,我描述了资产回报的程式化事实。现在,我将介绍回溯测试交易策略的概念,以及如何使用 Python 中现有的框架进行回溯测试。
什么是回溯测试?
先说交易策略。它可以被定义为一种在市场上购买和/或出售资产的方法(基于预先定义的规则)。这些规则可以基于例如技术分析或机器学习模型。
回溯测试基本上是根据历史数据评估交易策略的表现——如果我们在过去对一组资产使用了给定的策略,它的表现会有多好/多差。当然,不能保证过去的表现能代表未来的表现,但是我们仍然可以调查!
Python 中有一些可用的回测框架,在本文中,我决定使用zipline
。
为什么是zipline
?
zipline
环境提供的一些不错的特性包括:
- 易用性——有一个清晰的结构来说明如何构建回溯测试以及我们可以预期的结果,所以大部分时间可以花在开发最先进的交易策略上:)
- 现实—包括交易成本、滑点、订单延迟等。
- 基于流—单独处理每个事件,从而避免前瞻偏差
- 它附带了许多易于使用的统计方法,如移动*均、线性回归等。—无需从头开始编写代码
- 与 PyData 生态系统集成—
zipline
使用 Pandas 数据帧存储输入数据和性能指标 - 很容易将其他库,如
matplotlib
、scipy
、statsmodels
和sklearn
集成到构建和评估策略的工作流中 - 由 Quantopian 开发和更新,为
zipline
、历史数据甚至实时交易功能提供网络界面
我相信这些论点不言自明。开始编码吧!
使用conda
设置虚拟环境
安装zipline
最方便的方法是使用虚拟环境。在本文中,我使用conda
来实现这一点。我用 Python 3.5 创建了一个新环境(我在使用 3.6 或 3.7 时遇到了问题),然后安装了zipline
。也可以pip install
一下。
# create new virtual environment
conda create -n env_zipline python=3.5# activate it
conda activate env_zipline# install zipline
conda install -c Quantopian zipline
为了一切正常工作,你还应该安装jupyter
和本文中使用的其他软件包(见下面的watermark
)。
导入库
首先,我们需要使用%load_ext
魔法加载 IPython 扩展。
%load_ext watermark
%load_ext zipline
然后我们导入其余的库:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import zipline
from yahoofinancials import YahooFinancials
import warningsplt.style.use('seaborn')
plt.rcParams['figure.figsize'] = [16, 9]
plt.rcParams['figure.dpi'] = 200
warnings.simplefilter(action='ignore', category=FutureWarning)
下面您可以看到本文中使用的库列表,以及它们的版本。
导入自定义数据
zipline
准备好从 Quandl(维基数据库)下载的数据。您始终可以通过运行以下命令来检查已经接收的数据:
!zipline bundles
这种方法的问题是,在 2018 年年中,数据被中断,因此没有去年的数据。为了克服这一点,我展示了如何手动接收来自任何来源的数据。为此,我使用了yahoofinancials
库。为了加载到zipline
中,数据必须是 CSV 文件和预定义的格式——就像数据帧预览中的格式。
然后,我们需要将数据作为 CSV 文件保存在名为“daily”的文件夹中(或者您选择的另一个文件夹)。
df.to_csv('daily/aapl.csv', header=True, index=False)
在下一步中,我们需要修改位于 zipline 目录中的extension.py
文件。安装完zipline
后,它是空的,我们需要添加以下内容:
我们还可以为数据接收脚本定义并提供一个定制的日历——例如在处理欧洲股票时。有关如何操作的详细信息,请查看文档。
与数据下载函数相反,我们需要传递下载数据的确切日期范围。在本例中,我们从2017-01-03
开始,因为这是我们获得定价数据的第一天。
最后,我们运行以下命令:
!zipline ingest -b apple-prices-2017-2019
我们可以验证捆绑包是否被成功摄取:
!zipline bundles
下载基准数据有一个已知问题,所以——目前——我们坚持使用默认包中的历史数据。但是,您现在知道了如何使用自定 CSV 文件摄取数据。
有关如何使用csvdir
包加载自定义数据的详细信息,请参考这篇文章,其中我展示了如何导入欧洲股票数据并在此基础上运行基本策略。
买入并持有策略
我们从最基本的策略开始——买入并持有。这个想法是,我们购买某项资产,在整个投资期限内不做任何事情。这个简单的策略也可以被认为是更高级策略的基准——因为使用一个非常复杂的策略比购买和什么都不做产生更少的钱(例如由于交易成本)是没有意义的。
在这个例子中,我们考虑苹果的股票,并选择 2016 年至 2017 年作为回溯测试的持续时间。我们从 1050 美元的资本开始。我选择这个数字,因为我知道我们需要多少或多或少的初始购买,我喜欢让这个数字尽可能小,因为我们只购买 10 股,所以不需要几千的初始余额。我们假设默认的交易成本(每股 0.001 美元,没有最低交易成本)。
使用zipline
有两种方法——使用命令行或 Jupyter 笔记本。要使用后者,我们必须在笔记本的单元格中编写算法,并指出zipline
应该运行它。这是通过%%zipline
IPython magic 命令完成的。这个魔术与上面提到的 CLI 采用相同的参数。
还有一点很重要,算法运行所需的所有导入(如numpy
、sklearn
等)。)必须在算法单元中指定,即使它们以前被导入到其他地方。
恭喜,我们已经完成了第一次回溯测试。那么到底发生了什么?
每个zipline
算法包含(至少)两个我们必须定义的函数:
initialize(context)
handle_data(context, data)
在算法开始之前,调用initialize()
函数并传递一个context
变量。context
是一个全局变量,我们可以在其中存储从算法的一次迭代到下一次迭代需要访问的额外变量。
算法初始化后,每个事件调用一次handle_data()
函数。在每次调用时,它传递同一个context
变量和一个名为data
的事件帧。它包含当前的交易棒线,包括开盘价、最高价、最低价和收盘价(OHLC)以及交易量。
我们通过使用order(asset, number_of_units)
创建一个订单,在这里我们指定购买什么以及多少股票/单位。正数表示买入那么多股票,0 表示卖出我们所有的股票,负数表示卖空。另一种有用的订单类型是order_target
,根据需要订购尽可能多的股票,以达到投资组合中所需的数量。
在我们的买入并持有策略中,我们会检查是否已经下单。如果没有,我们订购一定数量的股票,然后在回溯测试的剩余时间里什么也不做。
我们来分析一下策略的表现。首先,我们需要从 pickle 文件加载性能数据帧。
# read the performance summary dataframe
buy_and_hold_results = pd.read_pickle('buy_and_hold.pkl')
现在我们可以绘制一些存储的指标:
从第一眼看,我们看到该投资组合在投资期限内产生了资金,并在很大程度上跟随苹果的价格(这是有意义的,因为它是投资组合中的唯一资产)。
为了查看事务,我们需要从 performance DataFrame 转换transactions
列。
pd.DataFrame.from_records([x[0] for x in buy_and_hold_results.transactions.values if x != []])
通过检查性能数据框架的列,我们可以看到所有可用的指标。
buy_and_hold_results.columns
其中一些值得注意的是:
- 期初/期末现金——检查给定日期的现金持有量
- 起始/终止值—检查资产;给定日期的值
- 订单—用于检查订单;当交易策略产生信号时,创建订单有不同的事件,当在下一个交易日实际执行时,创建订单有不同的事件
- pnl —每日损益
简单移动*均策略
我们考虑的第二个策略是基于简单移动*均线(SMA)。该战略的“机制”可以总结如下:
- 当价格向上穿过 20 日均线时,买入
x
股票 - 当价格向下穿过 20 日均线时,卖出股票
- 在任何时候,我们最多只能拥有
x
股 - 该策略中没有卖空(尽管它很容易实现)
回溯测试的其余组成部分,如考虑的资产、投资期限或启动资本,与买入并持有示例中的相同。
这个算法的代码稍微复杂一点,但是我们涵盖了代码的所有新方面。为了简单起见,我在上面的代码片段中标记了引用点(sma_strategy.py
),并将在下面用数字引用它们。
1.我演示如何手动设置佣金。在这种情况下,为了便于比较,我使用默认值。
2。“热身期”——这是一个用来确保算法有足够的天数来计算移动*均值的技巧。如果我们使用具有不同窗口长度的多个指标,我们应该总是取最长的一个用于预热。
3。我们通过使用data.history
访问历史(和当前)数据点。在本例中,我们访问过去 20 天。数据(在单个资产的情况下)存储为一个pandas.Series
,按时间索引。
4。SMA 是一个非常基本的指标,所以对于计算来说,我简单地取之前访问的数据的*均值。
5。我把交易策略的逻辑概括在一个if
声明中。为了访问当前和先前的数据点,我分别使用了price_history[-2]
和price_history[-1]
。为了查看是否有交叉,我将当前和以前的价格与均线进行比较,并确定我正在处理哪种情况(买入/卖出信号)。在没有信号的情况下,算法什么也不做。
6。当回溯测试完成时,您可以使用analyze(context, perf)
语句来执行额外的分析(如绘图)。perf
对象只是我们也存储在 pickle 文件中的性能数据帧。但是当在算法中使用时,我们应该称它为perf
,不需要加载它。
与买入并持有策略相比,你可能已经注意到投资组合价值持*的时期。这是因为当我们出售资产时(以及再次购买之前),我们只持有现金。
在我们的案例中,简单的均线策略胜过买入并持有策略。对于 SMA 策略,投资组合的期末价值(包括现金)为 1784.12 美元,而对于更简单的策略,期末价值为 1714.68 美元。
结论
在本文中,我展示了如何使用zipline
框架来执行交易策略的回溯测试。一旦你熟悉了这个库,就很容易测试出不同的策略。在以后的文章中,我将介绍如何使用基于技术分析的更先进的交易策略。
一如既往,我们欢迎任何建设性的反馈。你可以在推特上或者评论里联系我。您可以在我的 GitHub 上找到本文使用的代码。
喜欢这篇文章吗?成为一个媒介成员,通过无限制的阅读继续学习。如果你使用这个链接成为会员,你将支持我,不需要额外的费用。提前感谢,再见!
以下是本系列的后续文章:
- 导入自定义数据以使用 zipline ( 链接)
- 评估交易策略的表现(链接)
- 基于技术分析建立算法交易策略(链接)
- 基于均值-方差分析建立算法交易策略(链接)
我最*出版了一本关于使用 Python 解决金融领域实际任务的书。如果你有兴趣,我在贴了一篇文章介绍这本书的内容。你可以在亚马逊或者 Packt 的网站上买到这本书。
贝叶斯信念网络简介
原文:https://towardsdatascience.com/introduction-to-bayesian-belief-networks-c012e3f59f1b?source=collection_archive---------2-----------------------
什么是贝叶斯信念网络?
贝叶斯信念网络或贝叶斯网络或信念网络是一种概率图形模型(PGM),它通过有向无环图(DAG)来表示随机变量之间的条件依赖关系。
An Example Bayesian Belief Network Representation
今天,我将尝试解释信念网络的主要方面,尤其是可能与社会网络分析(SNA)相关的应用。此外,我将向您展示这种网络的一个示例实现。
我们用贝叶斯网络做什么?
贝叶斯网络在很多领域都有应用。例如,疾病诊断、优化的网络搜索、垃圾邮件过滤、基因调控网络等。这个列表还可以扩展。这些网络的主要目标是试图理解因果关系的结构。为了澄清这一点,让我们考虑一个疾病诊断问题。有了给定的症状及其导致的疾病,我们构建了我们的信念网络,当新患者到来时,我们可以通过提供每种疾病的概率来推断新患者可能患有哪种或哪些疾病。类似地,这些因果关系可以为其他问题构建,推理技术可以应用于有趣的结果。
快速概率复习
在继续之前,为了让我们回忆一下,让我给你条件属性的定义。条件概率是在给定其他随机变量的情况下,一个随机变量的概率。它显示为
如果这两个随机变量是相关的,
如果他们是独立的,那么
信念网络的数学定义
通过以下公式在信念网络中计算概率
正如您从公式中所理解的那样,为了能够计算联合分布,我们需要有由网络表示的条件概率。但是进一步说,如果我们有共同分布,那么我们可以开始问有趣的问题。例如,在第一个例子中,如果“季节”是“冬天”,“狗叫”是“真”,我们就要求“下雨”的概率。
信任网络的 Python 示例
所以,我认为这对于理论来说足够了,在继续之前,让我们看一些我目前最喜欢的编程语言 Python ❤️的真实例子,你可以在这里找到我写的 Jupyter 笔记本。
# create the nodes
season = BbnNode(Variable(0, 'season', ['winter', 'summer']), [0.5, 0.5])
atmos_pres = BbnNode(Variable(1, 'atmos_press', ['high', 'low']), [0.5, 0.5])
allergies = BbnNode(Variable(2, 'allergies', ['allergic', 'non_alergic']), [0.7, 0.3, 0.2, 0.8])
rain = BbnNode(Variable(3, 'rain', ['rainy', 'sunny']), [0.9, 0.1, 0.7, 0.3, 0.3, 0.7, 0.1, 0.9])
grass = BbnNode(Variable(4, 'grass', ['grass', 'no_grass']), [0.8, 0.2, 0.3, 0.7])
umbrellas = BbnNode(Variable(5, 'umbrellas', ['on', 'off']), [0.99, 0.01, 0.80, 0.20, 0.20, 0.80, 0.01, 0.99])
dog_bark = BbnNode(Variable(6, 'dog_bark', ['bark', 'not_bark']), [0.8, 0.2, 0.1, 0.9])
cat_mood = BbnNode(Variable(7, 'cat_mood', ['good', 'bad']), [0.05, 0.95, 0.95, 0.05])
cat_hide = BbnNode(Variable(8, 'cat_hide', ['hide', 'show']), [0.20, 0.80, 0.95, 0.05, 0.95, 0.05, 0.70, 0.30])bbn = Bbn() \
.add_node(season) \
.add_node(atmos_pres) \
.add_node(allergies) \
.add_node(rain) \
.add_node(grass) \
.add_node(umbrellas) \
.add_node(dog_bark) \
.add_node(cat_mood) \
.add_node(cat_hide) \
.add_edge(Edge(season, allergies, EdgeType.DIRECTED)) \
.add_edge(Edge(season, umbrellas, EdgeType.DIRECTED)) \
.add_edge(Edge(season, rain, EdgeType.DIRECTED)) \
.add_edge(Edge(atmos_pres, rain, EdgeType.DIRECTED)) \
.add_edge(Edge(rain, grass, EdgeType.DIRECTED)) \
.add_edge(Edge(rain, umbrellas, EdgeType.DIRECTED)) \
.add_edge(Edge(rain, dog_bark, EdgeType.DIRECTED)) \
.add_edge(Edge(rain, cat_mood, EdgeType.DIRECTED)) \
.add_edge(Edge(dog_bark, cat_hide, EdgeType.DIRECTED)) \
.add_edge(Edge(cat_mood, cat_hide, EdgeType.DIRECTED))
我们首先用条件概率描述了我们的节点。您应该注意到,为了简单起见,我跳过了一些可能的状态值。例如,季节变量取其他值“春天”和“秋天”。所以,想法是一样的。
不,让我们检查一下我们的网络是否构建正确。
with warnings.catch_warnings():
warnings.simplefilter('ignore')
graph = convert_for_drawing(bbn)
pos = nx.nx_agraph.graphviz_layout(graph, prog='neato')plt.figure(figsize=(20, 10))
plt.subplot(121)
labels = dict([(k, node.variable.name) for k, node in bbn.nodes.items()])
nx.draw(graph, pos=pos, with_labels=True, labels=labels)
plt.title('BBN DAG')
这段代码片段将生成下图
所以,你看这个网络和我一开始画的很像。现在,让我们在这个信念网络上做一些推论。
# convert the BBN to a join tree
join_tree = InferenceController.apply(bbn)# insert an observation evidence
ev = EvidenceBuilder() \
.with_node(join_tree.get_bbn_node_by_name('season')) \
.with_evidence('winter', 1.0) \
.build()join_tree.set_observation(ev)# print the marginal probabilities
for node in join_tree.get_bbn_nodes():
potential = join_tree.get_bbn_potential(node)
print(node)
print(potential)
print('--------------------->')
这段代码基本上以 1.0 的概率向网络证明了季节是冬天。根据这一证据,当我们进行推论时,我们得到以下结果。
0|season|winter,summer
0=winter|1.00000
0=summer|0.00000
--------------------->
2|allergies|allergic,non_alergic
2=allergic|0.70000
2=non_alergic|0.30000
--------------------->
3|rain|rainy,sunny
3=rainy|0.80000
3=sunny|0.20000
--------------------->
4|grass|grass,no_grass
4=grass|0.70000
4=no_grass|0.30000
--------------------->
1|atmos_press|high,low
1=high|0.50000
1=low|0.50000
--------------------->
5|umbrellas|on,off
5=on|0.95200
5=off|0.04800
--------------------->
6|dog_bark|bark,not_bark
6=bark|0.66000
6=not_bark|0.34000
--------------------->
7|cat_mood|good,bad
7=good|0.23000
7=bad|0.77000
--------------------->
8|cat_hide|hide,show
8=hide|0.87150
8=show|0.12850
--------------------->
当我们添加进一步的证据时,就像狗没有叫一样
# convert the BBN to a join tree
join_tree = InferenceController.apply(bbn)# insert an observation evidence
ev = EvidenceBuilder() \
.with_node(join_tree.get_bbn_node_by_name('season')) \
.with_evidence('winter', 1.0) \
.build()ev2 = EvidenceBuilder() \
.with_node(join_tree.get_bbn_node_by_name('dog_bark')) \
.with_evidence('not_bark', 1.0) \
.build()join_tree.set_observation(ev)
join_tree.set_observation(ev2)# print the marginal probabilities
for node in join_tree.get_bbn_nodes():
potential = join_tree.get_bbn_potential(node)
print(node)
print(potential)
print('--------------------->')
我们得到以下推论结果
0|season|winter,summer
0=winter|1.00000
0=summer|0.00000
--------------------->
2|allergies|allergic,non_alergic
2=allergic|0.70000
2=non_alergic|0.30000
--------------------->
3|rain|rainy,sunny
3=rainy|0.47059
3=sunny|0.52941
--------------------->
4|grass|grass,no_grass
4=grass|0.53529
4=no_grass|0.46471
--------------------->
1|atmos_press|high,low
1=high|0.39706
1=low|0.60294
--------------------->
5|umbrellas|on,off
5=on|0.88941
5=off|0.11059
--------------------->
6|dog_bark|bark,not_bark
6=bark|0.00000
6=not_bark|1.00000
--------------------->
7|cat_mood|good,bad
7=good|0.52647
7=bad|0.47353
--------------------->
8|cat_hide|hide,show
8=hide|0.83162
8=show|0.16838
--------------------->
你看出区别了吗?😆当我们加入与狗叫声有关的证据时,很多概率值都变了。这绝对是一个愚蠢的例子,但很好地获得了直觉。
SNA 中如何使用贝叶斯网络?
贝叶斯网络是理解变量之间因果关系结构的非常强大的工具。一旦你设计了你的模型,即使只有很小的数据集,它也能告诉你各种各样的事情。这一部分的问题是如何在 SNA 中获得贝叶斯网的好处。答案不是唯一的,但让我们从一个深刻的想法开始。在 SNA 中,我们试图理解社会网络的结构。此外,我们试图理解节点的重要性。但是我们不知道我们的重要性度量的结果是什么。这就是贝叶斯网络发生的地方。例如,如果你认为一个节点的重要性是由度中心性和链接中心性引起的,你可能有下面的网络。
这是一个非常幼稚的贝叶斯网络。除了确定节点的重要性,进一步的应用可能是搜索某些特定类型的节点。让我们考虑一个社交网络,其中有一些人是潜在的领导者,我想寻找他们。考虑下图
这个稍微复杂一点的网络将有助于我们确定与成为领导相关的节点的不确定性。
另一个应用程序将推断链接。新的链接可以从现有的链接中推断出来。例如,从社交网络中的群组成员关系,可以推断出可能的成员关系链接。我的意思是,我们可以通过考虑现有的链接来建立用户和组之间的新链接。参见下面的模型图
所以,这些是贝叶斯网络如何应用于 SNA 的一些基本例子。这个主题没有被很好地研究过,但是我认为进一步研究可能是非常有用的。
结论
贝叶斯网络的难点在于设计。特别是,当你想到 SNA 时,用贝叶斯网络从社会网络构建映射是艺术而不是科学😃但是一旦你完成了艺术工作,并且很好地设计了你的模型,这些方便的工具可以告诉你很多事情。众所周知,贝叶斯网络在很多领域都有应用。在大多数情况下,它工作得非常好。因此,我坚信我们也可以对社交网络做出非常深刻的推论。
关于 SNA 和贝叶斯网络的进一步研究,请继续关注🚀
参考
- 科尔勒、戴维&普法茨、乔纳森&法瑞、迈克尔&考克斯、扎克&卡托、杰弗里&坎波隆戈、约瑟夫。(2006).贝叶斯信念网络在社会网络分析中的应用。
- https://www.edureka.co/blog/bayesian-networks/
- 图纸绘制在草图 io 中
- 样本网络取自https://www . probabilistic world . com/Bayesian-belief-networks-part-1/
BigQuery ML 简介
原文:https://towardsdatascience.com/introduction-to-bigquery-ml-e746a3eaa28d?source=collection_archive---------7-----------------------
几个月前,谷歌宣布了一个名为 BigQuery ML 的新功能,目前正在测试中。它由一组 SQL 语言的扩展组成,允许创建机器学习模型,评估其预测性能,并直接在 BigQuery 中对新数据进行预测。
Source: https://twitter.com/sfeir/status/1039135212633042945
BigQuery ML (BQML)的一个优点是,一个人只需要知道标准 SQL 就可以使用它(不需要使用 R 或 Python 来训练模型),这使得机器学习更容易使用。它甚至处理数据转换、训练/测试集分割等。此外,它减少了模型的训练时间,因为它直接在存储数据的地方工作(BigQuery ),因此,没有必要将数据导出到其他工具。
但并不是一切都是优势。首先,实现的模型目前是有限的(尽管我们将看到它提供了一些灵活性),由于适应 SQL 的事实,这种情况可能会一直存在。其次(在我看来,更重要的是),即使 BQML 使模型训练变得更容易,但一个不熟悉机器学习的人仍然可能难以解释他们创建的模型,评估其性能并试图改进它。
在这篇文章中,我将解释 BQML 的主要功能,以及如何使用它们来创建我们的模型,评估它并使用它进行预测。这一过程将包括以下步骤:
- 创建数据集(可选)
- 创建模型
- 型号信息(可选)
- 评估模型
- 预测
创建数据集(可选)
与 BigQuery (BQ)表一样,模型必须保存在一个数据集中,因此首先您必须决定要将模型保存在哪个数据集中:现有的数据集还是新的数据集。
如果您的情况是后者,创建一个新的数据集就像下面这样简单:
- 在 BQ 界面中,选择要创建数据集的项目,点击“创建数据集”按钮。
2.命名新数据集,并选择存储数据的位置和到期时间。你可以在这个链接中找到关于这些领域的更多信息。
创建模型
在监督机器学习中,使用响应变量已知的训练数据集来生成模型,该模型捕获数据的潜在模式,以便它可以预测看不见的数据的结果。
BQML 允许您直接在 BigQuery 中完成这个过程。目前,它支持三种类型的模型:
- 线性回归。它用于预测连续数值变量的结果,如收入。
- 二元逻辑回归。它用于预测具有两个可能类别的分类变量的结果,例如当您想要确定用户是否会购买或而不是时。
- 多项逻辑回归(或多类)。它用于预测具有两个以上类别的分类变量的结果。
要使用 BQML 创建(和训练)模型,必须使用以下语法:
#standardSQL
{CREATE MODEL | CREATE MODEL IF NOT EXISTS | CREATE OR REPLACE MODEL} `project.dataset.model_name`
OPTIONS(model_option_list)
AS query_statement
此查询将使用指定的选项(options)创建一个模型(CREATE MODEL ),并将查询的结果(AS)用作训练数据。我们必须指定:
1)模型的名称及其保存位置。创建模型创建并训练模型(将在指定的数据集中以名称“ model_name ”保存),只要没有已创建的同名模型。如果模型名称存在,带有 CREATE MODEL 的查询将返回错误。为了避免这种错误,我们可以使用两种替代方法:
- 如果不存在,则创建模型,这将仅在没有已创建的同名模型的情况下创建和定型模型。
- 创建或替换模型,即创建模型(如果不存在)或替换模型(如果存在)并训练模型。
- 型号 _ 选项 _ 列表。指定与模型和培训过程相关的一些选项的列表。格式如下:选项 1 =值 1,选项 2 =值 2,… 两个最重要的选项是:
- model_type(强制):指定我们要训练的模型的类型: linear_reg 用于线性回归,或者 logistic_reg 用于二元或多类 logistic 回归。
- input_label_cols:指定包含响应变量的训练数据的表的列名。如果列名为标签,则该字段是可选的;如果不是,必须指定为 ['列名'] 。
尽管 BigQuery ML 具有用于模型训练的默认选项,但是它提供了一些灵活性来选择与避免过度拟合和模型参数优化相关的选项。例如,我们可以应用正则化 L1 或 L2,将数据分为训练集和验证集,或者设置梯度下降的最大迭代次数。您可以在这个链接中找到所有可用的选项。
- 查询 _ 语句。生成将用作定型数据的表的查询。BigQuery ML 的一个优点是负责模型训练的数据转换。特别是:
- 分类特征(BOOL、STRING、BYTES、DATE、DATETIME 或 TIME 类型)是一次性编码的(即转换为每个类的二进制变量)。由于被称为多重共线性的问题,如果您想要得出关于特征和响应变量之间关系的结论,则不建议这样做。
- 数值特征(NUMERIC、FLOAT64 或 INT64 类型)针对训练数据和未来预测进行了标准化。
- 在数值变量的情况下,空值由*均值替换;在分类特征的情况下,空值由对所有这些缺失数据进行分组的新类替换。
关于响应变量,必须考虑到:
- 线性回归中不能有无穷大或 NaN 值。
- 在二元逻辑回归中,它必须正好有两个可能的值。
- 在多类逻辑回归中,最多可以有 50 个不同的类别。
例如,让我们想象一下,我们希望根据与用户浏览活动相关的几个特征(页面浏览量、会话持续时间、用户类型、他使用的设备以及是否是付费流量)来预测一个 web 会话最终是否会购买。如果你想了解这个例子,我们将使用 BigQuery 提供的谷歌分析测试数据集。为了创建模型,我们将使用以下查询:
#standardSQL
CREATE MODEL `project.dataset.sample_model`
OPTIONS(model_type='logistic_reg',
input_label_cols=['isBuyer'])
AS
SELECT
IF(totals.transactions IS NULL, 0, 1) AS isBuyer,
IFNULL(totals.pageviews, 0) AS pageviews,
IFNULL(totals.timeOnSite, 0) AS timeOnSite,
IFNULL(totals.newVisits, 0) AS isNewVisit,
IF(device.deviceCategory = 'mobile', 1, 0) AS isMobile,
IF(device.deviceCategory = 'desktop', 1, 0) AS isDesktop,
IF(trafficSource.medium in ('affiliate', 'cpc', 'cpm'), 1, 0) AS isPaidTraffic
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20160801' AND '20170630'
由于我们的响应变量具有两个分类(1 =“有购买”或 0 =“没有购买”),我们必须在选项中指定模型的类型是逻辑回归(logistic_reg)。另外,请注意,响应变量名为“isBuyer”,因此我们也必须在选项中指定它。
型号信息(可选)
在线性模型中,每个解释变量都有一个相关的系数(或权重),用于确定该特征和响应变量之间的关系。其幅度越大,对响应变量的影响就越大。此外,正(负)号表示当该解释变量的值增加时(或者,在分类变量的情况下,类别存在),响应是否增加(减少)。
在 BigQuery ML 中,我们可以使用以下查询来获取已训练模型的权重:
#standardSQL
SELECT *
FROM ML.WEIGHTS(MODEL `project.dataset.model_name`)
如前所述,如果您没有在查询中“手动”将分类变量转换为二进制变量(例如,正如我们对 isMobile 和 isDesktop 所做的那样),每个可能的类别都将有一个权重,并且系数的可靠性将由于多重共线性而受到损害。
例如,我们在上一节中创建的模型具有以下系数:
也就是说,作为一个新用户的会话,使用移动设备或通过付费渠道访问网络降低了访问以购买结束的概率。而使用桌面或者在网站上花更多的时间增加转化的概率。
评估模型
一旦我们有了训练好的模型,我们需要评估它的预测性能。这总是必须在不同于训练集的测试集上进行,以避免过度拟合,当我们的模型记忆我们的训练数据的模式时,就会发生过度拟合,因此它在我们的训练集中非常精确,但它不能在新数据中做出良好的预测。
BQML 提供了几个函数来评估我们的模型:
- ML。培训信息。提供有关模型定型期间迭代的信息,包括每次迭代时定型集和验证集中的损失。预期结果是两组中的损失都减少(理想情况下,减少到 0,这意味着模型总是正确的)。
- ML.EVALUATE .提供最常用的指标来评估模型的预测性能。此函数可用于任何类型的模型(线性回归、二元逻辑回归、多类逻辑回归),但根据是回归还是分类任务,度量标准会有所不同。
- ML。困惑 _ 矩阵。返回给定数据集的混淆矩阵,这使我们能够知道分类模型中每个可能类别的正确预测和错误。它只能用于分类模型,即逻辑回归和多类逻辑回归。
- ML。ROC_CURVE。此函数允许我们构建 ROC 曲线,这是一种用于评估二元分类模型预测能力的可视化图形。在这种情况下,它只能用于二元逻辑回归模型。
在这篇文章中,我们将关注 ML。评估,但我们将给出其他函数的语法和示例,以防有人对使用它们感兴趣。
ML。评价
要评估先前创建的模型,必须使用以下语法:
#standardSQL
SELECT *
FROM ML.EVALUATE(MODEL `project.dataset.model_name`,
{TABLE table_name | (query_statement)}
[, STRUCT(XX AS threshold)])
我们必须指定:
- 模型。
- 我们要为其计算评估度量的表,评估度量可以是查询的结果。显然,这个测试集必须与定型集具有相同的列,包括响应变量(以便将模型预测与实际值进行比较)。如果未指定表或查询,它将使用验证集(如果在创建模型时指定)或定型集(如果未指定验证集)。
- 在逻辑回归的情况下,阈值。此值是可选的,它指定了我们的模型的预测值(介于 0 和 1 之间的值,可以解释为该观察值属于类 1 的概率)将用于类 0 或类 1。默认情况下,阈值为 0.5。
此查询的结果是一个单行,其中包含评估模型预测的最常用指标,这取决于所使用的模型类型。
特别是,BigQuery ML 为逻辑回归和多类逻辑回归模型提供的指标有:
- 精确
- 召回
- 准确(性)
- f1 _ 分数
- 日志 _ 损失
- roc_auc
在线性回归的情况下,它们是:
- *均绝对误差
- 均方误差
- 均方对数误差
- 中位数绝对误差
- r2 _ 分数
- 解释的差异
例如,对于我们示例中的逻辑回归,我们必须使用:
#standardSQL
SELECT *
FROM ML.EVALUATE(MODEL `project.dataset.sample_model`,
(
SELECT
IF(totals.transactions IS NULL, 0, 1) AS isBuyer,
IFNULL(totals.pageviews, 0) AS pageviews,
IFNULL(totals.timeOnSite, 0) AS timeOnSite,
IFNULL(totals.newVisits, 0) AS isNewVisit,
IF(device.deviceCategory = 'mobile', 1, 0) AS isMobile,
IF(device.deviceCategory = 'desktop', 1, 0) AS isDesktop,
IF(trafficSource.medium in ('affiliate', 'cpc', 'cpm'), 1, 0) AS isPaidTraffic
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20170701' AND '20170801'
),
STRUCT(0.5 AS threshold)
)
请注意,用于生成数据的日期与用于创建模型的日期不同。前一个查询的结果是:
评估模型的其他函数
1.ML。培训 _ 信息
语法:
#standardSQL
SELECT *
FROM ML.TRAINING_INFO(MODEL `project.dataset.model_name`)
示例:
#standardSQL
SELECT *
FROM ML.TRAINING_INFO(MODEL `project.dataset.sample_model`)
2.ML。困惑 _ 矩阵
语法:
#standardSQL
ML.CONFUSION_MATRIX(MODEL `project.dataset.model_name`,
{TABLE table_name | (query_statement)}
[, STRUCT(XX AS threshold)])
示例:
#standardSQL
SELECT *
FROM ML.CONFUSION_MATRIX(MODEL `project.dataset.sample_model`,
(
SELECT
IF(totals.transactions IS NULL, 0, 1) AS isBuyer,
IFNULL(totals.pageviews, 0) AS pageviews,
IFNULL(totals.timeOnSite, 0) AS timeOnSite,
IFNULL(totals.newVisits, 0) AS isNewVisit,
IF(device.deviceCategory = 'mobile', 1, 0) AS isMobile,
IF(device.deviceCategory = 'desktop', 1, 0) AS isDesktop,
IF(trafficSource.medium in ('affiliate', 'cpc', 'cpm'), 1, 0) AS isPaidTraffic
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20170701' AND '20170801'
),
STRUCT(0.5 AS threshold)
)
3.ML。ROC _ 曲线
语法:
#standardSQL
ML.ROC_CURVE(MODEL `project.dataset.model_name`,
{TABLE table_name | (query_statement)},
[GENERATE_ARRAY(thresholds)])
示例:
#standardSQL
SELECT *
FROM ML.ROC_CURVE(MODEL `project.dataset.sample_model`,
(
SELECT
IF(totals.transactions IS NULL, 0, 1) AS isBuyer,
IFNULL(totals.pageviews, 0) AS pageviews,
IFNULL(totals.timeOnSite, 0) AS timeOnSite,
IFNULL(totals.newVisits, 0) AS isNewVisit,
IF(device.deviceCategory = 'mobile', 1, 0) AS isMobile,
IF(device.deviceCategory = 'desktop', 1, 0) AS isDesktop,
IF(trafficSource.medium in ('affiliate', 'cpc', 'cpm'), 1, 0) AS isPaidTraffic
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20170701' AND '20170801'
),
GENERATE_ARRAY(0.0, 1.0, 0.01)
)
预测
要使用通过 BigQuery ML 创建的模型进行预测,必须使用以下语法:
#standardSQL
ML.PREDICT(MODEL model_name,
{TABLE table_name | (query_statement)}
[, STRUCT(XX AS threshold)])
该查询将使用一个模型(model ),并对一个新的数据集(TABLE)进行预测。显然,该表必须具有与定型数据相同的列,尽管没有必要包含响应变量(因为我们不需要它来预测新数据)。在逻辑回归中,您可以选择指定一个阈值,该阈值定义将哪个估计概率视为最终预测的一个类别或另一个类别。
该查询的结果将包含与我们提供的数据集一样多的行,并且将包括输入表和模型预测。在逻辑回归模型(二元或多类)的情况下,除了预测模型的类之外,还提供了每个可能类的估计概率。
继续我们的例子:
#standardSQL
SELECT *
FROM ML.PREDICT(MODEL `project.dataset.sample_model`,
(
SELECT
IFNULL(totals.pageviews, 0) AS pageviews,
IFNULL(totals.timeOnSite, 0) AS timeOnSite,
IFNULL(totals.newVisits, 0) AS isNewVisit,
IF(device.deviceCategory = 'mobile', 1, 0) AS isMobile,
IF(device.deviceCategory = 'desktop', 1, 0) AS isDesktop,
IF(trafficSource.medium in ('affiliate', 'cpc', 'cpm'), 1, 0) AS isPaidTraffic
FROM
`bigquery-public-data.google_analytics_sample.ga_sessions_*`
WHERE
_TABLE_SUFFIX BETWEEN '20170701' AND '20170801'
)
)
请注意,包含响应(isBuyer)的列不是必需的。前一个查询的结果是:
第一列返回我们的模型为每个新观察预测的类。第二列和第三列给出了每个类别的估计概率(估计概率较大的类别是第一列中的类别)。其余的列是我们请求其预测的数据。
化学信息学导论
原文:https://towardsdatascience.com/introduction-to-cheminformatics-7241de2fe5a8?source=collection_archive---------12-----------------------
化学信息学的常见挑战、库和数据集
Photo by Alex Kondratiev on Unsplash
什么是化学信息学?
随着计算能力的增加,机器学习在不同的科学领域中得到了许多应用。其中之一是化学,科学家应用机器学习模型来预测各种分子的属性,如其溶解性和毒性[1]或将其用于药物发现。
化学信息学是一个应用机器学习等计算方法来解决化学中各种问题的科学领域[2]。它提出了非常具有挑战性的问题,例如将 3D 分子结构转换为 ML 模型的输入,解决数据稀缺的问题,或者试图更好地理解哪个分子的特征对于预测是重要的[3]。
在本文中,我将温和地向您介绍化学信息学目前面临的几个问题,并列出一些可用的库和数据集,以帮助您开始涉足这一激动人心且富有挑战性的领域!
如何表示分子结构
分子可以被视为一个三维量子力学对象,它由分子内位置明确的原子组成[4]。你可以在这里提取大量信息:与每个分子的相对距离、原子序数、电子概率云的形状以及许多其他信息。
Photo by Holger Link on Unsplash
然而,在将这些信息转换为机器学习模型的输入时,很难保留所有这些信息。幸运的是,有一些现有的分子表示正在试图解决这个问题。
笑容
微笑是分子的一种类似文本的表示,它代表简化的分子输入行条目。除了它听起来别扭的名字之外,它还是最流行的表示分子的方式之一。事实上,一些深度学习模型直接接受微笑作为输入[5]。
你也应该意识到微笑表示确实会产生信息损失,这对训练机器学习模型非常重要。在将分子转换成微笑【4】时,像原子键的长度和分子的 3D 坐标位置这样的特征会丢失。
SMILES algorithm. [Source]
扩展连接指纹(ECFP)
首先:什么是分子指纹?分子指纹只是用数字表示分子的另一种方式。指纹产生的位状图案表明分子中某些亚结构的存在或不存在。生成这些模式背后的想法有点复杂,如果你感兴趣,可以看看这里的。
ECFP 是分子指纹的一个特例,它为任何分子的原子分配唯一的编号。编号取决于许多因素,如绝对电荷、重原子连接数、非氢键数量或原子电荷。这里需要注意的关键是,这种算法可以通过各种方式进行优化,并且可以由流行的化学信息学库 RDKit 处理。
流行的深度学习架构
一旦我们得到了正确形状的输入,我们应该决定哪种机器学习模型将有效地处理分子结构。在这里,我将为您提供一些在化学信息学中运行良好的流行架构。
递归神经网络
RNNs 与分子的 SMILES 表示一起工作得很好。由于 SMILES 是基于文本的表示,RNNs 可以用于预测序列中的另一个分子。它允许生成新的 SMILES 序列,这可能有助于发现具有所需特性(例如,某些溶解性或毒性)的分子。本文展示了用 RNNs 生成新分子的结果。
图形卷积网络
将 RNNs 和 CNN 一般化以将图形作为输入是一个相当困难的问题,在处理分子时经常会出现这种情况。图形卷积网络(gcn)通过将分子图及其特征作为输入来解决这个问题。更具体地说,图形连同每个节点(原子)的特征被转换成矩阵形式,然后插入到神经网络模型中。关于 GCNs 的深入文章可以在这里找到。
Image Convolution and Graph Convolution. [Source]
我们为什么要使用 gcn?根据文献[7],如果将分子表示为 2D 图,则保留了更多的信息。它还需要相对低的计算成本并达到高精度,这有助于类似 CNN 的架构。
公开可用的分子数据集
如果没有足够的数据,如何训练机器学习模型?这曾经是化学中的一个问题,但现在化学家们通常会将数据免费提供给每个人。我将在这里列出一些最受欢迎的分子数据集,以便您可以将其用作参考:)
公共化学
世界上最大的免费化学信息收集。它包含* 1 亿种化合物和超过 2.36 亿种物质。数据集似乎维护得很好,包括文档和教程。有大量关于物理和化学性质的信息,以及每种化合物的各种结构表示。绝对值得一探究竟!链接是这里的。
化学蜘蛛
这是一个与 Pubchem 非常相似的数据库,但是化学成分更少。在写这篇文章的时候,它包含了来自 270 个数据源的 7700 万个化学结构。如果你打算做一些大的事情,它可以和 PubChem 一起使用。这里的链接是这里的。
ChEMBL
这是一个人工筛选的数据集,包含具有类似药物特性的生物活性分子。目前,它包含 2M 化合物和 110 万种分析。此外,他们使用数据挖掘来收集更多关于分子的数据(例如,从专利文件中)。这里的链接是。
荣誉奖
一些鲜为人知但有用的数据集包括 Tox21 (毒理学)溶解度挑战,以及其他许多可以在 Kaggle 上找到的数据集。
有用的工具和 Python 库
深度化学
这是一个非常受欢迎和维护良好的 Python 库,在 Github 上有超过 1.7k 的 start。它为药物发现、量子化学和其他生命科学中的深度学习提供了开源工具链。他们网站的链接是这里。
RDKit
它是用 C++和 Python 编写的通用机器学习和化学信息学软件的集合。一些功能包括读写分子、亚结构搜索、化学转化或分子相似性。就我个人而言,我在我的笔记本电脑(Ubuntu)上很难设置它,但在 Conda 安装上它工作得很完美。他们网站的链接是这里。
荣誉奖
请看一下这个与化学相关的所有可用 Python 库的精选列表。
最后几句话要说
喜欢这篇关于化学信息学的文章吗?
确保你在 Medium 和 Linkedin 上关注我,我在那里发布了很多关于这个领域的有趣文章!你也可以在 Github 上找到我。
参考
[1] Pirashvili,m .,Steinberg,l .,Belchi Guillamon,f .,Niranjan,m .,Frey,j .和 Brodzki,J. (2019)。通过拓扑数据分析加深了对水溶性建模的理解。
[2]网上来源。可用这里。
[3]网上来源。约翰·加斯泰格。化学信息学中已解决和未解决的问题。可用此处。
[4]丹尼尔·c·埃尔顿、佐伊斯·鲍库瓦拉斯、马克·d·富格和彼得·w·琼加(2019)。用于分子设计的深度学习——当前技术水*综述
[5]潘德五世,沃尔特斯 P,伊斯曼 P,拉姆松达 B. 生命科学的深度学习
[6]网上来源。(2019).计算扩展连接指纹。此处可用。
[7] Seongok Ryu 等人。(2018).利用注意力和门增强图卷积网络深度学习分子结构-性质关系
计算机视觉导论
原文:https://towardsdatascience.com/introduction-to-computer-vision-b44bb4c495ab?source=collection_archive---------25-----------------------
超越所有媒体噪音和魅力的计算机视觉的基本解释。
“我不害怕电脑。我担心缺乏他们。” —艾萨克·阿西莫夫
在过去的十年中,计算机视觉一直是一个流行的重复出现的术语,尽管随着时间的推移,它的流行程度已经从一个闻所未闻的主题变成了热门新闻。作为*年来成为一个趋势性话题的结果,对计算机视觉需要什么的理解有些嘈杂。因此,本文的目的是分解术语计算机视觉并分析其组成部分,从而提供对什么是计算机视觉的基本理解。
为了扩展计算机视觉的主题,我们首先需要分析术语(“计算机”和“视觉”)的组成部分,并对它们进行定义。
计算机可以被定义为能够根据软件或硬件指导的指令集执行各种处理、计算和操作的电子机器。
因此,视觉,更具体地说,通过视觉的视觉感知可以被定义为通过可见光谱对环境中的物体进行照明来理解局部环境。
结合这两个术语的定义,初步的解释是,计算机视觉是机器如何试图理解它们看到的东西以实现目标。
我们可以通过陈述计算机视觉是机器或系统通过调用一个或多个作用于所提供的信息的算法来产生对视觉信息的理解的过程来扩展上述定义。理解然后被转化为决策、分类、模式观察等等。
然后在应用程序、硬件和软件中利用整理理解的翻译,翻译可以采取多种形式,如下所示:
- 对象检测:在数字图像甚至视频中识别感兴趣的对象(猫、狗、汽车)
- 光学字符识别:将书写或打字的文本图像翻译成机器编码格式
- 指纹识别:使用人类指纹的模式信息在指纹源和作为目标的指纹之间进行比较。
当向大众介绍计算机视觉时,我们需要包括已经采取的方法,以便使系统能够推理发展理解,并因此开发计算机视觉的有用应用。
计算机视觉系统可以应用两种主要的策略来从已经提供给它的信息中获得理解。它们分别是:自下而上和自上而下的方法。
自下而上的方法包括利用对积累的信息的理解来对一些任意的观察进行进一步的理解;最终,所有积累的理解会导致对观察对象整体的解决方案或总体理解。
在计算机视觉应用中使用自底向上方法的一个例子是自动车牌识别。这种类型的应用似乎是交通超速摄像机的合理组成部分。
自动车牌识别(ANPR)通过自下而上的方法将视觉信息(车牌)传递到我们的计算机视觉系统中。该系统通过识别盘子上数字的边缘来进行某种形式的理解。从边缘信息,我们继续向上一个层次,并开始通过连接边缘来识别线(这里我们可以看到理解从一个层次到另一个层次的转移)。之后,线条可以连接起来形成形状,最后,我们通过识别线条相交的区域和边缘来观察字符。
自上而下的方法应用背景知识从观察中获得理解。背景知识作为选择适合模型的参数的参考指南(类似于深度学习技术的方法)。这种方法可以简单地概括为这样的过程,通过该过程,图像被分解为子成分,并且获得对片段信息的理解,以呈现对图像整体的理解。
从这篇文章中,我们了解了计算机视觉的定义及其组成部分。还提到了计算机视觉技术的一些应用领域。除此之外,我们还探索了这些系统中的计算机视觉技术在试图从信息中获得理解时可以采用的方法。
从这里开始,您可以了解一些基本的低级图像处理技术,如边缘检测、降噪、图像锐化等。
张量流卷积神经网络简介
原文:https://towardsdatascience.com/introduction-to-convolutional-neural-networks-cnn-with-tensorflow-57e2f4837e18?source=collection_archive---------3-----------------------
学习计算机视觉卷积神经网络的基础,并使用 TensorFlow 构建 CNN
Photo by Stephanie Cook on Unsplash
深度学习的最新进展使计算机视觉应用向前迈进了一大步:从用我们的脸解锁手机,到更安全的自动驾驶汽车。
卷积神经网络 (CNN)是计算机视觉应用背后的架构。在这篇文章中,你将学习细胞神经网络和计算机视觉的基础,如卷积运算,填充,步长卷积和池层。然后,我们将使用 TensorFlow 构建一个用于图像识别的 CNN。
对于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
Spiderman recognizing Spiderman…
理解卷积
顾名思义,卷积运算是卷积神经网络的构建模块。
现在,在计算机视觉领域,图像可以表示为 RGB 值的矩阵。这个概念实际上是在之前的一篇文章中介绍的。
为了完成卷积运算,我们需要一个图像和一个过滤器。
因此,让我们将下面的 6x6 矩阵视为图像的一部分:
6x6 matrix. Source
并且过滤器将是下面的矩阵:
3x3 filter. Source
然后,卷积包括将过滤器叠加到图像矩阵上,将来自过滤器的值和来自图像矩阵的值的乘积相加,这将生成 4x4 卷积层。
这很难用语言表达,但这里有一个很好的动画来解释这个卷积:
Convolution operation
对上面的图像矩阵执行此操作,并使用上面定义的过滤器,您应该得到下面的结果矩阵:
4x4 output layer. Source
如何解读输出层?
考虑到每个值都表示颜色,或者像素有多暗(正值表示亮,负值表示暗),您可以将输出图层解释为:
Output layer interpretation. Source
因此,似乎这个特殊的过滤器负责检测图像中的垂直边缘!
如何选择合适的滤镜?
这是一个很自然的问题,因为你可能会意识到有无数种可能的滤镜可以应用于一幅图像。
事实证明,您的过滤器矩阵中的精确值可以是基于模型目标的可训练参数。因此,您可以选择适合特定应用的滤波器,也可以使用反向传播来确定能够产生最佳结果的滤波器的最佳值。
计算机视觉中的填充
之前,我们已经看到,3x3 滤波器与 6x6 图像卷积将产生 4x4 矩阵。这是因为在 6×6 的图像中,有 4×4 的可能位置适合滤波器。
因此,在每个卷积步骤之后,图像会缩小,这意味着只能执行有限次数的卷积,直到图像无法再缩小为止。此外,位于图像角落的像素仅被使用一次,这导致神经网络的信息丢失。
为了解决上述两个问题,使用了填充。填充包括在输入图像周围添加边框,如下所示:
Input image with padding of 1
如你所见,添加的边框通常用零填充。现在,图像的角像素将被多次使用来计算输出,有效地防止信息丢失。此外,它允许我们在输出中保持输入矩阵的形状。
考虑我们的 6x6 输入图像,如果我们添加 1 的填充,我们得到一个 8x8 的矩阵。应用 3×3 滤波器,这将产生 6×6 输出。
一个简单的等式可以帮助我们计算出输出的形状:
Where n is the input shape, p is the padding size, and f is the filter shape
重申一下,我们有:
- 6x6 输入
- 填充 1
- 3x3 过滤器
因此,输出形状将是:6+2(1)-3+1 = 6。因此,输出将是一个 6x6 的矩阵,就像输入图像一样!
填充并不总是必需的。但是,当使用填充时,通常是为了使输出与输入图像具有相同的大小。这产生了两种类型的卷积。
当没有应用填充时,这被称为“有效卷积”。否则称为“同卷积”。要确定保持输入图像尺寸所需的填充大小,只需将上面的公式等同于 n 。求解完 p 后,你应该得到:
您可能已经注意到,为了使填充为整数, f 应该是奇数。因此,在计算机视觉领域,使用奇数滤镜是一种惯例。
步进卷积
之前,我们已经看到了步长为 1 的卷积。这意味着过滤器水*和垂直移动了 1 个像素。
跨距卷积是指跨距大于 1 的卷积。在下面的动画中,步幅是 2:
Convolution with a stride of 2
现在,考虑步幅,计算输出矩阵形状的公式为:
Where s is the stride
按照惯例,如果上面的公式不能得出一个整数,那么我们就向下舍入到最接*的整数。
池层
合并图层是另一种减少图像解释大小以加快计算速度的方法,它使检测到的特征更加稳健。
用一个图像来解释池是最好的。下面是最大池的一个例子:
Max pooling with a 2x2 filter
如您所见,我们选择了步幅为 2 的 2x2 滤波器。这相当于将输入分成 4 个相同的正方形,然后我们取每个正方形的最大值,并将其用于输出。
也可以执行*均池化,但是它不如最大池化流行。
您可以将池化视为防止过度拟合的一种方式,因为我们正在从输入图像中移除一些特征。
为什么要使用卷积神经网络?
我们现在有一个强大的卷积神经网络的基础知识。但是,深度学习从业者为什么要用呢?
与全连接层不同,卷积层需要学习的参数要少得多。这是因为:
- 参数共享
- 联系的稀疏性
参数共享是指一个特征检测器,例如垂直边缘检测器,将在图像的许多部分有用。那么,连接的稀疏性是指只有少数特征与某个输出值相关。
考虑上面的最大池示例,输出的左上值仅取决于输入图像的左上 2x2 正方形。
因此,我们可以在更小的数据集上进行训练,并大大减少要学习的参数数量,使 CNN 成为计算机视觉任务的一个伟大工具。
用 TensorFlow 构建 CNN
理论讲够了,让我们为手势识别编写一个 CNN。我们重温一个以前的项目,看看 CNN 是否会表现得更好。
一如既往,完整的笔记本可在这里获得。
步骤 1:预处理图像
导入所需的库和资产后,我们加载数据并预处理图像:
步骤 2:创建占位符
然后,我们为特征和目标创建占位符:
步骤 3:初始化参数
然后,我们使用 Xavier 初始化来初始化参数:
步骤 4:定义正向传播
现在,我们定义正向传播步骤,这实际上是我们 CNN 的架构。我们将使用一个简单的三层网络,包括两个卷积层和一个全连接层:
第五步:计算成本
最后,我们定义一个函数来计算成本:
步骤 6:将所有功能组合成一个模型
现在,我们将上述所有功能合并到一个 CNN 网络中。我们将使用小批量梯度下降进行训练:
太好了!现在,我们可以运行我们的模型,看看它的表现如何:
_, _, parameters = model(X_train, Y_train, X_test, Y_test)
在我的例子中,我在只使用 CPU 的笔记本电脑上训练 CNN,我得到了一个相当糟糕的结果。如果你在有更好的 CPU 和 GPU 的台式机上训练 CNN,你肯定会得到比我更好的结果。
恭喜你!你现在对 CNN 和计算机视觉领域有了很好的了解。尽管还有更多的东西需要学习,但是更高级的技术使用这里介绍的概念作为构建模块。
在下一篇文章中,我将介绍 Keras 的剩余网络!
干杯!
参考: deeplearning.ai
Python 中的数据可视化简介
原文:https://towardsdatascience.com/introduction-to-data-visualization-in-python-89a54c97fbed?source=collection_archive---------0-----------------------
如何使用 Matplotlib,Pandas 和 Seaborn 制作图形
Figure 1: Photo by Lukas Blazek on Unsplash
数据可视化是一门学科,它试图通过将数据置于可视化的环境中来理解数据,从而揭示出可能无法检测到的模式、趋势和相关性。
Python 提供了多个优秀的图形库,这些图形库包含了许多不同的特性。无论你是想创建交互式的、实时的还是高度定制的情节,python 都为你提供了一个优秀的库。
下面是一些流行的绘图库:
- Matplotlib:低等级,提供了大量的自由
- 熊猫可视化: 易于使用的界面,基于 Matplotlib 构建
- Seaborn:高级界面,绝佳的默认样式****
- gg plot:基于 R 的 ggplot2,采用图形的语法
- 剧情: 可以创建互动剧情
在本文中,我们将学习如何使用 Matplotlib、Pandas visualization 和 Seaborn 创建基本的绘图,以及如何使用每个库的一些特定功能。本文将关注语法,而不是解释图形,我将在另一篇博客文章中介绍。
在以后的文章中,我将介绍像 Plotly 这样的交互式绘图工具,它构建在 D3 上,也可以与 JavaScript 一起使用。
导入数据集
在本文中,我们将使用两个免费提供的数据集。 Iris 和葡萄酒评论数据集,我们都可以使用 pandas read_csv
方法加载。
Figure 2: Iris dataset head
Figure 3: Wine Review dataset head
Matplotlib
Matplotlib 是最流行的 python 绘图库。这是一个低级的库,有一个类似 Matlab 的接口,提供了很多自由,代价是必须写更多的代码。
要安装 Matplotlib,可以使用 pip 和 conda。
**pip install matplotlib
or
conda install matplotlib**
Matplotlib 特别适合创建基本的图表,如线形图、条形图、直方图等等。可以通过键入以下内容来导入它:
**import matplotlib.pyplot as plt**
散点图
要在 Matplotlib 中创建散点图,我们可以使用scatter
方法。我们还将使用plt.subplots
创建一个图形和一个轴,这样我们就可以给我们的绘图一个标题和标签。
Figure 4: Matplotlib Scatter plot
我们可以通过按类别给每个数据点着色来赋予图表更多的意义。这可以通过创建一个从类映射到颜色的字典来完成,然后使用 for 循环分散每个点并传递各自的颜色。
Figure 5: Scatter Plot colored by class
折线图
在 Matplotlib 中,我们可以通过调用plot
方法来创建折线图。我们还可以在一个图形中绘制多个列,方法是循环遍历我们需要的列,并将每个列绘制在同一轴上。
Figure 6: Line Chart
柱状图
在 Matplotlib 中,我们可以使用hist
方法创建一个直方图。如果我们向它传递分类数据,如葡萄酒评论数据集中的 points 列,它将自动计算每个类出现的频率。
Figure 7: Histogram
条形图
可以使用bar
方法创建条形图。条形图不会自动计算类别的频率,所以我们将使用 pandas value_counts
函数来完成这项工作。条形图对于没有太多不同类别(少于 30 个)的分类数据非常有用,因为否则它会变得非常混乱。
Figure 8: Bar-Chart
熊猫可视化
Pandas 是一个开源的高性能、易于使用的库,它提供了数据结构(如数据帧)和数据分析工具(如我们将在本文中使用的可视化工具)。
熊猫可视化使得从熊猫数据帧和系列中创建情节变得非常容易。它还拥有比 Matplotlib 更高级的 API,因此我们需要更少的代码来获得相同的结果。
Pandas 可以使用 pip 或 conda 安装。
**pip install pandas
or
conda install pandas**
散点图
为了在 Pandas 中创建散点图,我们可以调用<dataset>.plot.scatter()
并向它传递两个参数,x 列的名称和 y 列的名称。可选地,我们也可以传递给它一个标题。
Figure 9: Scatter Plot
正如您在图像中看到的,它会自动将 x 和 y 标签设置为列名。
折线图
为了创建熊猫的折线图,我们可以称之为<dataframe>.plot.line()
。在 Matplotlib 中,我们需要循环遍历我们想要绘制的每一列,而在 Pandas 中,我们不需要这样做,因为它会自动绘制所有可用的数字列(至少如果我们没有指定特定的列)。
Figure 10: Line Chart
如果我们有一个以上的功能,熊猫会自动为我们创建一个图例,如上图所示。
柱状图
在熊猫中,我们可以用plot.hist
方法创建一个直方图。没有任何必需的参数,但是我们可以有选择地传递一些参数,比如 bin 的大小。
Figure 11: Histogram
创建多个直方图也非常容易。
Figure 12: Multiple Histograms
subplots
参数指定我们想要为每个特征单独绘图,而layout
指定每行和每列的绘图数量。
条形图
为了绘制条形图,我们可以使用plot.bar()
方法,但是在调用这个方法之前,我们需要获取数据。为此,我们将首先使用value_count()
方法对事件进行计数,然后使用sort_index()
方法从最小到最大对事件进行排序。
Figure 13: Vertical Bar-Chart
使用plot.barh()
方法制作水*条形图也非常简单。
Figure 14: Horizontal Bar-Chart
我们也可以绘制其他数据,然后是出现的次数。
Figure 15: Countries with the most expensive wine(on average)
在上面的例子中,我们按国家对数据进行分组,然后取葡萄酒价格的*均值,对其排序,并绘制出*均葡萄酒价格最高的 5 个国家。
海生的
Seaborn 是一个基于 Matplotlib 的 Python 数据可视化库。它为创建吸引人的图形提供了一个高级接口。
Seaborn 有很多东西可以提供。在 Matplotlib 中,你可以用一行创建几十行的图形。它的标准设计非常棒,而且它还有一个很好的界面来处理熊猫数据框。
可以通过键入以下内容来导入它:
**import seaborn as sns**
散点图
我们可以使用.scatterplot
方法创建散点图,就像在 Pandas 中一样,我们需要传递 x 和 y 数据的列名,但现在我们也需要传递数据作为附加参数,因为我们没有像在 Pandas 中那样直接调用数据上的函数。
Figure 16: Scatterplot
我们还可以使用hue
参数按类突出显示要点,这比在 Matplotlib 中容易得多。
Figure 17: Scatterplot colored by class
折线图
可使用sns.lineplot
方法创建折线图。唯一需要的参数是数据,在我们的例子中是 Iris 数据集中的四个数字列。我们也可以使用sns.kdeplot
方法,如果你的数据集中有很多异常值,这种方法会使曲线的边缘变圆,因此更干净。
Figure 18: Line Chart
柱状图
为了在 Seaborn 中创建直方图,我们使用了sns.distplot
方法。我们需要将我们想要绘制的列传递给它,它会自己计算出现的次数。如果我们想在图中画出高斯核密度估计值,我们也可以传递给它箱的数量。
Figure 19: Histogram
Figure 20: Histogram with gaussian kernel density estimate
条形图
在 Seaborn 中,可以使用sns.countplot
方法创建一个条形图,并将数据传递给它。
Figure 21: Bar-Chart
其他图表
现在你已经对 Matplotlib、Pandas Visualization 和 Seaborn 语法有了一个基本的了解,我想向你展示一些对提取内部有用的其他图形类型。
对他们中的大多数人来说,Seaborn 是首选库,因为它的高级接口只需要几行代码就可以创建漂亮的图形。
箱线图
方框图是显示五个数字汇总的图形方法。我们可以使用 seaborns sns.boxplot
方法创建箱线图,并向它传递数据以及 x 和 y 列名。
Figure 22: Boxplot
箱线图,就像条形图一样,对于只有几个类别的数据来说是很好的,但是会很快变得混乱。
热图
热图是数据的图形表示,其中包含在矩阵中的单个值用颜色表示。热点图非常适合探索数据集中要素的相关性。
为了获得数据集中特征的相关性,我们可以调用<dataset>.corr()
,这是一个 Pandas dataframe 方法。这将给我们相关矩阵。
我们现在可以使用 Matplotlib 或 Seaborn 来创建热图。
Matplotlib:
Figure 23: Heatmap without annotations
要向热图添加注释,我们需要添加两个 for 循环:
Figure 24: Heatmap with annotations
Seaborn 使创建热图和添加注释变得更加容易:
Figure 25: Heatmap with annotations
刻面
分面是将数据变量分解成多个子情节并将这些子情节组合成一个图形的行为。
如果想快速浏览数据集,分面真的很有帮助。
要在 Seaborn 使用一种刻面,我们可以使用FacetGrid
。首先,我们需要定义FacetGrid
并向它传递我们的数据以及一行或一列,它们将用于拆分数据。然后我们需要在我们的FacetGrid
对象上调用map
函数,并定义我们想要使用的绘图类型,以及我们想要绘制的列。
Figure 26: Facet-plot
你可以做出比上面例子更大更复杂的图。你可以在这里找到几个例子。
配对图
最后,我将向您展示 Seaborns pairplot
和 Pandas scatter_matrix
,它们使您能够在数据集中绘制成对关系的网格。
Figure 27: Pairplot
Figure 28: Scatter matrix
正如你在上面的图片中所看到的,这些技术总是将两个特征彼此结合在一起。图表的对角线用直方图填充,其他图是散点图。
推荐阅读
**** [## 抓取 Reddit 数据
如何使用 Python Reddit API 包装器从 Reddit 抓取数据(PRAW)
towardsdatascience.com](/scraping-reddit-data-1c0af3040768)****
结论
数据可视化是一门学科,它试图通过将数据置于可视化的环境中来理解数据,从而揭示出可能无法检测到的模式、趋势和相关性。
Python 提供了多个优秀的图形库,这些图形库包含了许多不同的特性。在本文中,我们研究了 Matplotlib、Pandas visualization 和 Seaborn。
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道,在社交媒体上关注我。
本文涵盖的代码可以从 Github 资源库获得。
如果你有任何问题、建议或批评,可以通过推特或评论区联系我。
决策智能简介
原文:https://towardsdatascience.com/introduction-to-decision-intelligence-5d147ddab767?source=collection_archive---------0-----------------------
人工智能时代领导力的新学科
好奇想知道在大草原上躲避狮子的心理与负责任的人工智能领导和设计数据仓库的挑战有什么共同点吗?欢迎来到决策智能!
决策智能是一门的新学科与选项选择的所有方面有关。它将最好的应用数据科学、社会科学和管理科学汇集到一个统一的领域,帮助人们使用数据改善他们的生活、业务和周围的世界。对于人工智能时代来说,这是一门至关重要的科学,涵盖了负责任地领导人工智能项目所需的技能,以及为大规模自动化设计目标、指标和安全网。
决策智能是在任何规模下将信息转化为更好行动的学科。
让我们浏览一下它的基本术语和概念。这些章节的设计有利于略读(也有跳读,也就是跳过无聊的部分……有时甚至完全跳过阅读)。
什么是决定?
数据很美,但重要的是决策。通过我们的决定——我们的行动——我们影响着周围的世界。
我们将单词“decision”定义为任何实体在选项之间的任何选择,因此对话的范围比 MBA 式的困境更广(比如是否在伦敦开设一家分公司)。
通过我们的决定——我们的行动——我们影响着周围的世界。
在这个术语中,在用户的照片上附加一个标签,如猫与非猫是由计算机系统执行的决定,而弄清楚是否启动该系统是由人类领袖深思熟虑后做出的决定(我希望!负责这个项目。
Decisions, decisions, decisions. Image: SOURCE
什么是决策者?
在我们的说法中,一个“ 决策者 ”不是那个突然出现否决项目团队阴谋的利益相关者或投资者,而是负责决策架构和上下文框架的人。换句话说,一个精心措辞的目标的创造者,而不是他们的破坏者。
什么是决策?
决策是一个不同学科使用不同的词,所以可以指:
- 当有其他选择时采取行动(在这个意义上,可以说是由计算机或蜥蜴做决策)。
- 履行(人类)决策者的职能,其中一部分是负责决策。尽管计算机系统可以执行决策,但它不能被称为决策者,因为它不对其输出承担责任——这一责任完全落在创造它的人类肩上。
计算与决策
并非所有的输出/建议都是决策。在决策分析术语中,只有当不可撤销的资源分配发生时才做出决策。只要你能免费改变你的想法,还没有做出任何决定。
决策智能分类法
学习决策智能的一种方法是按照传统路线将其分为定量方面(与应用 数据科学大部分重叠)和定性方面(主要由社会和管理科学的研究人员开发)。
定性方面:决策科学
构成定性方面的学科传统上被称为决策科学——我喜欢把整个事物都叫做决策科学(唉,我们不能总是得到我们想要的)。
Image: SOURCE
决策科学关心的问题有:
- 你应该如何建立决策标准和设计你的度量标准(全部)
- “您选择的指标是否与激励相容?”(经济学)
- “你应该以什么样的质量做出这个决定,你应该为完美的信息支付多少钱?”【决策分析】
- “情绪、启发和偏见如何影响决策?”(心理学)
- “像皮质醇水*这样的生物因素是如何影响决策的?”(神经经济学)
- “改变信息呈现方式如何影响选择行为?”(行为经济学)
- “在团队环境中做决策时,你如何优化你的结果?”(实验博弈论)
- “在设计决策环境时,您如何*衡众多约束和多阶段目标?”(设计)
- “谁将体验决策的后果,各种群体将如何看待这种体验?”(UX 研究)
- “决策客观道德吗?”【哲学】(T13)
这只是小试牛刀…还有更多!这也远远不是所涉及学科的完整列表。可以认为决策科学是以模糊的存储形式(人脑)来处理决策设置和信息处理,而不是以半永久性存储方式(纸质或电子形式)整齐地写下来的那种,我们称之为数据。
你大脑的问题
在上个世纪,赞美那些将大量数学知识投入到人类毫无察觉的努力中的人是一种时尚。采取定量的方法通常比轻率的混乱要好,但是有一种方法可以做得更好。
基于纯数学理性的策略相对幼稚,往往表现不佳。
基于纯数学理性而没有对决策和人类行为的定性理解的策略可能是相当幼稚的,并且相对于那些基于共同掌握定量和定性方面的策略来说,往往表现不佳。(请继续关注关于社会科学中理性历史的博客文章,以及心理学击败数学的行为博弈论的例子。)
人类不是优化者,我们是 满足者 ,这是对切角者的一个花哨说法。
人类不是优化者,我们是 满足者 ,这是一个对切角者的花哨称呼,他们满足于足够好而不是完美。(这也是一个足以打击我们人类傲慢的概念——这是对理性的、神圣的、完美的人的一记重拳——它值得获得诺贝尔奖。)
Aristotle thought that the brain was a glorified air conditioner for the heart. I guess the brain looks less impressive when it’s on the outside… Image: SOURCE
事实上,我们人类都使用认知启发法来节省时间和精力。这通常是件好事;在我们还没开始计算之前,想出完美的跑步路线来逃离大草原上的狮子会让我们被吃掉。满足感也降低了生活的卡路里成本,这是好事,因为我们的大脑是荒谬的耗电设备,尽管体重约为 3 磅,却吞噬了我们约五分之一的能量支出。(我打赌你总重量超过 15 磅,对吗?)
我们走的一些捷径会导致可预见的次优结果。
既然我们大多数人都不会整天躲避狮子,我们走的一些捷径会导致可预见的垃圾结果。我们的大脑并不完全适合现代环境。了解我们这个物种将信息转化为行动的方式,可以让你使用决策过程来保护自己免受自己大脑缺陷的影响(以及那些故意利用你本能的人的影响)。如果这个可怜的东西追赶达尔文的速度慢得惊人,它还可以帮助你构建工具,增强你的表现,并使你的环境适应你的大脑。
如果你认为人工智能把人类排除在外了,那就再想想吧!
顺便说一句,如果你认为人工智能将人类排除在等式之外,请三思!所有技术都是其创造者的反映,大规模运行的系统会放大人类的缺点,这就是为什么发展决策智能技能对于负责任的人工智能领导如此必要的一个原因。点击此处了解更多信息。
Image: SOURCE
也许你没有做决定
有时候,仔细思考你的决策标准会让你意识到世界上没有任何事实会改变你的想法——你已经选择了你的行动,现在你只是在寻找一种让它感觉更好的方式。这是一个有用的认识——它阻止你浪费更多的时间,帮助你在做你无论如何都要做的事情时转移你的情绪不适,让数据见鬼去吧。
“他用 统计 就像一个醉汉用灯柱……来支撑而不是照明。”——安德鲁·朗
除非你会对不同的未知事实采取不同的行动,否则这里没有决定…尽管有时决策分析的培训会帮助你更清楚地看到那些情况。
完全信息下的决策
现在想象一下,你已经非常小心地制定了一个决策,这个决策对事实非常敏感,你可以打响指来查看执行决策所需的事实信息。你需要数据科学做什么?没什么,就是这样。
当务之急应该是弄清楚我们会如何对事实做出反应。
没有什么比事实更好的了——你肯定知道的事情(是的,我知道这里有一个相对主义者的大兔子洞,让我们继续)——所以如果我们有事实,我们总是更喜欢根据事实做决定。这就是为什么当务之急应该是弄清楚我们想要如何处理事实。您希望将您的理想信息用于以下哪种用途?
Your author particularly enjoyed this wall in Jamaica. Image: SOURCE
你能用事实做什么?
- 你可以用事实做出一个重要的预先设定好的决定。如果它足够重要,你将需要大量依靠事物的定性方面来明智地制定你的决定。心理学家知道,如果你让自己遭到意外信息的袭击,它会以你不喜欢的方式操纵你,所以他们(和其他人)有很多话要说,如何提前选择你会接受的信息。
- 你可以利用事实做出一种特殊的预先框定的决策,称为影响(或因果)决策。如果你的决定是以采取行动导致某事发生为框架的,那么你需要因果关系的事实来做决定。在这种情况下,如果没有关于原因的事实(例如“因为抗生素”),关于效果的事实(例如“人们从这种疾病中康复”)对你是无用的。得到因果信息的方法是做一个受控的 实验 。另一方面,如果你正在做一个执行决定,作为对一个非因果事实的回应(例如,“如果我的储蓄账户里至少有 x ,我会给自己买双新鞋”),那么实验就没有必要了。
- 你可以用事实来支撑观点(“我预计外面是晴天”变成了“我知道外面是晴天”)。
- 你可以用事实来做出一个重要的基于生存的决定。基于存在的决策(“我刚刚发现隔壁有一个埃博拉病例,所以我马上离开这里……”)是这样的决策,以前未知的未知的存在动摇了你的方法的基础,以至于你事后意识到你的决策背景是草率制定的。
- 您可以使用事实来自动化大量决策。在传统编程中,人类指定一组指令,用于将事实输入转换成适当的动作,可能涉及类似查找表的东西。
- 您可以使用事实来揭示自动化解决方案。通过查看关于系统的事实,您可以基于它们编写代码。比起在没有任何信息的情况下绞尽脑汁想出解决方案的结构,这是一种更好的传统编程方法。例如,如果您不知道如何将摄氏温度转换为华氏温度,但是您可以使用数据集来查找与摄氏温度输入相匹配的华氏温度条目…但是如果您分析该查找表本身,您会发现将它们联系起来的公式。然后,您只需编写一个公式(“模型”)来为您完成您的脏工作,丢掉笨重的表格。
- 您可以使用事实来生成自动化问题的最佳解决方案,这是完全可以解决的。这是传统的优化。你会在运筹学领域找到很多例子,其中包括如何争论约束以获得理想结果,比如完成一系列任务的最佳顺序。
- 你可以用事实来启发你如何做未来的重要决定。这是分析的一部分,也属于部分信息部分。保持这种想法!
- 你可以用事实来评估你正在处理的事情。这有助于您了解可用于未来决策的输入类型,并设计如何更好地管理您的信息。如果你刚刚继承了一个充满潜在成分的又大又黑的(数据)仓库,你不会知道里面有什么,直到有人看了它。幸运的是,你的分析师有手电筒和旱冰鞋。
- 你可以草率地用事实做出没有框架的决定。当决策的风险足够低,以至于不值得花力气去仔细对待它们时,这种方法是有效的,例如,“我今天午餐应该吃什么?”试图在所有决策上始终保持严格会产生次优的长期/终生结果,并且属于无意义的完美主义。把你的努力留到足够重要的情况下,但是请不要忘记,即使使用低质量低努力的方法是有效的,最佳决策方法仍然是低质量的。当这是你的方法时,你不应该捶胸顿足或过于自信…如果你抄*路,你拿着的东西是脆弱的。有些情况下,脆弱可以完成工作,但这不会突然让你的结论变得坚定。不要靠在上面。如果你想要高质量的决策,你需要一个更严谨的方法。
通过决策科学的培训,你学会了减少做出基于事实的严格决策所需的努力,这意味着同样的工作量现在可以让你全面获得更高质量的决策。这是一项非常有价值的技能,但是需要大量的工作来磨练它。例如,行为经济学的学生养成了在信息之前设定决策标准的习惯。例如,我们这些从要求非常高的决策科学培训项目中受到打击的人不禁会问自己,在我们查询票价之前,我们最多会为一张票支付多少钱。
数据收集和数据工程
如果我们有事实,我们早就完事了。唉,我们生活在现实世界中,经常我们必须为我们的信息工作。数据工程是一门复杂的学科,致力于大规模可靠地获取信息。就像去杂货店买一品脱冰淇淋很容易一样,当所有可用的相关信息都在一个电子表格中时,数据工程也很容易。
Image: SOURCE
当你开始要求运送 200 万吨冰淇淋时,事情就变得棘手了……在那里冰淇淋是不允许融化的!如果你必须设计、建立和维护一个巨大的仓库,事情会变得更加棘手,你甚至不知道未来会要求你储存什么——也许是几吨鱼,也许是钚……祝你好运!
当你甚至不知道下周你将被要求储存什么时,建立一个仓库是很棘手的——也许是几吨鱼,也许是钚…祝你好运!
虽然数据工程是一个独立的姐妹学科,也是决策智能的主要合作者,但决策科学在建议设计和管理事实收集方面有着深厚的专业传统。
定量方面:数据科学
当你制定了你的决定,并且使用搜索引擎或分析师(为你扮演人肉搜索引擎的角色)查找了你需要的所有事实,剩下的就是执行你的决定。你完了!不需要花哨的数据科学。
如果在所有的跑腿工作和工程柔术之后,交付的事实并不是您理想的决策所需的事实呢?如果它们只是部分事实呢?也许你想要明天的事实,但你只有过去能通知你。(记不住未来的时候好烦。)也许你想知道你所有的潜在用户对你的产品的看法,但是你只能问一百个用户。然后你就在处理不确定性!你知道的并不是你希望知道的。进入数据科学!
当你被迫超越数据时,数据科学变得有趣了……但是一定要小心避免伊卡洛斯式的混乱!
自然,当你拥有的事实不是你需要的事实时,你应该期待你的方法会改变。也许它们是一个更大拼图中的一块拼图(就像来自更大的人口的样本一样)。也许它们是错误的谜题,但却是你最好的谜题(就像用过去预测未来一样)。当你被迫跨越数据时,数据科学变得有趣起来……但是一定要小心避免伊卡洛斯式的重击!
- 你可以利用部分事实,通过统计推断做出一个重要的预先设定的决定,用假设补充你已有的信息,看看你是否应该改变你的行动。这是 Frequentist(古典)统计。如果你正在做一个影响决策(框架为采取行动导致某事发生,例如“如果导致更多人访问你的网站,你只想将你的标志颜色改为橙色”),那么最好使用来自随机控制 实验 的数据。如果你正在做一个执行的决定(例如“如果至少 25%的用户认为橙色是他们最喜欢的颜色,你只想把你的标志颜色改成橙色”),一个调查或观察研究就足够了。
- 你可以利用部分事实合理地将观点更新为更有见识的(但仍然是不完善的和个人的)观点。这是贝叶斯统计。如果这些观点涉及因果关系,最好使用来自受控随机实验的数据。
- 你的部分事实可能包含关于存在的事实,这意味着你可以在事后利用它们做出基于存在的决定(见上文)。
- 您可以使用部分事实来自动化大量决策。这是传统的编程,使用类似查找表的东西,将你以前没有见过的东西转换成你拥有的最接*的东西,然后照常进行。(简而言之,这就是 k-NN 所做的……当果壳中有更多的东西时,它通常会工作得更好。)
- 您可以使用部分事实来激发自动化解决方案。通过查看系统的部分事实,您仍然可以基于您所看到的内容编写代码。这是分析。
- 你可以使用部分事实为一个不完美的可解自动化问题生成一个体面的解决方案,这样你就不必自己想出这个方案。这是机器学习和 AI 。
- 你可以用部分事实来启发你如何做未来的重要决定。这是分析。
- 你可以使用部分事实来理解你正在处理的事情(见上文),并通过高级分析来加速自动化解决方案的开发,例如通过激发新的方法来将信息融合在一起,以制作有用的模型输入(行话是“特征工程”)或在人工智能项目中尝试新的方法。
- 你可以草率地使用部分事实来做出无框架的决定,但是要注意质量甚至比你草率地使用事实时还要低,因为你实际知道的与你希望知道的差了一步。
对于所有这些用途,都有办法整合来自各种以前孤立的学科的智慧,以便更有效地制定决策。这就是什么是决策智能!它汇集了对决策的不同观点,使我们所有人更加强大,并给予他们新的声音,摆脱他们最初研究领域的传统限制。
To return to the kitchen analogy for AI, if research AI is building microwaves and applied AI is using microwaves, decision intelligence is using microwaves safely to meet your goals and using something else when you don’t need a microwave. The goal (objective) is always the starting point for decision intelligence. Image: SOURCE
如果你想了解更多,我这里关于 Medium.com 的大部分文章都是从决策智能的角度写的。我的启动人工智能项目的指南可能是最不微妙的,所以如果你还没有通过这篇文章中的链接选择你自己的冒险,我推荐你去那里潜水。
感谢阅读!人工智能课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
Enjoy the entire course playlist here: bit.ly/machinefriend
Keras 深度学习简介
原文:https://towardsdatascience.com/introduction-to-deep-learning-with-keras-17c09e4f0eb2?source=collection_archive---------3-----------------------
如何使用 Keras 深度学习库
Figure 1: Photo by Blake Connally on Unsplash
Keras 是一个高级神经网络 API,能够运行在 Tensorflow 、 Theano、和 CNTK 之上。它通过高级、用户友好、模块化和可扩展的 API 实现快速实验。Keras 也可以在 CPU 和 GPU 上运行。
Keras 由 Francois Chollet 开发和维护,是 Tensorflow 核心的一部分,这使其成为 tensor flow 首选的高级 API。
本文是解释如何使用 Keras 进行深度学习的系列文章的第一篇。
在本文中,我们将介绍 Keras 的基础知识,包括两个最常用的 Keras 模型(顺序和功能)、核心层以及一些预处理功能。
安装 Keras
我假设你已经有了一个可以工作的 Tensorflow 或 Theano 或 CNTK。如果你不检查上面的链接。
Keras 可以使用 pip 或 conda 安装:
pip install keras
or
conda install keras
在数据集中加载
Keras 提供了七个不同的数据集,可以使用 Keras 直接加载。这些包括图像数据集以及房价和电影评论数据集。
在本文中,我们将使用 MNIST 数据集 ,,它包含 70000 张 28x28 灰度图像和 10 个不同的类别。Keras 将其分为一个包含 60000 个实例的训练集和一个包含 10000 个实例的测试集。
为了将图像输入到卷积神经网络中,我们将数据帧转换为四维。这可以使用 numpys reshape
方法来完成。我们还将把数据转换成浮点数,并使其正常化。
我们还将使用 Keras 的to_categorical
方法将我们的标签转换成一键编码。
使用顺序 API 创建模型
在 Keras 中创建模型最简单的方法是使用顺序 API,它允许您一层一层地堆叠。顺序 API 的问题是,它不允许模型有多个输入或输出,而这对于某些问题是需要的。
然而,对于大多数问题,顺序 API 是一个完美的选择。
要创建一个卷积神经网络,我们只需要创建一个Sequential
对象,并使用add
函数添加层。
上面的代码首先创建了一个Sequential
对象,并添加了一些卷积、最大池和漏失层。然后,它使输出变*,并在将其传递给输出层之前,将其传递给最后一个密集层和漏失层。如果你没有信心建立一个卷积神经网络(CNN ),看看这个伟大的教程。
顺序 API 还支持另一种语法,其中层被直接传递给构造函数。
使用函数式 API 创建模型
或者,函数式 API 允许您创建相同的模型,但是以简单性和可读性为代价为您提供了更多的灵活性。
它可用于多个输入和输出图层以及共享图层,从而使您能够构建真正复杂的网络结构。
当使用函数式 API 时,我们总是需要将前一层传递给当前层。它还需要使用输入层。
函数式 API 也经常用于迁移学习,我们将在另一篇文章中讨论。
编译模型
在开始训练我们的模型之前,我们需要配置学习过程。为此,我们需要指定一个优化器、一个损失函数和一些可选的度量标准,如准确性。
损失函数是对我们的模型在实现给定目标方面有多好的度量。
优化器用于通过使用梯度更新权重来最小化损失(目标)函数。
扩充图像数据
扩充是从现有数据中创建更多数据的过程。对于图像,你可以做一些小的变换,比如旋转图像,放大图像,添加噪声等等。
这有助于使模型更加稳健,并解决没有足够数据的问题。Keras 有一个叫做ImageDataGenerator
的方法,可以用来扩充图像。
这个ImageDataGenerator
将创建已经旋转、放大或缩小、宽度和高度发生变化的新图像。
符合模型
既然我们已经定义并编译了我们的模型,那么就可以开始训练了。为了训练一个模型,我们通常会使用fit
方法,但是因为我们使用的是数据生成器,我们将使用fit_generator
并向其传递我们的生成器、X 数据、y 数据以及历元数和批量大小。我们还将向它传递一个验证集,以便我们可以监控这两个集的损失和准确性,以及使用生成器时所需的 steps_per_epoch,它被设置为训练集的长度除以 batch_size。
这将输出:
Epoch 1/5
1875/1875 [==============================] - 22s 12ms/step - loss: 0.1037 - acc: 0.9741 - val_loss: 0.0445 - val_acc: 0.9908
Epoch 2/5
1875/1875 [==============================] - 22s 12ms/step - loss: 0.0879 - acc: 0.9781 - val_loss: 0.0259 - val_acc: 0.9937
Epoch 3/5
1875/1875 [==============================] - 22s 12ms/step - loss: 0.0835 - acc: 0.9788 - val_loss: 0.0321 - val_acc: 0.9926
Epoch 4/5
1875/1875 [==============================] - 22s 12ms/step - loss: 0.0819 - acc: 0.9792 - val_loss: 0.0264 - val_acc: 0.9936
Epoch 5/5
1875/1875 [==============================] - 22s 12ms/step - loss: 0.0790 - acc: 0.9790 - val_loss: 0.0220 - val_acc: 0.9938
可视化培训过程
我们可以可视化每个时期的训练和测试精度和损失,这样我们就可以直观地了解模型的性能。各代的精度和损失保存在我们训练时获得的历史变量中,我们将使用 Matplotlib 来可视化这些数据。
Figure 2: Training/Testing accuracy over epochs
Figure 3: Training/Testing loss over epochs
在上面的图表中,我们可以看到我们的模型没有过度拟合,我们可以训练更多的纪元,因为验证损失仍在减少。
推荐读物
[## 使用 Keras 构建图书推荐系统
如何使用嵌入创建图书推荐系统?
towardsdatascience.com](/building-a-book-recommendation-system-using-keras-1fba34180699)
结论
Keras 是一个高级神经网络 API,能够运行在 Tensorflow 、 Theano 和 CNTK 之上。它通过高级、用户友好、模块化和可扩展的 API 以及在 CPU 和 GPU 上运行来实现快速实验。
本文是介绍 Keras 工作原理的系列文章的第一篇。在这篇文章中,我们讨论了安装以及如何创建一个简单的卷积神经网络。
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道并在社交媒体上关注我。
本文涵盖的代码可以从 Github 资源库获得。
如果您有任何问题、建议或批评,可以通过 Twitter 或评论区联系我。
使用 dtplyr 加速数据争论
原文:https://towardsdatascience.com/introduction-to-dtplyr-783d89e9ae56?source=collection_archive---------12-----------------------
了解如何轻松地将dplyr
的可读性与data.table
的性能结合起来!
我最*看到了哈德利·韦翰关于《T2》上映的推文。这是一个支持在data.table
对象上使用dplyr
语法的包。dtplyr
自动将dplyr
语法翻译成等价的data.table
,最终导致性能提升。
漫威:无限战争是历史上最雄心勃勃的跨界事件。哈德利·韦翰:拿着我的啤酒。
我一直很喜欢dplyr
的易用性和可读性,也很渴望对比一下软件包的性能。让我们看看它在实践中是如何工作的!
加载库
对于本文,我们需要通过运行devtools::install_github(“tidyverse/dtplyr”)
从 GitHub 安装dtplyr
,我们使用microbenchmark
进行性能比较。
生成数据集
我们生成一个人工数据集。我首先想到的是订单注册表,我们在其中存储:
id
客户端的name
产品的date
采购amount
购买的产品- 某一产品的单位
price
由于这只是一个玩具示例,我们不会深入研究数据集背后的逻辑。我们可以同意这有点像现实生活中的场景。为了测试不同方法的性能,我们生成了 1000 万行数据。
通过使用lazy_dt()
我们触发了惰性评估——直到我们通过使用as.data.table()
、as.data.frame()
或as_tibble()
明确请求它,才执行任何计算。为了便于比较,我们储存一个data.frame
,一个data.table
,一个【懒人】data.table
。
我们可以通过打印结果来预览转换以及生成的data.table
代码:
**Source:** local data table [?? x 3]
**Call:** `_DT3`[date < as.Date("2019-02-01"), .(id, product, date)][order(date)] id product date
*<chr>* *<chr>* *<date>*
1 DHQ GVF 2019-01-01
2 NUB ZIU 2019-01-01
3 CKW LJH 2019-01-01
4 AZO VIQ 2019-01-01
5 AQW AGD 2019-01-01
6 OBL NPC 2019-01-01
通常,这应该用于调试。我们应该指出我们希望在管道末端接收哪种类型的对象,以清楚地表明我们已经完成了转换。
用例 1:过滤、选择和排序
假设我们想要一个 2019 年 2 月 1 日之前发生的交易列表,按日期排序,我们不关心金额或价格。
我们看到dtplyr
比data.table
稍慢,但是通过观察中间时间,它比dplyr.
快了大约 4 倍
用例 2:过滤后添加新变量
在本例中,我们要过滤产品数量超过 5000 的订单,并计算订单值,即amount * price
。
大部分使用mutate()
的表达式必须复制(不要原地修改),直接使用data.table
就没必要了。为了应对这种情况,我们可以在lazy_dt()
中指定immutable = FALSE
来退出上述行为。
这一次,差异没有那么明显。当然,这取决于对表进行操作的复杂性。
用例 3:顶层聚合
假设我们想要:
- 根据金额<= 4000
- Calculate the average order value per customer
This time we get ~3x improvement in median execution time.
Use-case 4: Joining
In the last example, we consider a case of joining datasets. For that, we create a new 【 / 【 called 【 by selecting 75% of the available products and assigning a random letter to them. We can assume that the letter corresponds to a distribution center (variable called 【 ), from which the item is shipped.
We want to calculate the average order value per distribution center. In case we do not have data regarding the distribution center, we discard the row.
Again we see a ~3x speedup in the median execution time.
Conclusions
【 is (and always will be) slightly slower than 【 . That is because:
1. Each 【 verb must be converted to a 【 equivalent. For large datasets, this should be negligible, as these translation operations take time proportional to the complexity of the input code, rather than the amount of data.
2 过滤所有订单。一些data.table
表达式没有直接的dplyr
等价物。
3。用例 2 中提到的不变性问题。
综上所述,我认为dtplyr
是对tidyverse
的一个有价值的补充,因为只需对dplyr
代码做很小的改动,我们就可以实现显著的性能提升。
一如既往,我们欢迎任何建设性的反馈。你可以在推特上或评论中联系我。你可以在我的 GitHub 上找到本文使用的代码。
联合学习和隐私保护简介
原文:https://towardsdatascience.com/introduction-to-federated-learning-and-privacy-preservation-75644686b559?source=collection_archive---------14-----------------------
使用 PySyft 框架的联邦学习和附加秘密共享。
深度学习包括对存在于多个客户端设备上的大量高质量分散数据进行训练。该模型在客户端设备上被训练,因此不需要上传用户的数据。将个人数据保存在客户的设备上,使他们能够直接和实际控制自己的数据。
Figure 1: Federated Learning
服务器在预先可用的代理数据上训练初始模型。初始模型被发送到选定数量的合格客户端设备。合格标准确保用户的体验不会因为试图训练模型而被破坏。选择最佳数量的客户端设备来参与训练过程。处理完用户数据后,模型更新将与服务器共享。服务器聚集这些梯度并改进全局模型。
所有的模型更新都在内存中进行处理,而在服务器上只持续很短的一段时间。然后,服务器将改进的模型发送回参与下一轮训练的客户端设备。达到所需的精确度后,设备上的模型可以根据用户的个性化进行调整。然后,他们不再有资格参加培训。在整个过程中,数据不会离开客户端设备。
这与分散计算有什么不同?
联合学习与分散计算的不同之处在于:
- 客户端设备(如智能手机)的网络带宽有限。它们不能传输大量数据,上传速度通常低于下载速度。
- 客户端设备并不总是能够参与训练会话。最佳条件,如充电状态、连接到未计量的 Wi-Fi 网络、空闲等。并不总是可以实现的。
- 设备上的数据更新很快,并且不总是相同的。[数据并不总是可以获得。]
- 客户端设备可以选择不参与培训。
- 可用的客户端设备数量非常多,但是不一致。
- 联合学习将隐私保护与大规模群体的分布式训练和聚合结合在一起。
- 数据通常是不*衡的,因为数据是用户特定的并且是自相关的。
联合学习是“将代码带给数据,而不是将数据带给代码”这种更普遍方法的一个例子,它解决了数据的隐私、所有权和位置等基本问题。
在联合学习中:
- 某些技术用于压缩模型更新。
- 执行质量更新,而不是简单的梯度步骤。
- 在执行聚合之前,由服务器添加噪声,以掩盖个体对学习模型的影响。[全局差分隐私]
- 如果渐变更新太大,则会被裁剪。
PYSYFT 简介
我们将使用 PySyft 实现一个联邦学习模型。PySyft 是一个用于安全和私有深度学习的 Python 库。
装置
PySyft 要求 Python >= 3.6 和 PyTorch 1.1.0。确保你符合这些要求。
基础
让我们从导入库和初始化钩子开始。
这样做是为了覆盖 PyTorch 的方法,在一个 worker 上执行命令,这些命令在本地 worker 控制的 tensors 上调用。它还允许我们在工人之间移动张量。工人解释如下。
Jake has: {}
虚拟工作者是存在于我们本地机器上的实体。它们用于模拟实际工人的行为。
为了与分布在网络中的工作者一起工作,PySyft 提供了两种类型的工作者:
- 网络套接字工人
- Web 套接字工人
Web sockets workers 可以从浏览器实例化,每个 worker 位于一个单独的选项卡上。
在这里,Jake 是我们的虚拟工作者,可以将其视为设备上的一个独立实体。我们给他发些数据吧。
x: (Wrapper)>[PointerTensor | me:50034657126 -> jake:55209454569]
Jake has: {55209454569: tensor([1, 2, 3, 4, 5])}
当我们向 Jake 发送一个张量时,我们返回一个指向这个张量的指针。所有的操作都将通过这个指针来执行。这个指针保存另一台机器上的数据信息。现在, x 是一个点张量。
使用 get() 方法从杰克的设备中获取 x 的值。然而,这样做的话,杰克设备上的张量就被删除了。
x: tensor([1, 2, 3, 4, 5])
Jake has: {}
当我们将 PointTensor x (指向 Jake 机器上的一个张量)发送给另一个工人 John 时,整个链被发送给 John,并返回一个指向 John 设备上的节点的 PointTensor。张量仍在杰克的设备上。
x: (Wrapper)>[PointerTensor | me:70034574375 -> john:19572729271]
John has: {19572729271: (Wrapper)>[PointerTensor | john:19572729271 -> jake:55209454569]}
Jake has: {55209454569: tensor([1, 2, 3, 4, 5])}
Figure 2: Using the send() method on a PointTensor [Step 2].
方法的作用是:从一个工作线程中移除所有的对象。
Jake has: {}
John has: {}
假设我们想把一个张量从杰克的机器移到约翰的机器上。我们可以通过使用 send() 方法将“指向张量的指针”发送给 John,并让他调用 get() 方法。PySfyt 为此提供了一个 remote_get() 方法。还有一个方便的方法——move(),来执行这个操作。
(Wrapper)>[PointerTensor | me:86076501268 -> john:86076501268]
Jake has: {}
John has: {86076501268: tensor([ 6, 7, 8, 9, 10])}
Figure 3: Using the move() method on a PointTensor. [Step 2]
战略
我们可以通过以下步骤在客户端设备上执行联合学习:
- 将模型发送到设备,
- 使用设备上的数据进行正常训练,
- 拿回更聪明的模型。
然而,如果有人截获了与服务器共享的 smarter 模型,他可以执行逆向工程并提取关于数据集的敏感数据。差分隐私方法解决了这个问题并保护了数据。
当更新被发送回服务器时,服务器在聚集梯度时不应该能够辨别。让我们使用一种叫做附加秘密共享的加密形式。
我们希望在执行聚合之前加密这些梯度(或模型更新),这样就没有人能够看到梯度。我们可以通过附加秘密共享来实现这一点。
附加秘密共享
在秘密共享中,我们将一个秘密分成多个份额,并在一组秘密持有者中分发。秘密 x 只有当它被分割成的所有份额都可用时才能被构造。
比如说我们把 x 拆分成 3 份: x1 、 x2、和 x3 。我们随机初始化前两个份额,计算第三个份额为x3=x-(x1+x2)。然后我们将这些股份分配给三个秘密持有者。这个秘密仍然是隐藏的,因为每个人只持有一份,不知道总价值。
我们可以通过选择股票价值的范围来使其更加安全。设大质数 Q 为上限。现在第三份, x3 ,等于Q-(x1+x2)% Q+x。
Shares: (6191537984105042523084, 13171802122881167603111, 4377289736774029360531)
Figure 4: Encrypting x in three shares.
解密过程将股份求和在一起得到模数 Q 。
Value after decrypting: 3
Figure 5: Decrypting x from the three shares.
同态加密
同态加密是一种加密形式,它允许我们对加密的操作数执行计算,从而产生加密的输出。解密后的加密输出与对实际操作数执行相同计算得到的结果相匹配。
附加秘密共享技术已经具有同态性质。如果我们把 x 拆分成 x1 、 x2、和 x3 ,把 y 拆分成 y1 、 y2、和 y3 ,那么 x+y 就等于三份之和解密后的值:( x1+y1
Shares encrypting x: (17500273560307623083756, 20303731712796325592785, 9677254414416530296911)
Shares encrypting y: (2638247288257028636640, 9894151868679961125033, 11208230686823249725058)
Sum of shares: (20138520848564651720396, 6457253737716047231095, 20885485101239780021969)
Sum of original values (x + y): 14
我们能够在不知道 x 和 y 的值的情况下计算聚合函数加法的值。
使用 PYSYFT 的秘密共享
PySyft 提供了一个 share() 方法,将数据拆分成附加的秘密份额,并发送给指定的 workers。为了处理十进制数, fix_precision() 方法用于将小数表示为整数值。
Jake has: {}
John has: {}
Secure_worker has: {}
份额法用于在几个工人之间分配股份。每个指定的工人都得到一份,但不知道实际价值。
x: (Wrapper)>[AdditiveSharingTensor]
-> (Wrapper)>[PointerTensor | me:61668571578 -> jake:46010197955]
-> (Wrapper)>[PointerTensor | me:98554485951 -> john:16401048398]
-> (Wrapper)>[PointerTensor | me:86603681108 -> secure_worker:10365678011]
*crypto provider: me*
Jake has: {46010197955: tensor([3763264486363335961])}
John has: {16401048398: tensor([-3417241240056123075])}
Secure_worker has: {10365678011: tensor([-346023246307212880])}
如您所见, x 现在分别指向 Jake、John 和 Secure_worker 机器上的三个共享。
Figure 6: Encryption of x into three shares.
Figure 7: Distributing the shares of x among 3 VirtualWorkers.
(Wrapper)>[AdditiveSharingTensor]
-> (Wrapper)>[PointerTensor | me:86494036026 -> jake:42086952684]
-> (Wrapper)>[PointerTensor | me:25588703909 -> john:62500454711]
-> (Wrapper)>[PointerTensor | me:69281521084 -> secure_worker:18613849202]
*crypto provider: me*
Figure 8: Encryption of y into 3 shares.
Figure 9: Distributing the shares of y among 3 VirtualWorkers.
(Wrapper)>[AdditiveSharingTensor]
-> (Wrapper)>[PointerTensor | me:42086114389 -> jake:42886346279]
-> (Wrapper)>[PointerTensor | me:17211757051 -> john:23698397454]
-> (Wrapper)>[PointerTensor | me:83364958697 -> secure_worker:94704923907]
*crypto provider: me*
注意将 x 和 y 相加后得到的 z 的值存储在三台工人机中。 z 也加密了。
Figure 10: Performing computation on encrypted inputs.
tensor([14])
Figure 11: Decryption of result obtained after computation on encrypted inputs.
在对加密的份额执行加法之后获得的值等于通过将实际数字相加获得的值。
使用 PYSYFT 的联邦学习
现在,我们将使用两个工人:杰克和约翰,实现联合学习方法,在 MNIST 数据集上训练一个简单的神经网络。应用联邦学习方法只需要做一些修改。
- 导入库和模块。
2.加载数据集。
在实际应用中,数据存在于客户端设备上。为了复制这个场景,我们向虚拟工作者发送数据。
请注意,我们以不同的方式创建了训练数据集。 train_set.federate((jake,john)) 创建了一个 FederatedDataset ,其中 train_set 在 jake 和 john(我们的两个虚拟工作者)之间被拆分。 FederatedDataset 类旨在像 PyTorch 的数据集类一样使用。将创建的 FederatedDataset 传递给联邦数据加载器“ FederatedDataLoader ”,以联邦的方式对其进行迭代。这些批次来自不同的设备。
3.建立模型
4.训练模型
因为数据存在于客户端设备上,所以我们通过 location 属性获得它的位置。对代码的重要补充是从客户端设备取回改进的模型和损失值的步骤。
Epoch: 1 [ 0/60032 ( 0%)] Loss: 2.306809
Epoch: 1 [ 6400/60032 ( 11%)] Loss: 1.439327
Epoch: 1 [12800/60032 ( 21%)] Loss: 0.857306
Epoch: 1 [19200/60032 ( 32%)] Loss: 0.648741
Epoch: 1 [25600/60032 ( 43%)] Loss: 0.467296
...
...
...
Epoch: 5 [32000/60032 ( 53%)] Loss: 0.151630
Epoch: 5 [38400/60032 ( 64%)] Loss: 0.135291
Epoch: 5 [44800/60032 ( 75%)] Loss: 0.202033
Epoch: 5 [51200/60032 ( 85%)] Loss: 0.303086
Epoch: 5 [57600/60032 ( 96%)] Loss: 0.130088
5.测试模型
Test set: Average loss: 0.2428, Accuracy: 9300/10000 (93%)
就是这样。我们已经使用联合学习方法训练了一个模型。与传统训练相比,使用联邦方法训练模型需要更多的时间。
保护模型
在客户端设备上训练模型保护了用户的隐私。但是,模特的隐私呢?下载模型会威胁到组织的知识产权!
安全多方计算由秘密加法共享组成,为我们提供了一种在不公开模型的情况下进行模型训练的方法。
为了保护模型的权重,我们在客户端设备之间秘密共享模型。
要做到这一点,需要对上面的联邦学习示例进行一些更改。
如使用 PYSYFT 的秘密共享部分所示,现在是模型、输入、模型输出、权重等。也会被加密。处理加密的输入将产生加密的输出。
参考
[1] Theo Ryffel,Andrew Trask,Morten Dahl,Bobby Wagner,Jason Mancuso,Daniel Rueckert,Jonathan Passerat-Palmbach,保护隐私的深度学习通用框架(2018) ,arXiv
[2] Andrew Hard,Kanishka Rao,Rajiv Mathews,Swaroop Ramaswamy,Franç oise Beaufays,Sean Augenstein,Hubert Eichner,Chloé Kiddon,Daniel Ramage,用于移动键盘预测的联邦学习(2019) ,arXiv
[3]基思·博纳维茨、休伯特·艾希纳、沃尔夫冈·格里斯坎普、迪米特里·胡巴、亚历克斯·英格曼、弗拉基米尔·伊万诺夫、克洛伊·基登、雅各布·科涅纳、斯特凡诺·马佐基、h .布伦丹·麦克马汉、蒂蒙·范·奥弗代尔、戴维·彼得鲁、丹尼尔·拉梅奇、杰森·罗斯兰德、《走向大规模联合学习:系统设计》(2019) 、arXiv
[4] Brendan McMahan,Daniel Ramage,联合学习:没有集中训练数据的协作机器学习(2017) ,谷歌 AI 博客
[5]苹果差分隐私团队,大规模隐私学习(2017) ,苹果机器学习杂志
[6] Daniel Ramage,Emily Glanz,联合学习:分散数据上的机器学习(2019) ,Google I/O'19
[7] OpenMind, PySyft ,GitHub
虚拟游戏介绍
原文:https://towardsdatascience.com/introduction-to-fictitious-play-12a8bc4ed1bb?source=collection_archive---------16-----------------------
理解强化学习中自我游戏的第一步
Photo by Mpho Mojapelo on Unsplash
更新:学习和练习强化学习的最好方式是去 http://rl-lab.com
虚拟游戏是一个博弈论概念。它包括分析游戏,找出在零和游戏中面对对手时采取的最佳策略。
这通常是一个沉重的主题,所以我们将从一些重要的定义开始,然后我们将解释虚拟游戏算法。
零和对策
零和游戏是一种游戏,其中一个玩家获得的分数是其他玩家的损失。以这种方式,归属于玩家的所有分数的总和等于零。例如,如果玩家 I 赢了 5 分,那么玩家 II 输了 5 分。
游戏价值
游戏价值(V)是玩家在玩了足够多的次数后,*均期望赢得(或输掉)的点数、金钱、信用等。如果 V 为正,我们认为它有利于参与人 I(所以参与人 II 必须支付),如果 V 为负,我们认为它有利于支付者 II(所以参与人 I 必须支付)。
纳什均衡
纳什均衡是一种状态,在这种状态下,任何参与者都没有兴趣改变自己的策略,因为任何改变都会遭到他人的反击。纳什均衡并不意味着最优均衡,一个或多个参与者可能会有一个对他们更有利的策略,但他们不能采用的原因是因为对手(假设足够聪明)会反击他们,最终结果会变得不利。你可以认为这是一个僵局,但它也可能对所有人都有利。
一个简单的例子是想象两个强盗把他们的抢劫分成两半。如果其中一人向警方告发另一人,他可以得到全部赃物,但他没有兴趣这样做,因为另一个人也会告发他,他们最终都会进监狱。所以一分为二对他们俩来说都是最好的解决方案。
为什么我们要在人工智能中寻找纳什均衡?
理论上,纳什均衡将保证*均没有损失。这意味着在相当多的游戏中,*均而言,人工智能将会*局或获胜。
然而,在实践中,这是比较乐观的。当与人类对战时,人类玩家很有可能会在某一点上犯错误,而人工智能会利用这一点来获胜。
另一个重要的问题是,为什么人工智能不寻求纳什均衡,而是研究人类的策略,并利用它来获胜。这种方法的风险是,人类可以学会欺骗人工智能,给它一种他们正在使用某种策略的印象,然后切换到另一种策略。
例如假设在游戏石头剪刀布中,人类连续给出 3 把剪刀,这导致 AI 假设这是人类的策略。下一步,AI 会用石头反击,但是人类(放置陷阱的人)会用纸。
所以这个游戏中的最佳策略是坚持纳什均衡,使用随机策略(随机选择物品)。
虚拟游戏
虚拟博弈是乔治·w·布朗在 1951 年定义的一种方法,它由零和博弈组成,每个参与者对对手的策略做出最佳反应。该方法的目的是以迭代的方式找到游戏值。
通常,当问题变得复杂时,迭代法比解析法更容易计算。
虚拟方法被证明收敛于理论博弈值(V)。还证明了在两人零和博弈中虚拟博弈收敛于纳什均衡。
玩虚拟游戏
考虑下面的奇数或偶数游戏:
两个玩家 I 和 II 各自可以抽取数字“1”或“2”,如果抽取的数字之和是偶数,玩家 I 向玩家 II 支付该和,在下面的矩阵中用(-2 和-4)表示,如果该和是奇数,则玩家 II 向玩家 I 支付该和,用(+3 和+3)表示。
这个问题可以用解析的方法来解决,如果玩家 I 以 7/12 的概率玩“1”,以 5/12 的概率玩“2”,那么*均来说,玩家 I 会赢 1/12(这个方法的细节在这里并不重要)。
下图详细描述了迭代是如何展开的:
迭代#1 参与人 I 对抗选择“1”的参与人 II 的行动,参与人 I 的目标是最大化他的收益,所以他选择“2”,它的值是 max(-2,3) = 3。选择的值用青色标记。
在迭代#2 中,参与人 II 必须对抗选择“2”的参与人 I,他的目标是最小化参与人 I 的收益,所以他选择“2”,导致 min(3,-4) = -4。选择的值用黄色标记。
迭代#3,参与人 I 通过选择画“1”或“2”来对抗参与人 II,数值将取自第二列(记住参与人 II 在前一次迭代中选择了“2”)。这一列的值会加到参与人 I 的期望值上,意思是(-2+3 = 1;3 -4 = -1).所以从这些期望值中,参与人 I 必须选择对他最好的+1,所以他抽取相应的数字“1”(PS“1”不是抽取的数字,而+1 是收益)。
迭代#4,参与人 II 必须从第一行开始选择(因为参与人 I 选了“1”)。所以他把这些值加到他已经有的值上(3–2 = 1;-4+3=-1)所以他画“2”,以此类推…
这样做的次数足够多,就会导致值太接*游戏值。
以下是明确的步骤:
- 选择一列并写在网格的右边。
- 选择最大值并将其行写在底部。
- 选择该行的最小值,将其列与右边的值相加,写出总和。
- 选择该列的最大值,将其行与底部的值相加,写出总和。
- 根据需要重复步骤 3 和 4。
- 计算下限(L)和上限(U ),方法是取最后选择的值并除以迭代次数。这将给出游戏值(V)的范围,例如 L ≤ V ≤ U
以下代码将帮助您了解算法的工作原理:
Javascript implementation of Odd/Even game Fictitious Play. It can be easily tested using any online JS editor
在马克斯 _ITER = 1000 和马克斯 _ITER = 10000 的情况下运行上述代码会产生以下结果:
记住理论博弈值是 1/12 = 0.083333…这显然在迭代法的下限和上限之内。
结论
这篇文章以简单的方式解释了虚拟游戏算法,但没有提到任何与深度学习或神经网络相关的内容,这些内容将是未来文章的主题。
相关文章
神经虚构自演
神经虚构自演
介绍使用脸书的先知预测菲律宾股票价格
原文:https://towardsdatascience.com/introduction-to-forecasting-philippine-stock-prices-fd4df5dad9c3?source=collection_archive---------9-----------------------
预测菲律宾 Jollibee Food Corp (JFC)公司股票价格的基本 python 工作流
我从大学开始就在菲律宾从事股票交易,并立即确信这是一个预测模型非常有用的领域。为什么?因为你在股市赚钱的能力取决于你预测未来价格的能力。
在本文中,我将使用 python 上强大的 Prophet 包演示一种快速预测菲律宾股票 Jollibee Foods Corporation (JFC)每日收盘价的方法。Prophet 是脸书公司开发的一款开源预测工具,它可以将标准的预测工作流程从通常需要几天或几周的时间缩短到几分钟(假设你已经有了正确格式的数据)。
所有相关数据和代码可在本回购的时序目录中找到。
我们将遵循以下工作流程:
- 安装并导入必要的软件包
- 获取数据
- 绘制时间序列
- 训练先知模型
- 预测未来!
- 评估准确性
我们开始吧!
1.安装并导入必要的软件包
只是先知+基础。
# Run these on your terminal
pip install pandas
pip install datetime
pip install fbprophet
pip install numpy
pip install matplotlib# Alternatively, you can run these from jupyter this way
!pip install pandas
!pip install datetime
!pip install fbprophet
!pip install numpy
!pip install matplotlib
2.获取数据
我们所需要的是一个文件,我们可以读入 python 作为熊猫数据帧,其中包含 2 列对应于股票的收盘价和日期。
对于这个介绍,我在这个回购的时间序列目录中保存了一份 JFC 从 2013 年 9 月 1 日到 2019 年 4 月 26 日的收盘价(以及这里的其余代码)。我们可以通过克隆这个 repo 并导航到时序目录来访问数据。
# Run these on your terminal
git clone [https://github.com/enzoampil/data-science-demos.git](https://github.com/enzoampil/data-science-demos.git)
cd data-science-demos/time-series# Alternatively, you can run these from jupyter this way
!git clone [https://github.com/enzoampil/data-science-demos.git](https://github.com/enzoampil/data-science-demos.git)
!cd data-science-demos/time-series# Read the JFC data (csv) as a pandas DataFrame
jfc = pd.read_csv("[jfc_20130901_to_20190426.csv](https://github.com/enzoampil/data-science-demos/blob/master/time-series/jfc_20130901_to_20190426.csv)")# Convert the date column to datetime format
jfc['CHART_DATE'] = pd.to_datetime(jfc.CHART_DATE)
3.绘制时间序列
为此,我们可以使用直接从 pandas 数据框架中访问的基本绘图功能。
# Plot the time series
# 'CHART_DATE' is the date and 'CLOSE' is the closing price
jfc.set_index('CHART_DATE').CLOSE.plot(figsize=(15, 10))
plt.title('Jollibee Daily Closing Price', fontsize=25)
你会注意到,JFC 的收盘价在上升和下降的周期中波动,但整体趋势仍在上升。Prophet 的优势之一是,在进行预测时,它可以自动考虑趋势中发现的季节性。
4.训练先知模型
现在,我们可以训练先知模型了!要做到这一点,我们必须首先过滤数据框架,使其只有两列:日期,“CHART_DATE”和收盘价“CLOSE”。然后,我们将它们的名称分别改为“ds”和“y ”,因为 Prophet 会自动将“ds”列读取为日期,将“y”列读取为被预测的变量。最后,我们根据训练数据训练模型,训练数据是指在指定的维持期开始之前的数据。在这种情况下,“HOLDOUT_START”是对应于保持期开始的日期(设置为 2019-03-01)。
请注意,维持期的数据将被视为我们的验证集,并将用于评估已训练的 Prophet 模型的性能。
# Set holdout (validation) set start
HOLDOUT_START = '2019-03-01'# Import the Prophet package
from fbprophet import Prophet# Filter to only the date and closing price columns
ts = jfc[['CHART_DATE', 'CLOSE']]# Rename the date and closing price columns to 'ds', and 'y', respectively
# We do this since prophet automatically reads the 'ds' column as the date and the 'y' column as the variable that we are forecasting
ts.columns = ['ds', 'y']# Fit the Prophet model to the training data (before the start of the holdout set)
# We set daily_seasonality and yearly_seasonality to True to account for daily and yearly seasonality, respectively
m = Prophet(daily_seasonality=True, yearly_seasonality=True).fit(ts[ts.ds < HOLDOUT_START])
5.预测未来!
在 Prophet 中,我们首先创建一个未来数据帧,,在这里我们指定我们想要预测的未来有多远;在本例中,我们将其设置为 336 天。接下来,我们调用在已训练的 prophet 模型中找到的 predict 方法(使用未来数据帧作为参数),这将返回预测。
# Set the forecast period, "periods", in the specified unit, "freq"
# In this case, we're predicting 336 days into the future
future = m.make_future_dataframe(periods=7*4*12, freq='D')# Make the actual predictions
pred = m.predict(future)# Visualise the predictions using Prophet's plotting method
from matplotlib import pyplot as plt
fig1 = m.plot(pred)
plt.title('Jollibee: Forecasted Daily Closing Price', fontsize=25)
预测以及历史收盘价如上所示。蓝线对应于预测的收盘价,而黑点对应于训练集中的历史收盘价。抵制期的预测收盘价表明价格将在该期间(2019 年 3 月 1 日至 2019 年 4 月 26 日)下跌。
蓝色阴影区域对应于预测的 95%置信区间。您会注意到,距离更远的预测也具有更宽的预测置信区间。
6.评估准确性
为了评估我们训练的 Prophet 模型的准确性,我们将计算我们对 2019 年 3 月 1 日至 2019 年 4 月 26 日的维持集的预测的均方根误差(RMSE)。为了更详细地展示业绩,我们还绘制了 57 天维持期的预测 JFC 收盘价与实际 JFC 收盘价的对比图。
# Concatenate holdout (validation) set predictions and targets into one dataframe for easy comparison
pred_holdout = pred[(pred.ds >= HOLDOUT_START)&(pred.ds <= ts.ds.max())].set_index('ds').yhat
target_holdout = ts[ts.ds >= HOLDOUT_START].set_index('ds')
comb = pd.concat([pred_holdout, target_holdout], axis=1).dropna()# Calculate root mean squared error (RMSE)
import numpy as np
rmse_holdout = np.sqrt(comb.yhat.subtract(comb.y).pow(2).mean())# Plot predicted vs target while displaying accuracy based on rmse
comb.columns = ['Predicted', 'Actual']
comb.plot(figsize=(15, 10))
plt.title('Predicted (yhat) vs Actual (y) JFC Closing Price \n Validation Set RMSE: {}'.format(rmse_holdout), fontsize=25)
如前所述,维持集的预测价格(蓝色)表明,在维持集的持续时间内,价格会整体下降。有趣的是,实际价格(橙色)也显示了 JFC 收盘价的总体下降,尽管比预测的要快。
此外,短期运动似乎也反映在预测中。实际趋势显示,到 4 月 8 日开始上升,然后在 4 月 26 日开始下降。预测再次显示了类似的变化,尽管没有那么剧烈。
计算出的均方根误差(RMSE)为 5.56,这告诉我们,对于 2019 年 3 月 1 日至 2019 年 4 月 26 日的坚守期,Prophet 模型的 JFC 收盘价预测*均误差为 5.56 PHP。这个误差足够小,让我们相信预测吗?这将取决于我们承担风险的意愿,但保守的经验法则是,即使在预期价格向下偏离预测价格的情况下,也只根据显示盈利机会的预测进行交易。
下一步是什么?
恭喜你!您现在知道如何使用强大的 Prophet 包执行基本的预测工作流。这包括以下步骤:1)安装和导入必要的软件包,2)获取数据,3)绘制时间序列,4)训练 Prophet 模型,5)使用该模型预测未来,最后,6)评估准确性。除了预测股票价格之外,还可以使用其他预测模型和用例来应用相同的工作流。
值得注意的是,仍有许多方法可以改进我们当前的预测工作流程:
- 利用外生变量和衍生指标进行预测。我们可以明确说明股票过去收盘价以外的信息(外生变量)。例如股票的交易量、其他股票的价格和交易量、利率、通货膨胀、最*发布的广告的成功以及其他衍生指标,如波动性、RSI、短期&长期移动*均线等。
- 识别可能引发价格波动的事件。例如与公司相关的公告(通常在 twitter 上披露),如绩效、合并&收购、新法律等。我们可以专门对这些进行建模,以估计它们对价格的影响。
- 试验其他强大的模型。我经常使用 Prophet 作为基准,但最终还是使用了其他性能超过基准模型的模型。例如梯度推进机器(如 LightGBM)、深度学习模型(如 LSTM RNNs)和其他前沿时间序列模型(如 TBATS、SARIMAX)。
- 提高预测模型不确定性的准确性。除了点预测的性能,更重要的是预测不确定性的准确性,这可以指导我们知道何时更信任模型的预测。这是最*研究的一个焦点,一些已经成功地创建了模型,这些模型准确地预测了 95%的置信区间,实际上覆盖了 95%的目标。
- 通过模拟引擎可视化估计的影响。通过创建能够解释外部因素和事件的模型,我们可以将这些模型转化为模拟引擎,以可视化不同情景下价格的变化(即情景分析)。例如,如果明年经济衰退,利率上升 2%,价格会如何?
以上只是改进我们当前预测工作流程的许多方法中的一部分,我计划在未来的博客文章中详细讨论这些方法。如果你对从哪一个开始有任何建议,请随时评论或发电子邮件给我,地址是 lorenzo.ampil@gmail.com。敬请期待!
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
FPGA 及其架构介绍
原文:https://towardsdatascience.com/introduction-to-fpga-and-its-architecture-20a62c14421c?source=collection_archive---------6-----------------------
不久以前,大多数软件都是和它们各自的硬件一起永久发布的,没有办法改变它。但是随着技术的成熟,制造商找到了在现有硬件上增加新功能的方法。
现在,想象一下硬件更新也成为可能的未来——这难道不令人着迷吗?
这种可编程硬件的子系统配置甚至可以在制造后修改,属于可重构系统的范畴。而支持可重构计算的最主要的集成电路是 FPGA ,是FfieldP可编程 G ate A rray 的缩写。
FPGA 使您能够对产品功能进行编程,适应新标准,并针对特定应用重新配置硬件,即使产品已经现场安装——因此有术语“现场可编程”。而“门阵列指的是其架构中存在的二维逻辑门阵列。
所有现代个人计算机,包括台式机、笔记本电脑、智能手机和*板电脑,都是通用计算机的例子。通用计算结合了“冯·诺依曼”方法,该方法指出取指令和数据操作不能同时发生。因此,作为顺序机器,它们的性能也是有限的。
另一方面,我们有专用集成电路(ASICs ),它们是为特定任务定制的,如数字录音机或高效比特币挖矿机。ASIC 使用空间方法仅实现一个应用程序,并提供最佳性能。但是,除了最初设计的任务之外,它不能用于其他任务。
那么,如何用 ASICs 的性能换取通用处理器的灵活性呢?
嗯…
FPGAs 充当了这两种架构模式之间的中间地带!
话虽如此,FPGAs 与 ASICs 相比能效较低,也不适合大批量生产。然而,与 ASIC 相比,它们是可重新编程的,并且具有较低的 NRE 成本。
你看,ASICs 和 FPGAs 有不同的价值主张。大多数器件制造商通常更倾向于使用 FPGAs 进行原型开发,使用 ASICs 进行大批量生产。
Photo by numato.com
过去,FPGA 常常被选择用于较低的速度和复杂的设计,但现在 FPGA 可以轻松超过 500 MHz 的性能基准。
FPGA 的内部架构
1985 年,一家名为 Xilinx 的半导体制造公司发明了第一个商业上可行的 FPGA——xc 2064。另一家公司 Altera ,于 2015 年被英特尔收购,也与 Xilinx 一起推动了这个市场的发展。
FPGA 源于相对简单的技术,如可编程只读存储器(PROM)和可编程逻辑器件(PLD),如 PAL、PLA 或复杂 PLD (CPLD)。
它由三个主要部分组成:
- 可配置逻辑块——实现逻辑功能。
- 可编程互连——实现路由。
- 可编程 I / O 块——与外部元件连接。
The basic architecture of an FPGA
逻辑模块实现设计所需的逻辑功能,由晶体管对、查找表(lut)、触发器和多路复用器等各种元件组成。
您可以将逻辑块视为独立的模块,就像可以并行操作的乐高积木一样。与乐高积木不同,逻辑积木是可配置的,即其内部状态可以控制,您可以通过对互连进行编程来将它们连接在一起,以便构建有意义的东西。
这种可编程互连的层次结构用于在可配置逻辑块(clb)之间分配资源;其中布线路径包含可以通过反熔丝或基于存储器的技术连接的不同长度的线段。
每个 CLB 都连接到一个交换矩阵,以访问通用路由结构。开关矩阵提供可编程多路复用器,用于选择给定路由通道中的信号,从而连接垂直和水*线路。
最后,I/O 模块(iob)用于将 clb 和路由架构与外部元件连接。
在早期的 FPGAs 中,没有处理器来运行任何软件;因此,实现应用意味着从头开始设计电路。因此,我们可以将 FPGA 配置为像或门一样简单,或者像多核处理器一样复杂。
但是,自 XC2064 以来,我们已经取得了长足的进步,基本 FPGA 架构已经通过添加更专业的可编程功能模块得到了发展,如 alu、块 RAM、多路复用器、DSP-48 和微处理器。
FPGA 设计流程
设计流程说明了在物理板上实现和编程任何给定逻辑的流水线。我选择将这个设计流程命名为 FPGA 开发生命周期或 FDLC,因为它类似于 SDLC。
FPGA 架构设计流程包括设计输入、逻辑综合、设计实现、器件编程和设计验证。然而,具体步骤因制造商而异。
设计条目
可以使用原理图编辑器、有限状态机(FSM)编辑器或硬件描述语言(HDL)来描述逻辑。这是通过从给定库中选择组件并提供设计功能到所选计算模块的直接映射来实现的。
当具有大量功能的设计变得难以图形化管理时,HDL 可以用于以结构或行为的方式捕获设计。除了 VHDL 和 Verilog 这两种最成熟的 HDL 之外,还有几种类似 C 的语言可用,比如 Handel-C、Impulse C 和 SystemC。
逻辑综合
该过程将上述 VHDL 代码翻译成用于描述具有逻辑元件的完整电路的设备网表格式。综合包括检查代码语法和分析设计架构的层次结构。接下来,代码随着优化被编译,生成的网表被保存为 。ngc 文件。
设计实施
设计实施过程包括以下步骤:
- 翻译:该过程将所有输入的网表合并成逻辑设计文件,保存为 。ngd 文件文件。这里,用户约束文件将端口分配给物理元素。
- 映射:这包括映射由。ngd 文件转换成 FPGA 的组件然后生成一个 。ncd 文件文件。
- 放置和布线:这里的布线根据约束将上述过程中的子模块放置到逻辑模块中,然后连接这些模块。
设备编程
上述布线设计必须被加载并转换成 FPGA 支持的格式。于是,被击溃的 。ncd 文件交给 BitGen 程序,BitGen 程序生成包含 FPGA 所有编程信息的比特流文件。
设计验证
这与设计流程一起完成,以确保逻辑行为符合预期。这一过程涉及以下模拟:
- 行为模拟(RTL 模拟)
- 功能模拟
- 静态时序模拟
进行这些模拟是为了通过向设计的输入提供测试模式并观察输出来仿真组件的行为。
FPGA 的未来
行业趋势正在推动 FPGAs 在异构计算模式中发挥重要作用。在这里,异构计算指的是使用多种类型的处理器来执行专门处理功能的系统。所有这些不同的处理器,包括 FPGAs,都可以通过 OpenCL 进行编程,OpenCL 是一个行业标准开发*台。
事实上,FPGA 提供了经济高效的并行计算能力,这使得它适合快速原型制作。在测试神经网络时,有些情况下 FPGA 也优于 GPU。虽然 GPU 可能适合训练,但当涉及到实时应用时,FPGA 更具适应性。事实上,微软已经在通过微软 Azure 云服务来加速人工智能。
🔌简而言之…
从汽车到加密,从芯片开发到人工智能推理模型,FPGAs 提供了一定的通用性,吸引了广泛的用户,从而使未来看起来更光明!
Python 中 Git 数据提取和分析简介
原文:https://towardsdatascience.com/introduction-to-git-data-extraction-and-analysis-in-python-e7e2bf9b4606?source=collection_archive---------10-----------------------
从 Github REST API 中提取 Git 数据并在 Pandas 和 Plotly 中执行数据分析
Photo by Colby Thomas on Unsplash
软件行业有没有人没用过或者至少听说过 Git?
Git 是一个革命性的工具,如今在软件团队中无处不在。本文的目的并不是介绍 git,有大量的资源可以指导您完成这个过程。它的目的是分析 git 相关数据,以便从这些数据中获得重要的见解。
在整篇文章中,我们将使用 Github REST API 提取 Git 相关数据,然后利用 Python 的顶级数据分析库 【熊猫】 以及广受欢迎的交互式数据可视化库 Plotly 来分析这些数据。我们将以 Apache Spark 的存储库为例。
Git 数据提取
Git 存储库通常存储在源代码托管设施中。其中最流行的是 Github 和 Bitbucket,但是也有很多其他的,比如 Gitea、GitLab 等等。在本文中,我们将重点关注 Github,但是其他托管设施的数据提取过程应该也是类似的。
Github 提供了一个 REST API,其中包含了所有 git 相关资源的端点。为了能够使用 Github APIs,我们需要在 Github Profile 页面的开发者设置中生成一个访问令牌。做完那件事后,我们应该都准备好了。我们启动 Jupyter 笔记本,首先导入必要的库:
我们将配置参数存储在一个单独的文件中,即 Github 用户名和我们之前生成的访问令牌。与 Github 交互的推荐方式是使用 API 创建一个会话,如下所示:
哪些与 git 相关的实体可以提供关于 git 存储库进展的有价值的信息?
提交是首先想到的,但也有其他的,如分支、拉请求、问题、贡献者列表等。假设我们需要检索给定 git 存储库的提交列表。我们搜索 Github API 文档并找到相应的 API 端点:
GET /repos/:owner/:repo/commits
这里我们需要提供所有者和存储库名称作为输入参数。我们可以像这样用 Python 调用上面的 API 端点:
commits
变量包含从 Github API 返回的响应。然后我们使用 json 包的json()
方法来反序列化上面的响应对象。然而,这个 API 调用只返回 30 个结果,这对应于默认情况下通过单个 Github API 响应返回的结果数。我们可以为 API 请求提供一个额外的参数,per_page
,这允许我们将返回结果的数量增加到 100 个,但是我们试图从中提取数据的 Apache Spark 存储库有大约 26K 个提交!
别担心。Github 的家伙们提供了一个分页参数,称为page
,它与per_page
参数相结合,使我们能够提取任何 git 库的所有提交。现在,我们的 API 请求应该如下所示:
我们可以将提交提取过程封装在一个函数中,该函数将所有者和存储库名称作为参数,并返回一个提交列表:
为了控制遍历过程,在每次迭代中,我们检查响应头中的Link
参数是否包含rel="Next"
属性值,这告诉我们存在一个连续的页面,我们可以继续迭代;否则我们就此打住。为了更多地了解这种方法,你可以阅读 Github 文档中的分页遍历指南。
提取了列表中的提交后,我们现在可以从字典列表中生成 Pandas 数据帧,因此我们定义了以下函数来处理该任务:
json_normalize
函数很好地做到了这一点,它将一个半结构化的 JSON(字典列表)规范化为一个*面表。我们现在通过为 Apache Spark git 存储库传递必要的参数来调用上面创建的函数:
对其他资源的提取执行相同的过程,所以我跳过这一部分,您可以在本文的 Github 资源库中浏览。我还添加了将结果存储在 CSV 文件或 SQLAlchemy 支持的数据库中的可能性,以便我们可以访问这些数据以供以后分析。
数据预处理
因此,我们将提交和分支以及其他资源存储在内存中(如果您愿意,也可以存储在 CSV 文件中)。下一步是预处理这些数据。
检查提交数据帧的结构,我们得到以下结果:
我们将删除这些列中的大部分,更重要的是,我们将生成一些数据分析过程所需的与时间相关的列。以下代码将提交日期字段转换为日期时间字段,并利用dt
访问器对象获取熊猫系列的类似日期时间的属性:
删除不必要的列后,我们的commits.head
方法返回:
Git 数据分析
现在,我们转向数据科学领域的精彩部分——数据分析和数据可视化。Spark 资源库的贡献者总数是多少?
一个很好的洞察是一天中每个小时提交的分布情况。我们可以计算这个度量,因为我们已经为存储库的每次提交生成了一天中的某个小时。熊猫的代码是:
现在是时候可视化一些数据了。Plotly Python 库( plotly.py )是一个交互式、开源绘图库,支持 40 多种独特的图表类型,涵盖了广泛的统计、金融、地理、科学和三维用例。作为一个声明式编程库,Plotly 允许我们编写代码来描述我们想要制作什么,而不是如何制作。这大大减少了构建图表所花费的时间,并使我们更加专注于展示和解释结果。
标准 plotly 导入以及离线运行的设置如下:
回到我们有趣的每小时提交量指标,生成条形图所需的代码如下:
从图表中,我们注意到大部分的贡献都是在晚上提交的:)。在一天的工作时间里,活动较少。
随着时间的推移,Spark 存储库进展如何?这些年来它的活动是什么?让我们创建一个时序图并检查它。
事实证明,Spark repository 在 2015 年至 2016 年期间出现了活动高峰。但是我们能证明这个假设吗?当然可以!我们将计算每年的日均提交数量,以验证 2015 年和 2016 年是否是 Spark 存储库最活跃的年份。
上面的图表清楚地显示,存储库在 2015 年达到顶点,此后一直下降到 2017 年。从那时起,我们看到每年的日均提交数量保持稳定,并且直到撰写本文时,这种趋势一直存在。
谁是 Spark 存储库的主要贡献者?让我们找出它。
作为一个非常活跃的存储库,Spark 也有很多开放的拉取请求。通常,拉请求由一些预定义的关键字标记。下面的条形图显示了每个标签的拉取请求数:
很明显,最活跃的贡献者正在从事与 SQL 相关的功能。最后,Spark 是一个数据框架,允许对数 Pb 的数据进行类似 SQL 的操作。
恭喜
Photo by Ian Stauffer on Unsplash
您已到达这篇文章的结尾。在本指南中,我们学习了以下重要概念:
- 通过 Github API 在 Python 中提取数据
- 预处理 git 数据
- 使用 Pandas 和 Plotly 执行交互式分析和数据可视化
下面是我们在这篇文章中运行的所有内容的完整代码:
[## xhentilokaraj/git-统计
这是一个基于 git 库生成统计数据的迷你项目。已经有把 Github 当版本了…
github.com](https://github.com/xhentilokaraj/git-statistics)
感谢 的阅读!如果你想与我取得联系,请随时通过 xhentilokaraj@gmail.com 或我的 LinkedIn 个人资料 联系我。
面向数据科学家的 Github 简介
原文:https://towardsdatascience.com/introduction-to-github-for-data-scientists-2cf8b9b25fba?source=collection_archive---------6-----------------------
掌握 Github 的基础知识
Photo by Hack Capital on Unsplash
对版本控制的体验正迅速成为所有数据科学家的要求。版本控制可以帮助数据科学家更好地作为一个团队工作,促进项目协作,共享工作,并帮助其他数据科学家重复相同或相似的过程。即使您是一名独立工作的数据科学家,在合并到当前项目之前,能够先回滚更改或对分支进行更改,并测试您的更改不会破坏任何东西,这总是有用的。在接下来的文章中,我将讲述以下内容:
- 什么是 Github?
- 为什么数据科学家需要使用它?
- 如何创建和克隆存储库
- 分支
- 拉取请求
什么是 Github?
Github 是版本控制最知名和最广泛使用的*台之一。Github 使用一个名为 Git 的应用程序对代码进行版本控制。项目文件存储在一个称为存储库的中央远程位置。每次你在你的机器上做了一个本地的修改,然后推送到 Github,你的远程版本就会被更新,提交的内容会被记录下来。如果您想在提交之前回滚到项目的前一个版本,该记录允许您这样做。
此外,由于项目文件存储在远程位置,任何其他人都可以下载回购协议并对项目进行更改。分支的概念,本质上意味着你制作一个完全独立的项目的临时副本,意味着你可以首先在那里进行修改,而不用担心破坏任何东西。如果您从事的项目中有一个功能依赖于代码工作,这一点尤其重要。
这个页面涵盖了我在本文中使用的所有关键术语的含义,比如提交、分支和存储库。
为什么数据科学家需要使用它?
数据科学家需要使用 Github 的原因和软件工程师一样——为了协作,“安全地”对项目进行更改,并能够随着时间的推移跟踪和回滚更改。
传统上,数据科学家不一定必须使用 Github,因为将模型投入生产的过程(版本控制变得至关重要)通常被移交给软件或数据工程团队。然而,系统中有一个日益增长的趋势,这使得数据科学家更容易编写自己的代码来将模型投入生产——参见工具,如 H20.ai 和谷歌云人工智能*台。因此,数据科学家熟练使用版本控制变得越来越重要。
创建存储库
我将简要介绍如何使用 Github 和 Git 从命令行执行最常见的操作。如果你还没有帐户,你需要注册一个(这是完全免费的!)这里。
要从头开始创建存储库,请转到https://github.com/并点击new
按钮。
在接下来的页面上,您需要为您的项目键入一个名称,并选择是将其设为公共还是私有。
接下来,您要选中框initialise with a README.md
并点击create repository
。
现在,您可以添加并更改存储库中的文件了。要从命令行执行此操作,您首先需要按照这里的说明下载并安装 Git。
要在本地处理项目,您首先需要克隆存储库。如果您想克隆其他人的项目来工作,您也可以遵循这个步骤。
cd my-directory
git clone [https://github.com/rebeccavickery/my-repository.git](https://github.com/rebeccavickery/my-repository.git)
您可以通过点击clone or download
按钮找到存储库的 URL。
现在,一个新目录将出现在您当前的工作目录中,并与存储库同名。这是您的项目的本地版本。
分支
分支允许您制作存储库的副本,在那里进行更改,并在合并到主副本之前测试它们是否正常工作。最佳实践是始终在分支上进行更改,而不是在主分支上工作。
在创建分支之前,最好检查您的本地项目是否与远程存储库保持一致。您可以通过键入以下命令来检查状态:
git status
如果你不是最新的,你只需输入git pull
。
要创建并签出一个分支,请键入以下内容。
git branch my-branch
git checkout my-branch
现在,您可以进行更改,在合并之前,这些更改不会影响远程存储库。让我们对README.md
文件进行更改,并完成提交和合并更改的过程。
在首选文本编辑器中打开自述文件,并进行任何更改。我使用了升华文本并在文件中添加了一行。
拉取请求
处理协作项目的最佳实践是使用拉式请求,因此我们将使用此流程合并我们的变更。“拉”请求是一个过程,它允许您或其他人在将更改合并到主版本之前检查您所做的更改。在打开拉取请求之前,您需要添加并提交您的更改。
git add .
git commit -m "change to README.md"
git push --set-upstream origin my-branch
您只需要在第一次从新分支推送时添加参数---set-upstream origin my-branch
。
现在,您将在远程存储库中看到此消息。
点击compare and pull request
,然后点击create pull request
。
在这一点上,如果你和其他人或团队在项目上合作,你可能会要求别人检查你的修改。他们可以添加评论,当每个人都对更改感到满意时,您可以合并拉取请求
您的更改现在将被合并到主分支中。
如果你已经完成了分支,最好点击delete branch
按钮删除它
使用 Github 会变得更加复杂,但是我想在这里做一个简单的介绍。为了更全面的了解,Github 制作了一套指南,可以在这里找到。
使用 Catboost 对决策树进行梯度提升的介绍
原文:https://towardsdatascience.com/introduction-to-gradient-boosting-on-decision-trees-with-catboost-d511a9ccbd14?source=collection_archive---------2-----------------------
今天我想和大家分享我在开源机器学习库的经验,这个库是基于决策树的梯度推进,由俄罗斯搜索引擎公司 Yandex 开发的。
Github profile according to the 12th of February 2020
库是在 Apache 许可下发布的,并作为免费服务提供。
‘Cat’, by the way, is a shortening of ‘category’, Yandex is enjoying the play on words.
你可能熟悉梯度增强库,如 XGBoost、H2O 或 LightGBM,但在本教程中,我将快速概述梯度增强的基础,然后逐步转向更核心复杂的东西。
决策树简介
在谈论梯度推进之前,我将从决策树开始。树作为一种数据结构,在现实生活中有很多类比。它被用于许多领域,是决策过程的一个很好的代表。该树由根节点、决策节点和终端节点(不会被进一步分割的节点)组成。树通常是倒着画的,因为树叶在树的底部。决策树可以应用于回归和分类问题。
A simple decision tree used in scoring classification problem
在分类问题中,作为进行二元划分的标准,我们使用不同的指标——最常用的是基尼指数和交叉熵。基尼指数是对 K 个阶层总方差的一种衡量。在回归问题中,我们使用方差或与中位数的*均偏差
The functional whose value is maximized for finding the optimal partition at a given vertex
生长一棵树包括决定选择哪些特征和使用什么条件进行分割,以及知道何时停止。决策树往往非常复杂和过度拟合,这意味着训练集的误差将很低,但在验证集上却很高。更小的树和更少的分裂可能导致更低的方差和更好的解释,代价是一点点偏差。
决策树在非线性依赖中表现出良好的结果。在上面的例子中,我们可以看到每个类的划分表面是分段常数,并且表面的每一边都*行于坐标轴,因为每个条件都将一个符号的值与阈值进行比较。
我们可以用两种方法来避免过度拟合:添加停止标准,或者使用树修剪。停止标准有助于决定,我们是否需要继续划分树,或者我们可以停止,把这个顶点变成一片叶子。例如,我们可以在每个节点中设置多个对象。如果 m > n,则继续划分树,否则停止。n = = 1——最差情况。
或者我们可以调整树的高度。
另一种方法是树修剪——我们构建一棵过度拟合的树,然后根据选择的标准删除叶子。修剪可以从根部开始,也可以从叶子开始。从一棵“完全成长”的树上移除树枝——得到一系列逐渐修剪的树。在交叉验证中,我们比较了有分裂和没有分裂的过度拟合树。如果没有这个节点结果更好,我们就排除它。有许多用于优化性能的树修剪技术,例如,减少错误修剪和成本复杂性修剪,其中学习参数(alpha)用于衡量是否可以根据子树的大小删除节点。
决策树受到高方差的影响。这意味着,如果我们将训练数据随机分成两部分,并对这两部分都使用决策树,我们得到的结果可能会非常不同。
合奏
然而,研究人员发现,结合不同的决策树可能会显示更好的结果。整体——当我们有一个 N 基算法时,最终算法的结果将是基算法结果的函数。我们结合一系列 k 学习模型来创建改进的模型。
有各种集成技术,如 boosting(用一组分类器进行加权投票)、bagging(对一组分类器的预测进行*均)和 stacking(组合一组异类分类器)。
为了构建树集成,我们需要在不同的样本上训练算法。但是我们不能在一台设备上训练它们。我们需要使用随机化在不同的数据集上训练分类。例如,我们可以使用 bootstrap。
误差的期望值是方差、偏差和噪声的总和。集合由具有低偏差和高方差的树组成。梯度推进算法的主要目标是保持构造具有低偏差的树。
例如,我们需要基于带有噪声的 10 个点来*似右图中的格林函数。在左图中,我们显示了在不同样本上训练的策略。右图用红线显示了*均多项式。
我们可以看到,红色图形与绿色图形几乎相同,而算法分别与绿色函数有显著不同。下面的算法家族有低偏差,但高方差。
决策树的特点是低偏差但高方差,即使训练样本有很小的变化。总体方差是一个基本算法的方差除以算法数+基本算法之间的相关性。
随机森林算法
为了减少基算法之间相关性的影响,我们可以使用 bagging 算法和随机子空间方法。这种方法最显著的例子之一是随机森林分类器。这是一种基于随机子空间和 bagging 方法的算法,使用 CART 决策树作为基本算法。
随机子空间方法有助于降低树之间的相关性,避免过度拟合。让我们仔细看看:假设我们有一个数据集,有 D 个特征,L 个对象和 N 个基树。
每个基本算法都适合来自 bootstrap 的样本。
我们从 D 中随机选择 D 个特征,构建树直到停止准则(我前面提到过)。通常我们用低偏差建立过度拟合的树。
回归问题的特征数 D 为 D/3,分类 sqrt 为(D)。
应该强调的是,每个
再次选择一个大小为 d 的随机子集,这是分裂另一个顶点的时候。这是这种
方法与随机子空间方法的主要区别,在随机子空间方法中,在构建基础算法之前选择一次随机特征子集。
毕竟,我们应用 bagging 和*均每个基本算法的结果。
随机森林具有各种优点,如对离群点不敏感,对大特征空间工作良好,难以通过添加更多的树来过度拟合。
然而有一个缺点,存储模型需要 O(NK)内存存储,其中 K —树的数量。这已经很多了。
助推
Boosting 是一种加权集成方法。每个基本算法都是一个接一个按顺序添加的。一系列 N 分类器迭代学习。更新权重以允许后续分类器“更多地关注”被先前分类器错误分类的训练元组。加权投票不影响算法的复杂度,但*滑了基本算法的答案。
增压与装袋相比如何? Boosting 侧重于错误分类的元组,它有使生成的复合模型过度适应此类数据的风险。
用于构建线性模型的贪婪算法
以下每个算法都是为了纠正现有集合的错误而构建的。
- 用于阈值损失函数的不同*似
以 MSE 作为损失函数的标准回归任务为例
通常作为基本算法,我们采用最简单的算法,例如我们可以采用一个短决策树
第二种算法必须以最小化合成 b1(x) 和 b2(x) 的误差的方式拟合
至于 bN(x)
梯度推进
已知梯度推进是主要的集成算法之一。
梯度推进算法采用梯度下降法优化损失函数。这是一种迭代算法,步骤如下:
- 初始化第一个简单算法 b0
- 在每次迭代中,我们生成一个移位向量 s = (s1,..sl)。si — 训练样本上算法 bN(xi) = si 的值
3.那么算法就是
4.最后,我们将算法 bN 添加到集成中
有几个可用的梯度增强库:XGBoost、H20、LightGBM。它们之间的主要区别在于树结构、特征工程和处理稀疏数据
Catboost
Catboost 可以解决回归、分类、多类分类、排序等问题。模式因目标函数而异,我们试图在梯度下降过程中将其最小化。此外,Catboost 有预构建的指标来衡量模型的准确性。
在 Catboost 官方网站上,你可以找到 Catboost (method)与主要基准的比较,或者你可以在 Neptune.ai 博客上深入研究这个主题
Figures in this table represent Logloss values (lower is better) for Classification mode.
百分比是根据优化的 CatBoost 结果测量的度量差异。
Catboost 优势
Catboost 引入了以下算法进步:
- 一种用于处理分类特征的创新算法。不需要自己对特性进行预处理—它是开箱即用的。对于具有分类特征的数据,与另一种算法相比,准确性会更好。
- 实施有序升压,这是一种替代经典 bosting 算法的置换驱动算法。在小型数据集上,GB 很快就会被过度分配。在 Catboost 中,有一个针对这种情况的特殊修改。也就是说,在其他算法存在过度拟合问题的数据集上,您不会在 Catboost 上观察到相同的问题
- 快速易用的 GPU 训练。您可以通过 pip-install 简单地安装它
- 其他有用的特性:缺少值支持,可视化效果好
分类特征
分类特征是一组离散的值,称为类别,彼此不可比。
Catboost 的主要优势是分类数据的智能预处理。您不必自己对数据进行预处理。对分类数据进行编码的一些最流行的做法是:
- 一键编码
- 标签编码
- 哈希编码
- 目标编码
- 等等..
对于具有少量不同特征的分类特征,一键编码是一种流行的方法。Catboost 将 one_hot_max_size 用于多个不同值小于或等于给定参数值的所有特征。
在具有高基数的特征的情况下(例如,像“用户 ID”特征),这样的技术导致不可行的大量新特征。
另一种流行的方法是通过目标统计 (TS)对类别进行分组,这些统计估计了每个类别中的预期目标值。
这种贪婪方法的问题是目标泄漏:使用前一个特征的目标来计算新特征。这导致了有条件的转移——对于训练和测试示例,分布是不同的。
解决这个问题的标准方法是保持 TS 和留一TS。但是他们仍然不能防止模型目标泄漏。
CatBoost 使用更有效的策略。它依赖于排序原则,被称为基于目标与先验(TBS) 。它是受在线学习算法的启发,在线学习算法按时间顺序获取训练样本。每个示例的 TS 的值仅依赖于观察到的历史。为了使这种思想适应标准的离线设置,我们引入了人工“时间”,即训练样本的随机排列σ。
在 Catboost 中,数据被随机打乱,并且只对每个对象的历史数据计算*均值。数据可以被多次重组。
CatBoost 的另一个重要细节是使用分类特征的组合作为额外的分类特征,这些分类特征在广告点击预测任务中捕获高阶依赖性,如用户 ID 和广告主题的联合信息。可能组合的数量随着数据集中分类要素的数量呈指数增长,不可能处理所有的组合。CatBoost 以贪婪的方式构造组合。也就是说,对于树的每次分裂,CatBoost 将当前树中先前分裂已经使用的所有分类特征(及其组合)与数据集中的所有分类特征相结合(连接)。组合被动态地转换成 TS。
对抗梯度偏差
CatBoost 实现了一种算法,允许对抗常见的梯度增强偏差。现有的实现面临统计问题,预测偏移。训练示例的分布 F(x_k) | x_k 从测试示例 x 的分布 F(x) | x 转移。这个问题类似于上述分类变量预处理中出现的问题。
Catboost 团队衍生了有序增强,这是标准梯度增强算法的一种修改,可以避免目标泄漏。CatBoost 有两种升压模式,命令和普通。后一种模式是内置有序 TS 的标准 GBDT 算法。
You can find a detailed description of the algorithm in the paper Fighting biases with dynamic boosting
CatBoost 使用不经意决策树,在树的整个级别上使用相同的分裂标准。这样的树是*衡的,不容易过度拟合,并允许在测试时显著加速预测。
下面是不经意树评估在 Catboost 中的实现:
int index = 0;
for (int depth = 0; depth < tree.ysize(); ++depth) {
index |= binFeatures[tree[depth]] << depth;
}
result += Model.LeafValues[treeId][resultId][index];
如您所见,这段代码中没有“if”操作符。你不需要分支来评估一个健忘的决策树。
遗忘决策树可以描述为一个条件列表,每层一个条件。对于不经意树,你只需要评估所有树的条件,组成二进制向量,将这个二进制向量转换成数字,并通过等于这个数字的索引访问叶子数组。
例如在 LightGBM 中(XgBoost 有类似的实现)
std::vector<int> left_child_;
std::vector<int> right_child_;inline int NumericalDecision(double fval, int node) const {
...
if (GetDecisionType(decision_type_[node], kDefaultLeftMask)) {
return left_child_[node];
} else {
return right_child_[node];
}
...
}
inline int Tree::GetLeaf(const double* feature_values) const {
...
while (node >= 0) {
node = NumericalDecision(feature_values[split_feature_[node]], node);
}
...
}
在有序增强模式中,在学习过程中,我们维护支持模型 Mr,j ,其中 Mr,j(i) 是基于排列 σr 中的前 j 个示例的第 i 个示例的当前预测。在算法的每次迭代 t 中,我们从 {σ1,.。。,σs} 并在此基础上构造一棵 Tt。首先,对于分类特征,所有的 TS 都是根据这个排列计算的。第二,排列影响树学习过程。
基于 Mr,j(i),计算相应的梯度。在构建树时,我们根据余弦相似性来*似梯度 G ,其中对于每个示例 I,我们基于之前的示例取梯度为σs。当树结构 Tt (即,分裂属性的序列)被构建时,我们使用它来提升所有模型Mr’,j
您可以在原始文件或 NIPS 的 18 张幻灯片中找到详细信息
GPU 培训
CatBoost 可以在一台机器的几个 GPU 上高效训练。
Experimental result for different hardware
CatBoost 实现了良好的可扩展性。在采用 InfiniBand 的 16 个 GPU 上,CatBoost 的运行速度比 4 个 GPU 快大约 3.75 倍。对于更大的数据集,可伸缩性应该更好。如果有足够的数据,我们可以在缓慢的 1gb 网络上训练模型,因为两台机器(每台机器有两个卡)不会明显慢于一个 PCIe 根联合体上的 4 个 GPU。你可以在这篇 NVIDIA 文章中了解更多信息
在所描述的优点中,还需要提到以下一个:
- 过拟合检测器。通常在梯度推进中,我们将学习速率调整到稳定的精度。但是学习率越小,需要的迭代次数就越多。
- 缺少变量。刚离开南
- 在 Catboost 中,您可以编写自己的损失函数
- 特征重要性
- CatBoost 为 Python 包提供工具,允许用不同的训练统计数据绘制图表。该信息可以在训练过程中和训练之后被访问
Monitor training in iPython Notebook using our visualization tool CatBoost Viewer.
Catboost 模型可以集成到 Tensorflow 中。例如,将 Catboost 和 Tensorflow 结合在一起是常见的情况。神经网络可用于梯度增强的特征提取。
此外,现在 Catboost 模型可以在 CoreML 的帮助下用于生产。
例子
我创建了一个应用 Catboost 解决回归问题的例子。我使用 Allstate 索赔严重程度的数据作为基础。
在您的进一步研究中,请随意使用 my colab !
你也可以在 Catboost 官方的 github 中找到大量其他的例子
贡献
如果你想让 CatBoost 变得更好:
- 查看求助问题,看看有哪些可以改进的地方,或者如果您需要什么,可以打开一个问题。
- 将您的故事和经验添加到 Awesome CatBoost 中。
- 要向 CatBoost 投稿,您需要首先阅读 CLA 文本,并在您的请求中添加您同意 CLA 条款的内容。更多信息可以在 CONTRIBUTING.md 找到对贡献者的说明可以在这里找到。
关注推特或微信(zkid18)来了解我的最新消息。
图表介绍(第一部分)
原文:https://towardsdatascience.com/introduction-to-graphs-part-1-2de6cda8c5a5?source=collection_archive---------6-----------------------
内线艾
Python 中的主要概念、属性和应用
G 如今,raphs 正成为机器学习的核心,例如,无论你是想通过预测潜在的联系来了解社交网络的结构,检测欺诈,了解汽车租赁服务的客户行为,还是提出实时建议。
在本文中,我们将讨论以下主题:
- 什么是图?
- 如何存储一个图形?
- 图的类型和性质
- Python 中的示例
这是致力于图论、图算法和图学习的三篇系列文章的第一篇。
本文最初发表于我的个人博客:https://maelfabien.github.io/ml/#
我在这个资源库上发布我所有的文章和相应的代码:
[## mael fabien/机器学习教程
本报告包含练习、代码、教程和我的个人博客文章
github.com](https://github.com/maelfabien/Machine_Learning_Tutorials)
NB : Part 2 和 Part 3 出来了!😃
[## 图形算法(第二部分)
Python 中的主要概念、属性和应用
towardsdatascience.com](/graph-algorithms-part-2-dce0b2734a1d) [## 用 Python 学习图形(第 3 部分)
Python 的概念、应用和示例
towardsdatascience.com](/learning-in-graphs-with-python-part-3-8d5513eef62d)
接下来,打开 Jupyter 笔记本,导入以下包:
import numpy as np
import random
import networkx as nx
from IPython.display import Image
import matplotlib.pyplot as plt
以下文章将使用最新版本的networkx``2.x
。NetworkX 是一个 Python 包,用于创建、操作和研究复杂网络的结构、动态和功能。
我将尽量保持一种实用的方法,并举例说明每个概念。
一、什么是图?
图是相互连接的节点的集合。
例如,一个非常简单的图形可以是:
Nodes in red, are linked by edges in black
图表可用于表示:
- 社交网络
- 网页
- 生物网络
- …
我们可以对图表进行什么样的分析?
- 研究拓扑和连通性
- 社区检测
- 确定中心节点
- 预测缺失节点
- 预测丢失的边
- …
所有这些概念在几分钟后会变得更加清晰。
在我们的笔记本中,让我们导入第一个预构建的图表:
# Load the graph
G_karate = nx.karate_club_graph()
# Find key-values for the graph
pos = nx.spring_layout(G_karate)
# Plot the graph
nx.draw(G_karate, cmap = plt.get_cmap('rainbow'), with_labels=True, pos=pos)
Karate Graph
这个“空手道”图代表什么?韦恩·w·扎卡里从 1970 年到 1972 年对一个空手道俱乐部的社交网络进行了为期三年的研究。该网络捕获了一个空手道俱乐部的 34 名成员,记录了在俱乐部外互动的成对成员之间的联系。在研究过程中,管理员“约翰 A”和指导员“嗨先生”(化名)之间发生了冲突,导致俱乐部一分为二。一半的成员在 Hi 先生周围组成了一个新的俱乐部;另一部分的成员找到了新的教练或者放弃了空手道。根据收集到的数据,扎卡里正确地将俱乐部中除了一名成员之外的所有成员分配到了他们在分裂后实际加入的小组中。
基本图形概念
一个图 G=(V,E)由一组:
- 节点(也叫顶点) V=1,…,n
- 棱角 E⊆V×V
- 一条边 (i,j) ∈ E 链接节点 I 和 j
- 据说我和 j 是邻居
- 节点的度是其邻居的数量
Illustration of nodes, edges, and degrees
- 如果所有节点都有 n-1 个邻居,则图是完整的。这意味着所有节点都以各种可能的方式连接在一起。
- 从 I 到 j 的路径是从 I 到 j 的一系列边。该路径的长度等于它穿过的边数。
- 图的直径是连接任意两个节点的所有最短路径中最长路径的长度。
例如,在这种情况下,我们可以计算连接任意两个节点的一些最短路径。直径通常为 3,因为没有节点对,因此连接它们的最短路径长于 3。
Diameter of 3
- 测地线 路径是两个节点之间的最短路径。
- 如果所有的节点都可以通过给定的路径相互到达,那么它们就形成了一个连通分量。一个图是连通的它有单个连通分量吗
例如,下面是一个包含两个不同连接组件的图表:
2 connected components
- 如果边是有序对,则图是有向的。在这种情况下,I 的“入度”是到 I 的传入边的数量,“出度”是从 I 传出的边的数量。
Directed Graph
- 一个图是循环的如果你能返回到一个给定的节点。另一方面,如果至少有一个节点不能返回,那么它就是非循环的。
- 如果我们给节点或者关系赋予权重,那么一个图就可以是加权的。
- 如果边的数量比节点的数量多,那么图是稀疏的。另一方面,如果节点之间有许多边,则称其为密集。
Neo4J 关于图算法的书提供了一个清晰的总结:
Summary (Neo4J Graph Book)
现在让我们看看如何用 Python 从图表中检索这些信息:
n=34G_karate.degree()
属性.degree()
返回图中每个节点的度数(邻居)列表:
DegreeView({0: 16, 1: 9, 2: 10, 3: 6, 4: 3, 5: 4, 6: 4, 7: 4, 8: 5, 9: 2, 10: 3, 11: 1, 12: 2, 13: 5, 14: 2, 15: 2, 16: 2, 17: 2, 18: 2, 19: 3, 20: 2, 21: 2, 22: 2, 23: 5, 24: 3, 25: 3, 26: 2, 27: 4, 28: 3, 29: 4, 30: 4, 31: 6, 32: 12, 33: 17})
然后,分离度数值:
# Isolate the sequence of degrees
degree_sequence = list(G_karate.degree())
计算边的数量,以及度序列的度量:
nb_nodes = n
nb_arr = len(G_karate.edges())avg_degree = np.mean(np.array(degree_sequence)[:,1])
med_degree = np.median(np.array(degree_sequence)[:,1])max_degree = max(np.array(degree_sequence)[:,1])
min_degree = np.min(np.array(degree_sequence)[:,1])
最后,打印所有这些信息:
print("Number of nodes : " + str(nb_nodes))
print("Number of edges : " + str(nb_arr))print("Maximum degree : " + str(max_degree))
print("Minimum degree : " + str(min_degree))print("Average degree : " + str(avg_degree))
print("Median degree : " + str(med_degree))
这个标题是:
Number of nodes : 34
Number of edges : 78
Maximum degree : 17
Minimum degree : 1
Average degree : 4.588235294117647
Median degree : 3.0
*均而言,图表中的每个人都与 4.6 个人有联系。
我们还可以绘制度数直方图:
degree_freq = np.array(nx.degree_histogram(G_karate)).astype('float')plt.figure(figsize=(12, 8))
plt.stem(degree_freq)
plt.ylabel("Frequence")
plt.xlabel("Degre")
plt.show()
Degree Histogram
稍后,我们将会看到,度数直方图对于确定我们所看到的图形的类型非常重要。
二。图表是如何存储的?
你现在可能想知道我们如何存储复杂的图形结构?
根据我们想要的用途,有三种方法来存储图表:
- 在边缘列表中:
1 2
1 3
1 4
2 3
3 4
...
我们存储由边链接的每对节点的 ID。
- 使用邻接矩阵,通常加载到内存中:
Adjacency matrix
对于图中的每个可能的对,如果两个节点由一条边链接,则将其设置为 1。如果图是无向的,则 a 是对称的。
- 使用邻接表:
1 : [2,3, 4]
2 : [1,3]
3: [2, 4]
...
最佳表现取决于使用情况和可用内存。图形通常可以保存为.txt
文件。
图形的一些扩展可能包括:
- 加权边
- 节点/边上的标签
- 与节点/边相关联的特征向量
三。图形的类型
在这一节中,我们将介绍两种主要类型的图表:
- 鄂尔多斯-雷尼
- 巴拉巴斯-艾伯特
1.鄂尔多斯-雷尼模型
a .定义
在一个 Erdos-Rényi 模型中,我们建立一个有 n 个节点的 随机 图模型。该图是通过在一对节点(I,j)和 概率 p 之间画一条 边 而生成的。因此我们有两个参数:节点数:n 和概率:p。
Erdos-Rényi Graphs
在 Python 中,networkx
包有一个生成鄂尔多斯-雷尼图的内置函数。
*# Generate the graph
n = 50
p = 0.2
G_erdos = nx.erdos_renyi_graph(n,p, seed =100)# Plot the graph
plt.figure(figsize=(12,8))
nx.draw(G_erdos, node_size=10)*
您将得到与此非常相似的结果:
Generated Graph
b .学位分布
设 pk 随机选择的节点具有度 k 的概率*由于图的构建方式是随机的,所以图的度分布是二项式**😗
Binomial node degree distribution
每个节点的度数分布应该非常接**均值。观察到大量节点的概率呈指数下降。
*degree_freq = np.array(nx.degree_histogram(G_erdos)).astype('float')plt.figure(figsize=(12, 8))
plt.stem(degree_freq)
plt.ylabel("Frequence")
plt.xlabel("Degree")
plt.show()*
为了可视化分布,我在生成的图中将 n 增加到 200。
Degree Distribution
c .描述性统计
- *均度数由 n×p 给出,p=0.2,n=200,我们以 40 为中心。
- 期望度数由(n1)×p 给出
- 最大程度集中在*均值附*
让我们用 Python 检索这些值:
*# Get the list of the degrees
degree_sequence_erdos = list(G_erdos.degree())
nb_nodes = n
nb_arr = len(G_erdos.edges())
avg_degree = np.mean(np.array(degree_sequence_erdos)[:,1])
med_degree = np.median(np.array(degree_sequence_erdos)[:,1])
max_degree = max(np.array(degree_sequence_erdos)[:,1])
min_degree = np.min(np.array(degree_sequence_erdos)[:,1])
esp_degree = (n-1)*p
print("Number of nodes : " + str(nb_nodes))
print("Number of edges : " + str(nb_arr))
print("Maximum degree : " + str(max_degree))
print("Minimum degree : " + str(min_degree))
print("Average degree : " + str(avg_degree))
print("Expected degree : " + str(esp_degree))
print("Median degree : " + str(med_degree))*
这应该会给你类似于:
*Number of nodes : 200
Number of edges : 3949
Maximum degree : 56
Minimum degree : 25
Average degree : 39.49
Expected degree : 39.800000000000004
Median degree : 39.5*
*均学位和预期学位非常接*,因为两者之间只有一个很小的因素。
2.巴拉巴斯-艾伯特模型
a .定义
在 Barabasi-Albert 模型中,我们建立了一个具有 n 个节点的随机图模型,该模型具有优先连接组件。该图由以下算法生成:
- 第一步:概率为 p,进入第二步。否则,转到第三步。
- 第二步:将一个新节点连接到在随机选择的现有节点****
- 步骤 3:将新节点连接到 n 个现有节点,其概率与它们的度成比例
该图的目的是模拟在真实网络中经常观察到的优先连接。
在 Python 中,networkx
包还有一个生成 Barabasi-Albert 图的内置函数。
*# Generate the graph
n = 150
m = 3
G_barabasi = nx.barabasi_albert_graph(n,m)# Plot the graph
plt.figure(figsize=(12,8))
nx.draw(G_barabasi, node_size=10)*
您将得到与此非常相似的结果:
Barabasi-Albert Graph
您可以很容易地注意到,现在一些节点的度数似乎比其他节点的度数大得多!
b .学位分布
设 pk 随机选择的节点的度为 k 的概率。度分布遵循幂律:
Power-law degree distribution
分布现在是重尾的。有大量的节点具有较小的度数,但是有大量的节点具有较高的度数。
*degree_freq = np.array(nx.degree_histogram(G_barabasi)).astype('float')plt.figure(figsize=(12, 8))
plt.stem(degree_freq)
plt.ylabel("Frequence")
plt.xlabel("Degree")
plt.show()*
Degree Distribution
这种分布被认为是无尺度的,也就是说,*均程度是没有信息的。
c .描述性统计
- 如果α≤2,则*均度为常数,否则,*均度发散
- 最大度数的顺序如下:
*# Get the list of the degrees
degree_sequence_erdos = list(G_erdos.degree())
nb_nodes = n
nb_arr = len(G_erdos.edges())
avg_degree = np.mean(np.array(degree_sequence_erdos)[:,1])
med_degree = np.median(np.array(degree_sequence_erdos)[:,1])
max_degree = max(np.array(degree_sequence_erdos)[:,1])
min_degree = np.min(np.array(degree_sequence_erdos)[:,1])
esp_degree = (n-1)*p
print("Number of nodes : " + str(nb_nodes))
print("Number of edges : " + str(nb_arr))
print("Maximum degree : " + str(max_degree))
print("Minimum degree : " + str(min_degree))
print("Average degree : " + str(avg_degree))
print("Expected degree : " + str(esp_degree))
print("Median degree : " + str(med_degree))*
这应该会给你类似于:
*Number of nodes : 200
Number of edges : 3949
Maximum degree : 56
Minimum degree : 25
Average degree : 39.49
Expected degree : 39.800000000000004
Median degree : 39.5*
四。结论
到目前为止,我们讨论了图的主要种类,以及描述图的最基本的特征。在下一篇文章中,我们将深入探讨图形分析/算法,以及分析图形的不同方式,用于:
- 实时欺诈检测
- 实时推荐
- 简化法规遵从性
- 复杂网络的管理和监控
- 身份和访问管理
- 社交应用/功能
- …
如果您有任何问题或意见,请随时评论。
下一篇文章可以在这里找到:
* [## 图形算法(第二部分)
Python 中的主要概念、属性和应用
towardsdatascience.com](/graph-algorithms-part-2-dce0b2734a1d)
来源:
- Neo4j 中的图形算法综合指南
- 网络 x 文档,https://networkx.github.io/documentation/stable/
如果你想从我这里读到更多,我以前的文章可以在这里找到:
[## 马尔可夫链和 hmm
在本文中,我们将关注马尔可夫模型,何时何地应该使用它们,以及隐马尔可夫模型。这个…
towardsdatascience.com](/markov-chains-and-hmms-ceaf2c854788) [## Python 中的人脸检测指南
在本教程中,我们将看到如何使用 OpenCV 和 Dlib 在 Python 中创建和启动人脸检测算法。我们会…
towardsdatascience.com](/a-guide-to-face-detection-in-python-3eab0f6b9fc1) [## 升压和 AdaBoost 解释清楚
直观的解释
towardsdatascience.com](/boosting-and-adaboost-clearly-explained-856e21152d3e)*
隐马尔可夫模型简介
原文:https://towardsdatascience.com/introduction-to-hidden-markov-models-cd2c93e6b781?source=collection_archive---------2-----------------------
我们介绍马尔可夫链和隐马尔可夫模型。
马尔可夫链
让我们先简单介绍一下马尔可夫链,一种随机过程。我们从链条的几个“状态”开始,{ S ₁,…,sₖ};例如,如果我们的链代表每天的天气,我们可以有{雪,雨,阳光}。一个过程( X ₜ)ₜ应该是一个马尔可夫链)的性质是:
换句话说,处于状态 j 的概率只取决于前一个状态,而不取决于之前发生的事情。
马尔可夫链通常用带有转移概率的图来描述,即从状态 i 移动到状态 j 的概率,用 p ᵢ,ⱼ.来表示让我们看看下面的例子:
Markov chain example
该链有三种状态;例如,雪和雨之间的转移概率是 0.3,也就是说,如果昨天下雪,今天有 30%的可能性会下雨。转移概率可以总结为一个矩阵:
注意每一行的总和等于 1(想想为什么)。这样的矩阵称为随机矩阵。( i , j )定义为pᵢ,ⱼ——在 i 和 j 之间的转移概率。
事实:如果我们取矩阵的幂, P ᵏ,( i , j )条目代表在 k 步从状态 i 到达状态 j 的概率。
在许多情况下,我们被给定一个初始概率向量 q =( q ₁,…, q ₖ)在时间 t =0 时处于每个状态。因此,在时间 t 处于状态 i 的概率将等于向量 P ᵏ q 的第 i- 个条目。
例如,如果今天下雪、下雨和阳光的概率是 0,0.2,0.8,那么 100 天后下雨的概率计算如下:
第二项等于≈ 0.44。
隐马尔可夫模型
在隐马尔可夫模型(HMM)中,我们有一个看不见的马尔可夫链(我们无法观察到),每个状态从 k 个观察值中随机产生一个,这对我们来说是可见的。
让我们看一个例子。假设我们有上面的马尔可夫链,有三个状态(雪、雨和阳光), P -转移概率矩阵和q-初始概率。这是看不见的马尔可夫链——假设我们在家,看不见天气。然而,我们可以感觉到我们房间内的温度,假设有两种可能的观察结果:热和冷,其中:
基本示例
作为第一个例子,我们应用 HMM 来计算我们连续两天感到寒冷的概率。这两天,底层马尔可夫状态有 3*3=9 个选项。让我们举例说明这 9 个选项之一的概率计算:
将所有选项相加得出期望的概率。
寻找隐藏状态—维特比算法
在某些情况下,我们被给定一系列的观察值,并想找到最有可能对应的隐藏状态。
强力解决方案需要指数级的时间(就像上面的计算);一种更有效的方法叫做维特比算法;它的主要思想是这样的:给我们一个观察序列 o ₁,…, o ₜ 。对于每个状态 i 和 t =1,…, T ,我们定义
也就是,给定我们的观察,在状态 i 在时间 t 结束的路径的最大概率。这里的主要观察是,根据马尔可夫性质,如果在时间 t 以 i 结束的最可能路径等于在时间t1 的某个 i ,则 i 是在时间t*1 结束的最可能路径的最后状态的值。这给了我们下面的前向递归:
这里, α ⱼ( o ₜ)表示当隐马尔可夫状态为 j 时拥有 o ₜ的概率。
这里有一个例子。让我们生成一个 14 天的序列,其中 1 表示高温,0 表示低温。我们会用算法找到这两周最有可能的天气预报。
import numpy as np
import pandas as pd
obs_map = {'Cold':0, 'Hot':1}
obs = np.array([1,1,0,1,0,0,1,0,1,1,0,0,0,1])
inv_obs_map = dict((v,k) for k, v in obs_map.items())
obs_seq = [inv_obs_map[v] for v in list(obs)]
print("Simulated Observations:\n",pd.DataFrame(np.column_stack([obs, obs_seq]),columns=['Obs_code', 'Obs_seq']) )
pi = [0.6,0.4] # initial probabilities vector
states = ['Cold', 'Hot']
hidden_states = ['Snow', 'Rain', 'Sunshine']
pi = [0, 0.2, 0.8]
state_space = pd.Series(pi, index=hidden_states, name='states')
a_df = pd.DataFrame(columns=hidden_states, index=hidden_states)
a_df.loc[hidden_states[0]] = [0.3, 0.3, 0.4]
a_df.loc[hidden_states[1]] = [0.1, 0.45, 0.45]
a_df.loc[hidden_states[2]] = [0.2, 0.3, 0.5]
print("\n HMM matrix:\n", a_df)
a = a_df.values
observable_states = states
b_df = pd.DataFrame(columns=observable_states, index=hidden_states)
b_df.loc[hidden_states[0]] = [1,0]
b_df.loc[hidden_states[1]] = [0.8,0.2]
b_df.loc[hidden_states[2]] = [0.3,0.7]
print("\n Observable layer matrix:\n",b_df)
b = b_df.values
我们得到:
Simulated Observations:
Obs_code Obs_seq
0 1 Hot
1 1 Hot
2 0 Cold
3 1 Hot
4 0 Cold
5 0 Cold
6 1 Hot
7 0 Cold
8 1 Hot
9 1 Hot
10 0 Cold
11 0 Cold
12 0 Cold
13 1 Hot
HMM matrix:
Snow Rain Sunshine
Snow 0.3 0.3 0.4
Rain 0.1 0.45 0.45
Sunshine 0.2 0.3 0.5
Observable layer matrix:
Cold Hot
Snow 1 0
Rain 0.8 0.2
Sunshine 0.3 0.7
现在让我们使用算法:
path, delta, phi = viterbi(pi, a, b, obs)
state_map = {0:'Snow', 1:'Rain', 2:'Sunshine'}
state_path = [state_map[v] for v in path]
pd.DataFrame().assign(Observation=obs_seq).assign(Best_Path=state_path)
我们得到:
Start Walk Forward
s=0 and t=1: phi[0, 1] = 2.0
s=1 and t=1: phi[1, 1] = 2.0
s=2 and t=1: phi[2, 1] = 2.0
s=0 and t=2: phi[0, 2] = 2.0
s=1 and t=2: phi[1, 2] = 2.0
s=2 and t=2: phi[2, 2] = 2.0
s=0 and t=3: phi[0, 3] = 0.0
s=1 and t=3: phi[1, 3] = 1.0
s=2 and t=3: phi[2, 3] = 1.0
s=0 and t=4: phi[0, 4] = 2.0
s=1 and t=4: phi[1, 4] = 2.0
s=2 and t=4: phi[2, 4] = 2.0
s=0 and t=5: phi[0, 5] = 0.0
s=1 and t=5: phi[1, 5] = 1.0
s=2 and t=5: phi[2, 5] = 1.0
s=0 and t=6: phi[0, 6] = 0.0
s=1 and t=6: phi[1, 6] = 1.0
s=2 and t=6: phi[2, 6] = 1.0
s=0 and t=7: phi[0, 7] = 2.0
s=1 and t=7: phi[1, 7] = 2.0
s=2 and t=7: phi[2, 7] = 2.0
s=0 and t=8: phi[0, 8] = 0.0
s=1 and t=8: phi[1, 8] = 1.0
s=2 and t=8: phi[2, 8] = 1.0
s=0 and t=9: phi[0, 9] = 2.0
s=1 and t=9: phi[1, 9] = 2.0
s=2 and t=9: phi[2, 9] = 2.0
s=0 and t=10: phi[0, 10] = 2.0
s=1 and t=10: phi[1, 10] = 2.0
s=2 and t=10: phi[2, 10] = 2.0
s=0 and t=11: phi[0, 11] = 0.0
s=1 and t=11: phi[1, 11] = 1.0
s=2 and t=11: phi[2, 11] = 1.0
s=0 and t=12: phi[0, 12] = 0.0
s=1 and t=12: phi[1, 12] = 1.0
s=2 and t=12: phi[2, 12] = 1.0
s=0 and t=13: phi[0, 13] = 0.0
s=1 and t=13: phi[1, 13] = 1.0
s=2 and t=13: phi[2, 13] = 1.0
--------------------------------------------------
Start Backtrace
path[12] = 1
path[11] = 1
path[10] = 1
path[9] = 2
path[8] = 2
path[7] = 1
path[6] = 2
path[5] = 1
path[4] = 1
path[3] = 2
path[2] = 1
path[1] = 2
path[0] = 2
这导致输出:
我们基于[2]使用了以下实现:
def viterbi(pi, a, b, obs):
nStates = np.shape(b)[0]
T = np.shape(obs)[0]
# init blank path
path = path = np.zeros(T,dtype=int)
# delta --> highest probability of any path that reaches state i
delta = np.zeros((nStates, T))
# phi --> argmax by time step for each state
phi = np.zeros((nStates, T))
# init delta and phi
delta[:, 0] = pi * b[:, obs[0]]
phi[:, 0] = 0
print('\nStart Walk Forward\n')
# the forward algorithm extension
for t in range(1, T):
for s in range(nStates):
delta[s, t] = np.max(delta[:, t-1] * a[:, s]) * b[s, obs[t]]
phi[s, t] = np.argmax(delta[:, t-1] * a[:, s])
print('s={s} and t={t}: phi[{s}, {t}] = {phi}'.format(s=s, t=t, phi=phi[s, t]))
# find optimal path
print('-'*50)
print('Start Backtrace\n')
path[T-1] = np.argmax(delta[:, T-1])
for t in range(T-2, -1, -1):
path[t] = phi[path[t+1], [t+1]]
print('path[{}] = {}'.format(t, path[t]))
return path, delta, phi
学习和鲍姆-韦尔奇算法
与上述方法类似的方法可以用于 HMM 模型的参数学习。我们有一些数据集,我们想找到最适合 HMM 模型的参数。 Baum-Welch 算法是一个迭代过程,它找到观察值 P 的概率的(局部)最大值( O |M),其中 M 表示模型(带有我们想要拟合的参数)。由于我们通过模型知道 P(M| O ),我们可以使用贝叶斯方法找到 P(M| O )并收敛到一个最优值。
HMM 有各种各样的应用,从字符识别到金融预测(检测市场机制)。
参考文献
[1]https://CSE . buffalo . edu/~ jcorso/t/CSE 555/files/lecture _ hmm . pdf
[2]http://www . blackarbs . com/blog/introduction-hidden-Markov-models-python-networkx-sk learn/2/9/2017
使用 fastai 库进行图像增强的介绍
原文:https://towardsdatascience.com/introduction-to-image-augmentations-using-the-fastai-library-692dfaa2da42?source=collection_archive---------6-----------------------
使用 fastai 库应用图像增强的示例演练
Photo by Thomas Willmott on Unsplash
你也可以在这个 kaggle 内核中找到这个博客的可执行代码。
关于 fastai 课程或图书馆的更多细节:请查看课程网站和图书馆文档。
文章简介
这篇文章的目的是向您展示 fastai 中所有的图像增强。我将首先介绍数据增强,然后介绍图像增强。
然后我们再来做一个案例,为什么 fastai 默认“刚刚好”。
接下来,我们将看几个这种转换将非常有用的真实用例:
- 构建 SOTA 社区游泳池检测器
- 构建医学图像 OCR
- 建立一个谷歌镜头 Ripoff(咳,启动,咳)
- 建立一个车牌检测器。
我们将查看一个可爱小狗的基本图像,首先应用变换将其用作参考,然后我将展示相同的真实世界用例的示例。
注意,这些定义和解释很大程度上来自 fastai 文档,我鼓励你去看看。
此外,这并不意味着大量编写代码,而是在更高层次上讨论在何处或何时使用代码。
如果你想运行内核,请点击副标题空间的链接。
数据扩充
数据扩充是最常见的正则化技术之一,在图像处理任务中尤其常见。
当你在一台机器上工作学习模型时,你的模型的性能只和你的数据一样好。根据您试图解决的模型和问题,您需要不同数量的数据。
然而,数据收集和清理是一个消耗资源的过程,并不总是可行的。
神经网络,或者通常用于图像处理相关目的:卷积神经网络,学习图像内部的“特征”。
为什么图像增强会起作用?
任何机器学习项目的目标都是确保我们的代码或“模型”能够推广到现实世界的数据。然而,与此相反的是“过度拟合”,即模型只是学习识别训练数据集中的特征。
为了避免这种情况,我们在将图像输入模型时会“增加”或添加一些细微的变化。尽管 2 度的旋转对人眼来说可能不会产生巨大的差异,但这种微小的变化足以让模型更好地推广。
为了给你一个“it just works”的例子,让我们尝试在打开/关闭图像增强的情况下,在 CIFAR-10 数据集上运行训练 ResNet 50。
启用增强(默认)后,您可以看到模型表现得更好。
接下来,我将深入研究 fastai 支持的图像增强,并给出可能有用的示例用例。
使用 fastai 的图像增强
为了将“转换”应用到您的数据集,我们在创建“ImageDataBunch”对象时传递转换列表。
fastai 有一个默认的推荐转换列表,它是由团队经过大量实验得出的,所以对于初学者,我建议相信这些:
tfms = get_transforms()
这将返回一个长度为 2 的元组,其中包含两个列表:一个用于定型数据集,另一个用于验证数据集。
get_transforms 函数的默认参数是:
get_transforms(do_flip:bool=True, flip_vert:bool=False, max_rotate:float=10.0, max_zoom:float=1.1, max_lighting:float=0.2, max_warp:float=0.2, p_affine:float=0.75, p_lighting:float=0.75, xtra_tfms:Optional[Collection[Transform]]=None) → Collection[Transform]
这样生成的默认元组是:
([RandTransform(tfm=TfmCrop (crop_pad), kwargs={'row_pct': (0, 1), 'col_pct': (0, 1), 'padding_mode': 'reflection'}, p=1.0, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (flip_affine), kwargs={}, p=0.5, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmCoord (symmetric_warp), kwargs={'magnitude': (-0.2, 0.2)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (rotate), kwargs={'degrees': (-10.0, 10.0)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmAffine (zoom), kwargs={'scale': (1.0, 1.1), 'row_pct': (0, 1), 'col_pct': (0, 1)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmLighting (brightness), kwargs={'change': (0.4, 0.6)}, p=0.75, resolved={}, do_run=True, is_random=True),
RandTransform(tfm=TfmLighting (contrast), kwargs={'scale': (0.8, 1.25)}, p=0.75, resolved={}, do_run=True, is_random=True)],
[RandTransform(tfm=TfmCrop (crop_pad), kwargs={}, p=1.0, resolved={}, do_run=True, is_random=True)])
如果你不理解索引中的所有单词,没关系。让我们深入探讨并尝试探索其中的一些。我分享这些的理由是:默认值总是一个好的起点,除非你正在处理非常不同的数据。例如:点突变或星系间图像。
fastai 支持的转换
- 聪明
- 对比
- 农作物
- 作物 _ 垫
- 有两个*面的
- 二面角 _ 仿射
- 翻转 _lr
- 翻转 _ 仿射
- 振动
- 衬垫
- 透视 _ 扭曲
- 调整大小
- 辐状的
- rgb _ 随机化
- 斜交
- 咯吱声
- 对称 _ 扭曲
- 倾斜
- 嗡嗡声
- 断流器
便利功能:
- 随机作物
- rand_pad
- 随机缩放
这是一个很长的列表!让我们试着一个一个地探索这些问题。
默认值:
我从文档中(窃取)了一些助手代码:
*#Helper functions from fastai docs*
def get_ex(): return open_image(path/'images/beagle_192.jpg')
def plots_f(rows, cols, width, height, **kwargs):
[get_ex().apply_tfms(tfms[0], **kwargs).show(ax=ax) for i,ax **in** enumerate(plt.subplots(
rows,cols,figsize=(width,height))[1].flatten())]
这将允许我们看狗的图片。这些将是比较的基本情况。因此,我将进一步分享这种变换,它对基本的狗图片做了什么,以及在现实世界中你可能会发现它有用的地方,因为我们的狗图片可能不会作为我们将看到的所有情况的最佳示例。
旋转
(max_rotate=angle)在此处指定的-角度和+角度之间切换随机旋转。
tfms = get_transforms(max_rotate=180)
因为没有人会在这些角度点击他们狗狗的照片。让我们考虑另一种情况:
真实世界用例
你的任务是在你的社区找到游泳池。你下载卫星图像,但由于你所在的地区很小,你的模型不适合。
在这种情况下,图像增强可能是有用的:
乍一看,我可能骗你说这些是不同的照片,不是吗?我相信这对我们的模型来说是一个很好的目的。
RGB 随机化
rgb_randomize
( **x**
,**channel**
: int
= ***None***
,**thresh**
: float
= ***0.3***
) → [Image](https://docs.fast.ai/vision.image.html#Image)
:: [TfmPixel](https://docs.fast.ai/vision.image.html#TfmPixel)
众所周知,图像有三个通道(红、绿、蓝,即 RGB)。这种变换使输入图像的一个通道随机化。
- 通道:随机化哪个通道(RGB)。
- 阈值:随机化后,将数值缩放至不超过
thresh
值
这在这样的情况下可能是有用的:你的数据集应该帮助你检测汽车,但是你的实习生(或者研究生 Turk😛)做的不好,只采集了红色汽车的图像。您可以随机选择颜色,帮助学习者更好地概括。
聪明
我们可以在 0 到 1 之间改变亮度,默认值是 0.5。
让我们看一下我们的狗狗照片,在亮度范围内有各种变化。由于原始图像拍摄得相当完美,增强在这里没有帮助。这是另一个扩大你的形象可能会破坏你的模型的例子。因此,在对数据应用变换时要小心。
真实世界用例
警告远离我们。这是我工作中的一个例子:任务是从这个图像中提取文本。即使对于人眼来说,当背景和文本之间的差异最明显时,这也更容易做到。所以对于 ex:看 0.3 值——这是这种情况下最好的结果。
对比
顾名思义,它允许我们从 0 到 2 的范围内改变对比度。1 是默认/原始图片。
这是我们可怜的狗狗的照片,正在进行另一组增强:
就我个人而言,我会投票给最“反差”的照片。归咎于 Instagram 滤镜。
真实世界用例
让我们重新开始之前的挑战。我们的任务是创建一个字符阅读器,从药品的图像中读取字符。对比度最大时效果最佳。
不相信我?看一看:
农作物
裁剪有助于裁剪到图像中提到的部分。
真实世界用例
你的任务是建立一个停车场计费机。由于我们的相机会固定在一个角度,我们可以预计大多数轿车进入很多,车牌最有可能是在一个固定的区域(中下部)。裁剪到那里将允许我们的模型只关注那个区域,使我们和模型的工作更容易。
作物垫
基于设置模式的 Crop_pad、crops 和 pads。fastai dev(s)推荐的是“反射填充”。有关零和反射填充,请参见下面的示例。
有两个*面的
二面角变换在二面体的 8 个可能的方向/角度上旋转图像。
让我们首先看看什么是二面角:
正如你所想象的,它会在所有这些可能的方向上旋转图像。定义够了,让我们从坏的角度来看我们无辜的小狗:
真实世界用例
现在,我敢打赌,如果你在 Instagram 上以这样的角度给你的小狗拍照,或者是一个糟糕的父母。不管怎样,这都不是一个好例子。
回到我们最初的夏令营任务,我们使用谷歌地图监视附*地区,寻找游泳池。
如你所见,在这种情况下,以这些角度旋转图像可能更有意义。如果你不知道,这些第一眼看上去可能是完全不同的图像。不是吗?
抖动
抖动会给图像增加随机噪声。我不确定同样的最佳实际使用情况是什么,幅度可以从-x 到+x 设置,0 是原始图像。
真实世界用例
在幕后,抖动是来自邻域的随机像素替换。这意味着,它可能有助于避免过度拟合(认为它类似于辍学)
远景
这种变换改变了图像的视角,就好像我们的对象被移动了一样。
还记得苹果的这个视频吗?
这正是它的作用。
作为参考,让我们先看看我们的小狗。
真实世界用例
这可能有用的一个用例是,假设您正在创建一个药品检测器,您希望客户对药品拍照,并且您的“技术”应该能够检测/读取所有细节。现在,客户可能不会从最佳角度点击照片,你也不愿意教他们同样的方法。相反,你可以使用这个变换。
查看这些示例:
对称翘曲
以下是文档中的定义:
同时应用四个倾斜,每个倾斜的强度在矢量magnitude
中给出。
让我们看看我们的小狗作为参考。
真实世界用例
好了,现在举个真实世界的例子。听说过谷歌镜头吗?
其在技术俱乐部中也被称为内容检索引擎/图片搜索引擎。现在想想,你使用这类服务真的不在乎角度对不对。所以这是你的工作。
例如,如果您的任务是构建一个 SOTA 谷物检测机图像引擎,这种转变将会非常突出:
倾斜
倾斜允许磁场“倾斜”到一个随机的方向和一个特定的大小。
direction
是一个数字(0:左,1:右,2:上,3:下)。正面的magnitude
是向前倾斜(朝向看图的人),负面的magnitude
是向后倾斜。
真实世界用例
我会饶了我们可爱的小狗,回到建造世界级谷物盒探测器的重要任务上。您可以看到转换对于这个用例再次非常有用:
这是一个很长的变换和例子列表。如果你有兴趣尝试这些,我会鼓励你检查我的入门内核。
如果你有任何问题,请给我发推文或在下面留言。
如果你觉得这很有趣,并且想成为我的学习之路 的一部分,你可以在 Twitter 这里 找到我。
如果你有兴趣阅读关于深度学习和计算机视觉的新闻,可以在这里 查看我的 简讯。
如果你有兴趣阅读机器学习英雄的一些最佳建议:从业者、研究人员和 Kagglers。 请点击这里
数字图像处理:数字图像介绍
原文:https://towardsdatascience.com/introduction-to-images-c9c7abe6bfd2?source=collection_archive---------5-----------------------
图像类型的基本介绍
让我们讨论一下什么是图像。如果您来自信号处理背景,那么您可能会将图像视为二维信号,即具有二维 f(x,y)的函数,其中 x,y 是空间坐标。从几何学的角度来看,你可以把图像看作二维或三维空间中的一组点。每个(x,y)上的每个点称为图像的振幅或强度。当这个振幅和 x,y 点是离散的,那么我们称之为数字图像。如果值是连续值,那么我们称之为模拟图像。我们可以通过采样和量化将模拟图像转换成数字图像。用计算机处理数字图像的过程称为数字图像处理。
像素:在一幅数字图像中,二维函数上的所有坐标及其对应的值都是有限的。每个位置的每个可用值都被视为一个像素。换句话说,像素是图像的最小部分。因此,数字图像可以被认为是二维像素阵列。
灰度:每个像素都有一个强度值,称为灰度或灰度值。这些值通常用 8 位整数表示。所以取值范围从 0 到 255。接* 0 的值表示较暗的区域,接* 255 的值表示较亮的区域。
图像类型:二值、灰度、彩色
二进制图像:二进制图像只有两种可能的灰度值或强度 0 和 255,没有中间值。在许多图像处理任务中,二进制图像被用作指示感兴趣的像素的掩模。下面是二值图像的例子。
Binary Image (only 0 and 255)
灰度图像:灰度图像的值范围从 0 到 255,即每个像素位置可以有 0 到 255 之间的任何值。如果你看 20 世纪 50 年代左右的老电影,你看到的是灰度图像(电影只不过是视频,是按适当顺序排列的单个图像的集合)。下面是一个例子
Grayscale image (0–255 range)
彩色图像:二值图像和灰度图像都是二维数组,其中在每个位置,都有一个值来表示像素。记住,为了表示一幅彩色图像,我们需要每个像素有不止一个值。但是我们需要多少个值来代表一种颜色呢?通常,每个像素需要 3 个值来表示任何颜色。这来自于任何颜色都可以由红、蓝、绿三种基本颜色组合而成的想法。将红色和绿色混合就可以得到黄色,将红色和蓝色混合就可以得到紫色,等等。,这其实叫 RGB 色彩空间。还有许多其他方法来创建彩色图像,我们将在以后的讨论中讨论。下面是一个彩色图像的例子。
Color Image (3-dim array with 3 values at every pixel location)
视频:视频就是一组按适当顺序排列的图像。
本帖到此为止,谢谢大家!
订阅 FOCUS——我的每周简讯,获取人工智能的最新更新和最新进展,以及来自机器学习媒体的精选故事。
用 Java 8 对库美尔笔迹分类实验介绍 kNN 算法
原文:https://towardsdatascience.com/introduction-to-knn-machine-learning-algorithm-by-experiment-on-khmer-handwriting-classification-66a64652a02c?source=collection_archive---------13-----------------------
机器学习是当前的热门领域,到处都在讨论。上面有很多使用一些函数式或者统计编程语言的实现,比如 Python 或者 R 。然而 Java ,这种流行的 OOP 编程语言,仍然可以实现几乎所有的机器学习算法。作为一名 Java 开发人员,我想介绍 kNN ( K *邻 )算法,因为它易于实现,并且不需要大量的数学或统计背景就可以理解。
1.要应用的解决方案
笔迹可以是 kNN 算法解决的问题之一,我将使用 高棉文字字符 作为解决的样本问题。高棉语是柬埔寨人所说的东南亚语言之一。它包含大量的辅音、从属或独立元音以及数字。下图是数字脚本,我们将编写一些代码来确定它是否看起来像预期的数字,或者换句话说,对它进行分类。
Khmer numerals : source from Wikipedia
2.数据准备
为了对其进行测试,需要将手写图像转换为包含表示图像上绘制的像素的位(0,1)的文本。每一个机器学习都必须有训练数据集和实验测试数据集。将图像转换成文本的过程将在另一篇文章中提到。
Text represents Khmer handwriting numeral script in bit(0,1)
3.kNN 流程图
为了对我们将要写的东西有一个准确的概念,让我们看看下面的流程图:
kNN flowchart by https://draw.io
4.使用 Java 8 实现 Java 代码
首先需要生成数据加载器类,以便将文本文件加载到内存中。正在使用地图,因为按文件夹分组是首选。
Data loader class
距离计算器用于使用欧几里德公式计算距离:
还需要生成一些类来保存一些数据和值,如下所示:
KnnClassifer 是本演示的主要逻辑。按照上面的流程图,下面是 Java 代码:
最后,我们创建主类,将所有的逻辑组合到一个应用程序中。
如果运行应用类没有任何问题,应该会显示如下图所示的结果。错误率为 0.34 ,时间为 0.572 秒(根据硬件规格不同,在您的电脑上可能会有所不同)。我们可以修改K _ CONSTANT,NUMBER _ OF _ THREAD或者修改一些 parallelStream 部分到普通 stream 来查看不同时间的分类。
kNN classification result
5.结论
kNN 可以使用 Java 进行实验,并通过多线程、并行流和许多其他 Java 8 特性进行优化。kNN 的应用可以在许多领域找到,包括推荐系统、手写和其他分类。 优步预测系统 是现实世界中应用 kNN 算法系统的一个例子。然而,它需要大量的计算、成比例的系统以及为训练集做好准备以避免性能问题。本次演示的完整代码和数据集可以在https://github.com/engleangs/knnclassifier中找到。
希望这个基本介绍能对你有用。如果有任何反馈或建议,请告诉我,加油!!。
科特林统计学简介
原文:https://towardsdatascience.com/introduction-to-kotlin-statistics-cdad3be88b5?source=collection_archive---------8-----------------------
Kotlin Island outside of Saint Petersburg, Russia (SOURCE: Wikimedia)
使用 Kotlin 的流畅数据科学运算符
在过去的几年里,我一直是 Kotlin 的狂热用户。但是我对 Kotlin 的癖好不仅仅是因为对语言的厌倦或者对 JetBrains 产品(包括 PyCharm,伟大的 Python IDE )的热情。Kotlin 是一个更加实用的 Scala,或者我听到有人这样描述它:“傻瓜的 Scala”。它的独特之处在于,它试图不这样做,专注于实用性和工业,而不是学术实验。它吸收了迄今为止编程语言(包括 Java、Groovy、Scala、C#和 Python)的许多最有用的特性,并将它们集成到一种语言中。
我对 Kotlin 的使用是出于需要,这是我在 2017 年 KotlinConf 演讲中谈到的事情:
你可能会说“Python 是实用的”,当然,我仍然使用 Python,尤其是当我需要某些库的时候。但是,在快速发展的生产应用程序中管理 10,000 行 Python 代码可能会很困难。虽然有些人能够成功地做到这一点,并在 Python 上运行整个公司,但像 Khan Academy 这样的一些公司正在发现 Kotlin 及其静态类型的现代方法的好处。Khan Academy 写了他们从 Python 生态系统转换到 Python/Kotlin 生态系统的经历:
[## 可汗学院服务器上的科特林
在 Khan Academy,我们使用 Python 2.7 在 Google 的应用引擎标准上运行我们的 web 应用程序。我们非常喜欢 Python
engineering.khanacademy.org](https://engineering.khanacademy.org/posts/kotlin-adoption.htm)
Khan 还为希望学习 Kotlin 的 Python 开发人员写了一个文档:
[## 面向 Python 开发者的 Kotlin
对 Kotlin 的全面介绍,面向具有 Python 或其他动态语言背景的开发人员。
khan.github.io](https://khan.github.io/kotlin-for-python-developers/)
但是我跑题了。在这篇文章中我想介绍的是一个我已经工作了一段时间的库,叫做 Kotlin-Statistics 。它最初是一个实验,用函数式和面向对象的编程来表达有意义的统计和数据分析,同时使代码清晰直观。换句话说,我想证明在不求助于数据框架和其他数据科学结构的情况下分析 OOP/功能数据是可能的。
[## 托马斯尼尔德/科特林-统计
科特林惯用的统计运算符。为托马斯尼尔德/科特林统计发展作出贡献
github.com](https://github.com/thomasnield/kotlin-statistics)
以下面这段 Kotlin 代码为例,我声明了一个Patient
类型,并包含了名字、姓氏、生日和白细胞计数。我还有一个名为Gender
的enum
来反映男性/女性类别。当然,我可以从文本文件、数据库或其他来源导入这些数据,但是现在我打算用 Kotlin 代码来声明它们:
**import** java.time.LocalDate
**data class** Patient(**val firstName**: String,
**val lastName**: String,
**val gender**: Gender,
**val birthday**: LocalDate,
**val whiteBloodCellCount**: Int) {
**val age get**() =
ChronoUnit.**YEARS**.between(**birthday**, LocalDate.now())
}**val** *patients* = *listOf*(
Patient(
**"John"**,
**"Simone"**,
Gender.**MALE**,
LocalDate.of(1989, 1, 7),
4500
),
Patient(
**"Sarah"**,
**"Marley"**,
Gender.**FEMALE**,
LocalDate.of(1970, 2, 5),
6700
),
Patient(
**"Jessica"**,
**"Arnold"**,
Gender.**FEMALE**,
LocalDate.of(1980, 3, 9),
3400
),
Patient(
**"Sam"**,
**"Beasley"**,
Gender.**MALE**,
LocalDate.of(1981, 4, 17),
8800
),
Patient(
**"Dan"**,
**"Forney"**,
Gender.**MALE**,
LocalDate.of(1985, 9, 13),
5400
),
Patient(
**"Lauren"**,
**"Michaels"**,
Gender.**FEMALE**,
LocalDate.of(1975, 8, 21),
5000
),
Patient(
**"Michael"**,
**"Erlich"**,
Gender.**MALE**,
LocalDate.of(1985, 12, 17),
4100
),
Patient(
**"Jason"**,
**"Miles"**,
Gender.**MALE**,
LocalDate.of(1991, 11, 1),
3900
),
Patient(
**"Rebekah"**,
**"Earley"**,
Gender.**FEMALE**,
LocalDate.of(1985, 2, 18),
4600
),
Patient(
**"James"**,
**"Larson"**,
Gender.**MALE**,
LocalDate.of(1974, 4, 10),
5100
),
Patient(
**"Dan"**,
**"Ulrech"**,
Gender.**MALE**,
LocalDate.of(1991, 7, 11),
6000
),
Patient(
**"Heather"**,
**"Eisner"**,
Gender.**FEMALE**,
LocalDate.of(1994, 3, 6),
6000
),
Patient(
**"Jasper"**,
**"Martin"**,
Gender.**MALE**,
LocalDate.of(1971, 7, 1),
6000
)
)
**enum class** Gender {
**MALE**,
**FEMALE** }
先说一些基本的分析:所有患者的whiteBloodCellCount
的*均值和标准差是多少?我们可以利用 Kotlin 统计数据中的一些扩展函数来快速找到这一点:
**fun** main() {
**val** averageWbcc =
*patients*.*map* **{ it**.**whiteBloodCellCount }**.*average*()
**val** standardDevWbcc = *patients*.*map* **{ it**.**whiteBloodCellCount }** .*standardDeviation*()
*println*(**"Average WBCC: $**averageWbcc**,
Std Dev WBCC: $**standardDevWbcc**"**)
*// PRINTS:
// Average WBCC: 5346.153846153846,
Std Dev WBCC: 1412.2177503341948* }
我们还可以从一组项目中创建一个DescriptiveStatistics
对象:
**fun** main() {
**val** descriptives = *patients* .*map* **{ it**.**whiteBloodCellCount }** .*descriptiveStatistics
println*(**"Average: ${**descriptives.**mean}
STD DEV: ${**descriptives.**standardDeviation}"**)
*/* PRINTS
Average: 5346.153846153846 STD DEV: 1412.2177503341948
*/* }
然而,我们有时需要对数据进行切片,不仅是为了更详细的了解,也是为了判断我们的样本。例如,我们是否获得了男性和女性患者的代表性样本?我们可以使用 Kotlin Statistics 中的countBy()
操作符,通过一个keySelector
来计数一个Collection
或Sequence
项目,如下所示:
**fun** main() {
**val** genderCounts = *patients*.*countBy* **{ it**.**gender }** *println*(genderCounts)
*// PRINTS
// {MALE=8, FEMALE=5}* }
这将返回一个Map<Gender,Int>
,反映打印时显示{MALE=8, FEMALE=5}
的按性别分类的患者计数。
好吧,我们的样本有点男性化,但让我们继续。我们还可以使用averageBy()
通过gender
找到*均白细胞数。这不仅接受一个keySelector
lambda,还接受一个intSelector
来从每个Patient
中选择一个整数(我们也可以使用doubleSelector
、bigDecimalSelector
等)。在这种情况下,我们从每个Patient
中选择whiteBloodCellCount
并通过Gender
进行*均,如下所示。有两种方法可以做到这一点:
方法 1:
**fun** main() {
**val** averageWbccByGender = *patients* .*groupBy* **{ it**.**gender }** .*averageByInt* **{ it**.**whiteBloodCellCount }** *println*(averageWbccByGender)
*// PRINTS
// {MALE=5475.0, FEMALE=5140.0}* }
方法二:
**fun** main() {
**val** averageWbccByGender = *patients*.*averageBy*(
keySelector = **{ it**.**gender }**,
intSelector = **{ it**.**whiteBloodCellCount }** )
*println*(averageWbccByGender)
*// PRINTS
// {MALE=5475.0, FEMALE=5140.0}* }
所以男性的*均 WBCC 是 5475,女性是 5140。
年龄呢?我们对年轻和年长的患者进行了很好的取样吗?如果你看看我们的Patient
类,我们只有一个birthday
可以使用,那就是 Java 8 LocalDate
。但是使用 Java 8 的日期和时间工具,我们可以像这样导出keySelector
中的年龄:
**fun** main() {
**val** patientCountByAge = *patients*.*countBy*(
keySelector = **{ it.age }** )
patientCountByAge.forEach **{** age, count **->** *println*(**"AGE: $**age **COUNT: $**count**"**)
**}** */* PRINTS:
AGE: 30 COUNT: 1
AGE: 48 COUNT: 1
AGE: 38 COUNT: 1
AGE: 37 COUNT: 1
AGE: 33 COUNT: 3
AGE: 43 COUNT: 1
AGE: 27 COUNT: 2
AGE: 44 COUNT: 1
AGE: 24 COUNT: 1
AGE: 47 COUNT: 1
*/* }
如果您查看我们的代码输出,按年龄计数并没有太大的意义。如果我们能够按照年龄范围来计算,比如 20-29 岁、30-39 岁和 40-49 岁,那就更好了。我们可以使用binByXXX()
操作符来做到这一点。如果我们想要通过一个Int
值(比如年龄)来进行分类,我们可以定义一个从 20 开始的BinModel
,并且将每个binSize
递增 10。我们还使用valueSelector
提供了我们是宁滨的值,即患者的年龄,如下所示:
**fun** main() {
**val** binnedPatients = *patients*.*binByInt*(
valueSelector = **{ it.age }**,
binSize = 10,
rangeStart = 20
)
binnedPatients.*forEach* **{** bin **->** *println*(bin.**range**)
bin.**value**.*forEach* **{** patient **->** *println*(**" $**patient**"**)
**}
}** }/* PRINTS:[20..29]
Patient(firstName=Jason, lastName=Miles, gender=MALE...
Patient(firstName=Dan, lastName=Ulrech, gender=MALE...
Patient(firstName=Heather, lastName=Eisner, gender=FEMALE...
[30..39]
Patient(firstName=John, lastName=Simone, gender=MALE...
Patient(firstName=Jessica, lastName=Arnold, gender=FEMALE...
Patient(firstName=Sam, lastName=Beasley, gender=MALE...
Patient(firstName=Dan, lastName=Forney, gender=MALE...
Patient(firstName=Michael, lastName=Erlich, gender=MALE...
Patient(firstName=Rebekah, lastName=Earley, gender=FEMALE...
[40..49]
Patient(firstName=Sarah, lastName=Marley, gender=FEMALE...
Patient(firstName=Lauren, lastName=Michaels, gender=FEMALE...
Patient(firstName=James, lastName=Larson, gender=MALE...
Patient(firstName=Jasper, lastName=Martin, gender=MALE...*/
我们可以使用 getter 语法查找给定年龄的 bin。例如,我们可以像这样检索年龄为 25 的Bin
,它将返回 20-29 的 bin:
**fun** main() {
**val** binnedPatients = *patients*.*binByInt*(
valueSelector = **{ it.age }**,
binSize = 10,
rangeStart = 20
)
*println*(binnedPatients[25])
}
如果我们不想将项目收集到 bin 中,而是对每个项目执行聚合,我们也可以通过提供一个groupOp
参数来实现。这允许您使用 lambda 来指定如何为每个Bin
减少每个List<Patient>
。以下是按年龄范围划分的*均白细胞数:
**val** avgWbccByAgeRange = *patients*.*binByInt*(
valueSelector = **{ it.age }**,
binSize = 10,
rangeStart = 20,
groupOp = **{ it**.*map* **{ it**.**whiteBloodCellCount }**.*average*() **}** )
*println*(avgWbccByAgeRange)/* PRINTS:
BinModel(bins=[Bin(range=[20..29], value=5300.0),
Bin(range=[30..39], value=5133.333333333333),
Bin(range=[40..49], value=5700.0)]
)
*/
有时,您可能希望执行多个聚合来创建各种指标的报告。这通常可以使用 Kotlin 的 let()操作符来实现。假设您想按性别找出第 1、25、50、75 和 100 个百分点。我们可以有策略地使用一个名为wbccPercentileByGender()
的 Kotlin 扩展函数,它将选取一组患者,并按性别进行百分位数计算。然后我们可以为五个期望的百分点调用它,并将它们打包在一个Map<Double,Map<Gender,Double>>
中,如下所示:
**fun** main() {
**fun** Collection<Patient>.wbccPercentileByGender(
percentile: Double) =
*percentileBy*(
percentile = percentile,
keySelector = **{ it**.**gender }**,
valueSelector = **{
it**.**whiteBloodCellCount**.toDouble()
**}** )
**val** percentileQuadrantsByGender = *patients*.*let* **{** *mapOf*(1.0 *to* **it**.*wbccPercentileByGender*(1.0),
25.0 *to* **it**.*wbccPercentileByGender*(25.0),
50.0 *to* **it**.*wbccPercentileByGender*(50.0),
75.0 *to* **it**.*wbccPercentileByGender*(75.0),
100.0 *to* **it**.*wbccPercentileByGender*(100.0)
)
**}** percentileQuadrantsByGender.*forEach*(::println)
}/* PRINTS:
1.0={MALE=3900.0, FEMALE=3400.0}
25.0={MALE=4200.0, FEMALE=4000.0}
50.0={MALE=5250.0, FEMALE=5000.0}
75.0={MALE=6000.0, FEMALE=6350.0}
100.0={MALE=8800.0, FEMALE=6700.0}
*/
这是对科特林统计学的简单介绍。请务必阅读该项目的自述文件以查看库中更全面的可用操作符集合(它也有一些不同的工具,如朴素贝叶斯分类器和随机操作符)。
我希望这能证明 Kotlin 在战术上的有效性,但也很强大。Kotlin 能够快速周转以进行快速的特别分析,但是您可以使用静态类型的代码,并通过许多编译时检查对其进行改进。虽然您可能认为 Kotlin 没有 Python 或 R 所拥有的生态系统,但它实际上在 JVM 上已经有了很多库和功能。随着 Kotlin/Native 获得牵引力,看看什么样的数字库会从 Kotlin 生态系统中崛起将会很有趣。
为了获得一些关于将 Kotlin 用于数据科学目的的资源,我在这里整理了一个列表:
[## 托马斯尼尔德/科特林-数据-科学-资源
管理图书馆、媒体、链接和其他资源,将 Kotlin 用于数据科学…
github.com](https://github.com/thomasnield/kotlin-data-science-resources/blob/master/README.md)
以下是我为演示 Kotlin 进行数学建模而撰写的一些其他文章:
[## 制作旅行推销员问题的动画
关于制作模型动画的经验教训
towardsdatascience.com](/animating-the-traveling-salesman-problem-56da20b95b2f) [## 数独和时间表
用树搜索解决调度问题
towardsdatascience.com](/sudokus-and-schedules-60f3de5dfe0d)
语言模型:N 元语法
原文:https://towardsdatascience.com/introduction-to-language-models-n-gram-e323081503d9?source=collection_archive---------1-----------------------
Photo by Erik Eastman on Unsplash
介绍
统计语言建模的一个步骤
介绍
统计语言模型本质上是一种为单词序列分配概率的模型。在本文中,我们将了解为句子和单词序列分配概率的最简单模型,即 n 元语法
你可以把一个 N-gram 看作是 N 个单词的序列,根据这个概念,一个 2-gram(或二元模型)是两个单词的序列,如“请转”、“转你的”或“你的作业”,而一个 3-gram(或三元模型)是三个单词的序列,如“请转你的”或“转你的作业”
直觉公式
先说方程 P(w|h),给定一些历史,单词 w 的概率, h 。举个例子,
在这里,水是如此的透明
而且,估算上述概率函数的一种方法是通过相对频率计数法,在这里你会取一个相当大的语料库,统计你看到 的次数,它的水是如此透明以至于 ,然后统计它后面是的次数。换句话说,你在回答这个问题:
在你看到历史 h 的次数中,单词 w 跟随了多少次
现在,你可以想象在整个语料库上执行这个是不可行的;尤其是它的尺寸很大。
这一缺点和使用链式法则分解概率函数的方式充当了 N-gram 模型的基本直觉。在这里,你不是使用整个语料库来计算概率,而是用几个历史单词来*似计算概率
二元模型
顾名思义,二元模型通过仅使用一个前面单词的条件概率来*似给定所有前面单词的单词的概率。换句话说,你用概率来*似它:P(the | that)
因此,当您使用二元模型来预测下一个单词的条件概率时,您会得出以下*似值:
这种一个词的概率只取决于前一个词的假设也被称为马尔可夫假设。
马尔可夫模型是一类概率模型,它假设我们可以预测某个未来单位的概率,而不用考虑太远的过去。
您可以进一步将二元模型推广到三元模型,它查看过去的两个单词,因此可以进一步推广到 N 元模型
概率估计
现在,我们理解了 N 元模型的基础,你会想,我们如何估计概率函数。最直接和直观的方法之一是最大似然估计(MLE)
例如,给定前一个单词 x ,计算单词 y 的特定二元模型概率,您可以确定二元模型 C(xy)的计数,并通过共享相同首词 x 的所有二元模型的总和对其进行归一化。
挑战
当然,每一种建模方法和评估方法都存在挑战。让我们看看影响 N-gram 模型的关键因素,以及 MLE 的使用
对训练语料的敏感度
与许多统计模型一样,N-gram 模型非常依赖于训练语料库。因此,,概率通常编码关于给定训练语料库的特定事实。此外,N 元模型的性能随着 N 值的变化而变化。
此外,你可能有一个语言任务,其中你知道所有可能出现的单词,因此我们提前知道词汇量 V。封闭词汇表假设没有未知单词,这在实际场景中不太可能。
*滑
MLE 方法的一个显著问题是数据稀疏。也就是说,任何出现足够多次的 N-gram 都可能对其概率有一个合理的估计。但是因为任何语料库都是有限的,一些完全可以接受的英语单词序列必然会从其中缺失。
因此,任何训练语料库的 N-gram 矩阵必然具有大量假定的“零概率 N-gram”的情况
来源:
[1]章节草稿— | Stanford Lagunita。https://lag unita . Stanford . edu/c4x/Engineering/CS-224n/asset/sl P4 . pdf
[2]语音和语言处理:自然语言处理、计算语言学和语音导论
感谢阅读。如果您有任何反馈,请对本文发表评论,在LinkedIn上给我发消息,或者给我发电子邮件(shmkapadia[at]gmail.com)**
如果你喜欢这篇文章,请访问我的其他文章
* [## Python 中的主题建模:潜在狄利克雷分配(LDA)
如何开始使用 Python 中的 LDA 进行主题建模
towardsdatascience.com](/end-to-end-topic-modeling-in-python-latent-dirichlet-allocation-lda-35ce4ed6b3e0) [## 评估主题模型:潜在狄利克雷分配(LDA)
构建可解释主题模型的分步指南
towardsdatascience.com](/evaluate-topic-model-in-python-latent-dirichlet-allocation-lda-7d57484bb5d0) [## 构建块:文本预处理
本文是关于自然语言处理的后续文章的第二篇。这一系列…的目的
towardsdatascience.com](/building-blocks-text-pre-processing-641cae8ba3bf)*
潜在矩阵分解推荐系统简介
原文:https://towardsdatascience.com/introduction-to-latent-matrix-factorization-recommender-systems-8dfc63b94875?source=collection_archive---------5-----------------------
Latent Factors are “Hidden Factors” unseen in the data set. Let’s use their power. Image URL: https://www.3dmgame.com/games/darknet/tu/
在创建推荐系统时,潜在矩阵分解是一种非常强大的方法。自从潜在矩阵分解在网飞推荐竞赛中被证明优于其他推荐方法以来,它就成为了构建推荐系统的基石。这篇文章的目的是给你一些直觉,告诉你什么时候使用潜在矩阵分解进行推荐,同时也给你一些直觉,告诉你为什么它会起作用。如果你想看完整的实现,可以去我的 Kaggle 内核:概率矩阵分解。
开始之前,让我们先回顾一下我们要解决的问题。潜在矩阵分解是一种解决推荐问题的算法:给定一组 m 个用户和 n 个项目,以及一组用户对某些项目的评分,尝试为每个用户推荐排名靠前的项目。这个问题有很多味道和交替的偏差,大多数都给问题增加了更多的维度,就像添加标签一样。潜在矩阵分解之所以强大,是因为它从核心问题中产生了非常强大的结果,并且可以成为一个很好的基础。
当使用用户项目评分矩阵,以及阅读关于矩阵分解的文章时,首先要看的是线性代数。直觉是正确的,但它不完全是你所期望的。
稀疏不完全矩阵代数:
传统的线性代数是机器学习的基石,这是因为大多数机器学习应用程序拥有推荐系统所没有的东西:没有 nan(不完整数据条目)的数据集。例如,无论何时构建模型,nan 或缺失数据都会在数据预处理步骤中被删除,因为大多数函数无法处理未填充的值。如果有缺失值,则像主成分分析这样的函数是未定义的。然而,如果你摆脱了 nan,推荐系统就无法工作。那些 nan 的存在是有原因的:不是每个用户都对每个项目进行了评级,期望他们这样做有点荒谬。处理稀疏数据是非常不同的事情——这使得推荐成为一个有趣的问题。
稀疏使事情复杂化。奇异值分解是一种将矩阵分解为奇异值和正交值的分解,如果矩阵中的任何元素未定义,则该分解是未定义的。这意味着我们不能以这样一种方式显式分解矩阵,即我们可以找到哪个对角(或潜在)因子在数据集中具有最大权重。
相反,我们将使用一种叫做概率矩阵分解的技术来*似矩阵的最佳分解。这项技术归功于 Simon Funk,他在他的 FunkSVD 算法中使用了这项技术,并在网飞竞赛中取得了巨大成功。更多阅读,请查看西蒙的原帖。
方法:
我先解释算法,再解释直觉。
Image URL: https://www.slideshare.net/RussiaAI/deep-learning-for-audiobased-music-recommendation
我们将首先从高斯分布初始化两个矩阵(或者,随机初始化它们)。第一个将是一个 m x k 矩阵 P 而第二个将是一个 k x n 矩阵 Q 。当这两个矩阵相乘时,它们会产生一个 m x n 矩阵,这正好是我们试图预测的评级矩阵的大小。维度 k 是我们的超参数之一,它代表了我们用来估计评级矩阵的潜在因素的数量。一般来说, k 在 10–250 之间,但不要相信我的话——使用线搜索(或网格搜索)找到适合您应用的最佳值。
Source: katbailey.github.io
对于我们的矩阵 P,Q,,我们将通过使用随机梯度下降来优化它们的值。因此,您将有另外两个超参数需要优化,即学习率和时期。对于每个时期,我们将遍历我们原始的 m x n 矩阵中的每个已知评级。
然后,我们将得到一个误差或残差值 e ,通过 P 中的原始评分用户行和 q 中的项目列的点积减去原始评分值。
在正常的随机梯度下降方式中,我们将通过将 P 和 Q 的当前行加上学习率乘以误差乘以另一个矩阵的值的乘积来同时更新矩阵 P 和 Q。
这是 python 语言。在我的 Kaggle 内核中完整查看。
#randomly initialize user/item factors from a Gaussian
P = np.random.normal(0,.1,(train.n_users,self.num_factors))
Q = np.random.normal(0,.1,(train.n_items,self.num_factors))
#print('fit')for epoch in range(self.num_epochs):
for u,i,r_ui in train.all_ratings():
residual = r_ui - np.dot(P[u],Q[i])
temp = P[u,:] # we want to update them at the same time, so we make a temporary variable.
P[u,:] += self.alpha * residual * Q[i]
Q[i,:] += self.alpha * residual * tempself.P = P
self.Q = Qself.trainset = train
现在我们有了算法,为什么它会工作,我们如何解释它的结果?
潜在因素代表数据中存在的类别。对于电影数据集的 k=5 个潜在因素,这些因素可以代表动作、浪漫、科幻、喜剧和恐怖。有了更高的 k,你就有了更具体的类别。我们正在尝试预测用户 u 对项目 i. 的评级。因此,我们查看 P 以找到代表用户 u、以及他们对所有潜在因素的偏好或“亲和力”的向量。然后,我们查看 Q 以找到一个代表项目 I 的向量,以及它对所有潜在因素的“亲和力”。我们得到这两个向量的点积,这将返回给我们一个用户在潜在因素的上下文中有多喜欢这个项目的感觉。
来源及延伸阅读:
大量的信息和灵感来自于这篇关于概率矩阵分解的文章和Charu Aggarwal 的《推荐系统:教科书》第三章。
你可以在这里找到 python 实现。
线性回归和多项式回归简介
原文:https://towardsdatascience.com/introduction-to-linear-regression-and-polynomial-regression-f8adc96f31cb?source=collection_archive---------4-----------------------
介绍
在这个博客中,我们将讨论两个重要的主题,它们将构成机器学习的基础,即“线性回归”和“多项式回归”。
什么是回归?
回归分析是预测建模技术的一种形式,它研究因变量和自变量之间的关系。
以上定义是一个书生气十足的定义,简单来说回归可以定义为,“利用变量之间的关系来寻找最佳拟合直线或可以用来进行预测的回归方程”。
Regression | Image: Wikipedia
回归有许多类型,如“线性回归”、“多项式回归”、“逻辑回归”等,但在这篇博客中,我们将学习“线性回归”和“多项式回归”。
线性回归
线性回归是一种基本且常用的预测分析类型,通常用于连续数据。我们将基于一个例子来理解线性回归:
Aarav 是一个想买房子的人,他正在收集住房数据,以便根据房子的“居住面积”(以英尺为单位)来估算房子的“成本”。
Housing data | Andrew Ng course
他观察了数据,并在绘制散点图后得出数据是线性的结论。在他的第一个散点图中,Aarav 使用了两个变量:“居住面积”和“价格”。
Scatter plot | Image: Andrew Ng course
他一看到数据中的模式,就计划在图上画一条回归线,这样他就可以用这条线来预测“房子的价格”。
使用训练数据,即“价格”和“居住面积”,得到一条给出最小误差的回归线。要做到这一点,他需要画一条尽可能接*多点的线。这个“线性方程”然后被用于任何新的数据,以便他能够预测所需的输出。
这里,β1 是参数(也称为权重),β0 是 y 轴截距,єi 是随机误差项,其作用是增加偏差。上面的方程是需要以最小的误差得到的线性方程。
上面的方程是一个简单的“直线的方程”即
y(预测)= (β1*x + βo) +误差值
其中' β1 '为斜率,' βo '为 y 轴截距,类似于直线的方程。必须选择值“β1”和“β0 ”,以使误差最小。为了检查误差,我们必须计算误差*方和,并调整参数以尽量减少误差。
误差=σ(实际输出-预测输出)
Cost function
键: 1。 Y(预测) 也叫假设函数。
2。J(θ)是代价函数,也可以称为误差函数。我们的主要目标是使成本最小化。
3。y(I)是的预测输出。
4。【x(I))称为假设函数基本上就是 Y(预测)值。
现在问题来了,我们如何减少误差值。嗯,这可以通过使用梯度下降来实现。梯度下降的主要目标是最小化成本值。即 min J(θo,θ1T53)
Gradient Descent Visualization | Gif: mi-academy.com
梯度下降有一个类比,我们必须想象自己在一个山谷的山顶,被蒙住眼睛,束手无策,我们的目标是到达山脚。感觉你周围地形的坡度是每个人都会做的。这个动作类似于计算梯度下降,而走一步类似于更新参数的一次迭代。
Gradient Decent Analogy | Image: Andrew Ng course
选择一个完美的 学习速率 是一项非常重要的任务,因为它取决于我们在每次迭代中走下坡路的幅度。如果我们迈得太大,我们可能会跳过最小值。然而,如果我们采取小步骤,将需要多次迭代才能达到最小值。
Linear Regression
多项式线性回归
在上一节中,我们看到数据集中的两个变量是相关的,但如果我们知道我们的数据是相关的,但这种关系看起来不是线性的,会发生什么呢?因此,根据数据的情况,我们可以对数据进行多项式回归,以拟合多项式方程。
Left: Linear Regression, Right: Polynomial regression | GIF: Towards Data Science
因此,如果我们试图在上图中使用一个简单的线性回归,那么线性回归线将不会很好地拟合。很难在上面的图表中拟合出误差值很低的线性回归线。因此,我们可以尝试使用多项式回归来拟合多项式线,以便我们可以实现最小误差或最小成本函数。上述图表数据的多项式回归方程为:
y =θo+θ₁x₁+θ₂x₁
这是多项式回归的一般方程是:
y=θo+θ₁x+θ₂x+…+θₘxᵐ+残差
使用多项式回归的优点:
- 多项式提供了因变量和自变量之间关系的最佳*似。
- 在它下面可以安装多种功能。
- 多项式基本上适合大范围的曲率。
使用多项式回归的缺点
- 数据中存在一两个异常值会严重影响非线性分析的结果。
- 这些对异常值过于敏感。
- 此外,不幸的是,用于检测非线性回归中异常值的模型验证工具比用于线性回归的工具少。
结论
在这篇博客中,我已经向你介绍了线性回归和多项式回归的基本概念。
逻辑回归介绍
原文:https://towardsdatascience.com/introduction-to-logistic-regression-66248243c148?source=collection_archive---------0-----------------------
介绍
在这个博客中,我们将讨论逻辑回归的基本概念以及它能帮助我们解决什么样的问题。
GIF: University of Toronto
逻辑回归是一种分类算法,用于将观察值分配给一组离散的类。分类问题的一些例子是电子邮件垃圾邮件或非垃圾邮件、在线交易欺诈或非欺诈、恶性肿瘤或良性肿瘤。逻辑回归使用逻辑 sigmoid 函数转换其输出,以返回概率值。
逻辑回归有哪些类型
- 二元(如恶性肿瘤或良性肿瘤)
- 多线性函数失败类(如猫、狗或羊的)
逻辑回归
逻辑回归是一种用于分类问题的机器学习算法,它是一种基于概率概念的预测分析算法。
Linear Regression VS Logistic Regression Graph| Image: Data Camp
我们可以将逻辑回归称为线性回归模型,但是逻辑回归使用更复杂的成本函数,该成本函数可以定义为“ Sigmoid 函数,或者也称为“逻辑函数”,而不是线性函数。
逻辑回归的假设倾向于将成本函数限制在 0 和 1 之间。因此,线性函数不能表示它,因为它可以具有大于 1 或小于 0 的值,根据逻辑回归的假设,这是不可能的。
Logistic regression hypothesis expectation
什么是乙状结肠函数?
为了将预测值映射到概率,我们使用 Sigmoid 函数。该函数将任何实数值映射到 0 和 1 之间的另一个值。在机器学习中,我们使用 sigmoid 将预测映射到概率。
Sigmoid Function Graph
Formula of a sigmoid function | Image: Analytics India Magazine
假设表象
使用线性回归时,我们使用假设的公式,即
hθ(x)=β₀+β₁x
对于逻辑回归,我们将对其稍加修改,即
σ(Z) = σ(β₀ + β₁X)
我们预计我们的假设将给出介于 0 和 1 之间的值。
Z = β₀ + β₁X
hθ(x)= sigmoid(Z)
即 hθ(x)= 1/(1+e^-(β₀+β₁x)
The Hypothesis of logistic regression
判别边界
当我们通过一个预测函数传递输入并返回一个介于 0 和 1 之间的概率分数时,我们期望我们的分类器根据概率给出一组输出或类。
例如,我们有 2 个类,让我们像猫和狗一样对待它们(1 —狗,0 —猫)。我们基本上确定一个阈值,高于该阈值的值我们将其分类为第 1 类,低于该阈值的值我们将其分类为第 2 类。
Example
如上图所示,我们选择阈值为 0.5,如果预测函数返回值为 0.7,则我们会将此观察结果分类为 1 类(狗)。如果我们的预测返回值为 0.2,那么我们会将观察结果分类为第 2 类(CAT)。
价值函数
我们在线性回归中学习了成本函数 J ( θ ,成本函数代表优化目标,即我们创建一个成本函数并将其最小化,以便我们可以开发一个误差最小的精确模型。
The Cost function of Linear regression
如果我们试图在“逻辑回归”中使用线性回归的成本函数,那么它将是无用的,因为它最终将是一个具有许多局部最小值的非凸函数,其中很难使最小化成本值并找到全局最小值。
Non-convex function
对于逻辑回归,成本函数定义为:
如果 y = 1,log( hθ ( x ))
如果 y = 0,log(1hθ(x))
Cost function of Logistic Regression
**
Graph of logistic regression
上述两个函数可以压缩成一个函数,即
Above functions compressed into one cost function
梯度下降
现在问题来了,我们如何降低成本价值。嗯,这个可以用梯度下降来实现。梯度下降的主要目标是最小化成本值。即 min J( θ )。
现在,为了最小化成本函数,我们需要对每个参数运行梯度下降函数,即
Objective: To minimize the cost function we have to run the gradient descent function on each parameter
Gradient Descent Simplified | Image: Andrew Ng Course
梯度下降有一个类比,我们必须想象自己在一个山谷的山顶,被蒙住眼睛,束手无策,我们的目标是到达山脚。感觉你周围地形的坡度是每个人都会做的。这个动作类似于计算梯度下降,而走一步类似于更新参数的一次迭代。
Gradient Descent analogy
结论
在这篇博客中,我向你介绍了逻辑回归的基本概念。我希望这篇博客对你有所帮助,并能激发你对这个话题的兴趣。
演奏爵士乐时介绍 LSTM 单元
原文:https://towardsdatascience.com/introduction-to-lstm-units-while-playing-jazz-fa0175b59012?source=collection_archive---------15-----------------------
了解长短期记忆(LSTM)单位,并运用它们生成爵士乐使用 Keras
Photo by Chris Bair on Unsplash
长短期记忆(LSTM)单元允许学习很长的序列。它是门控循环单元( GRU )的一个更加通用和健壮的版本,在这篇文章中不会讨论。
在这篇文章中,我们将学习 LSTM 单元是如何工作的,我们将应用它来生成一些爵士音乐。
我们开始吧!
对于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
You can call me Al is a great song!
LSTM 的结构
LSTM 的主要特征是有三个门:
- 更新门
- 忘记大门
- 输出门
下面是一个 LSTM 单位的示意图。三个门通过三个符号的出现来显示:
Schema of an LSTM unit
从上图中,注意在 LSTM 单元的顶部有一条从左到右的线。这条线代表早期的信息如何在网络中传递到下一步,这就是为什么 LSTM 单元如此擅长于记忆长序列。因此,这允许模型捕捉更长范围的依赖性。
这看起来好像没有太多关于 LSTM 的知识,但是要理解这只是一个循环神经网络中的一个单元(MAKE LINK)。上面的绿框只是代表一个 RNN 的一个单位。然后,连接多个单元,形成一个完整的网络。
使用 LSTMs 生成 jazz
现在,我们将使用 LSTM 实现一个 RNN 来生成爵士乐!我们将使用 Keras 实现网络,它将生成一个 15 秒的爵士乐剪辑。
一如既往的全笔记本可供咨询。
不幸的是,用于训练的数据太大,无法上传到 Github 上
概观
我们模型的架构将如下所示:
RNN architecture to generate jazz music. Source
基本上,这个模型会被输入一个音乐值,然后它会产生一系列的音乐值来产生音乐。
在这里,“值”代表一个音符、一个持续时间,它还包含是否同时演奏另一个音符的信息(也称为和弦)。
步骤 1:初始模型设置
首先,我们定义网络中隐藏状态的数量。在这种情况下,我们将使用 64。
现在,Keras 有简单的内置函数来构建模型。然而,对于序列生成,不是所有的输入值都是已知的;它们一次生成一个。因此,我们需要添加一个定制的 for 循环,并定义层对象,以便在步骤之间共享权重。
步骤 2:构建模型
现在,我们准备构建模型:
步骤 3:创建、编译、适应
现在,我们可以创建模型,对其进行编译,并使其符合数据:
第四步:创作音乐
现在,我们开始有趣的部分:让我们用我们的模型产生音乐!
在每个采样步骤中,来自前一个 LSTM 单元的激活和单元状态将在下一个单元中传播,并且它们将用于生成另一个输出。
How the output propagates in the network. Source
要生成音乐,我们需要首先对音符进行采样:
有了这些,我们现在可以预测并创造一个音乐序列:
然后用这个代码单元生成音乐:
out_stream = generate_music(inference_model)
你可以找到我生成的音乐文件(。midi 文件)存储在库中。
就是这样!您学习了什么是 LSTM 单元,以及如何用 Keras 应用它来生成音乐。请记住,LSTM 单位只是 RNN 中使用的块。
对于进一步的阅读,我建议你看看 GRU 单元,因为它是一个 LSTM 的简单版本。
干杯!
机器学习的简单介绍
原文:https://towardsdatascience.com/introduction-to-machine-learning-f41aabc55264?source=collection_archive---------7-----------------------
关于 ML 的数据科学入门帖子。
Credit: congerdesign on Pixabay
本帖与一个 视频 有关,名为《机器学习导论》变现为 走向数据科学 。这个视频的剧本是用 安妮·邦纳 写的。视频中你能听到的声音是爱丽丝·伊里扎里的声音。
Introduction to Machine Learning
介绍
我们目前生活在一个“数据时代”,每天都有大量的数据被收集和存储。面对这种不断增长的数据量,机器学习方法已经变得不可避免。以至于你可能一天用几十次,甚至都没有注意到!
让我们从一个对数百万用户的“日常”机器学习贡献的例子开始:脸书新闻订阅背后的算法。脸书使用机器学习来利用用户的数据和反馈来个性化他们的订阅。如果你“喜欢”一个帖子或停止滚动阅读某个内容,该算法会从中学习,并开始用更多类似的内容填充你的提要。这种学习是持续进行的,因此新闻提要中建议的内容会随着您的偏好而发展,从而使您的用户体验更加愉快。
Facebook uses likes, comments and other signals from users to learn what they are interested in and populate their new feeds in consequences.
这只是一个例子!还有很多其他的。苹果可以在你刚拍的照片里认出你朋友的脸。亚马逊 Echo 理解你,可以回答你的问题。你的吸尘器甚至可以在你的房子周围导航,而网飞会推荐符合你个人资料的视频!机器学习已经成为我们日常生活的一个重要部分,而且不会很快消失。
Machine learning can now be found in many tools that we use on a daily basis.
机器学习的定义
但是机器学习到底是什么?这些看起来很神奇的算法背后是什么?他们是如何利用数据工作得如此出色的?
从形式上来说,机器学习是让计算机在没有明确编程的情况下实现一项任务的科学。换句话说,经典算法和机器学习算法之间的巨大差异在于我们定义它们的方式。
经典算法被赋予精确完整的规则来完成任务。机器学习算法被给予定义模型的一般准则,以及数据。这些数据应该包含模型完成任务所需的缺失信息。因此,当模型已经相对于数据进行了调整时,机器学习算法可以完成其任务。我们说“根据数据拟合模型”或者“必须根据数据训练模型。”
让我们用一个简单的例子来说明这个问题。假设我们想根据房子的大小、花园的大小和房间的数量来预测房子的价格。
Features we are going to consider in our house pricing example.
我们可以尝试建立一个经典算法来解决这个问题。该算法必须采用三种房屋特征,并根据显式规则返回预测价格。在这个例子中,确切的房价公式必须是已知的,并明确编码。但在实践中,这个公式往往不为人知。
For our house pricing example, a classical programming approach would consists in coding explicitly the formula that gives the price of a house depending on the three features we are considering.
另一方面,我们可以建立一个机器学习算法。首先,这种算法将定义一个模型,该模型可以是根据我们有限的知识创建的不完整的公式。然后,通过对给定的房价实例进行训练来调整模型。为此,我们将模型与一些数据结合起来。
For our house pricing example, a machine learning approach would consists in defining a model that contains a partial knowledge about the house pricing formula and use the available data to “specify” the model (we fit the model on the data).
总的来说,当我们拥有不完整的信息或太复杂而无法手工编码的信息时,机器学习对于困难的任务非常有用。在这种情况下,我们可以将现有的信息提供给我们的模型,让这个模型自己“学习”它需要的缺失信息。然后,该算法将使用统计技术直接从数据中提取缺失的知识。
监督和非监督模型
机器学习技术的两个主要类别是监督学习和非监督学习。
在监督学习中,我们希望得到一个模型,根据数据的特征来预测数据的标签。为了学习特征和标签之间的映射,模型必须适合于具有相关标签的特征的给定示例。我们说“模型是在一个有标签的数据集上训练的。”
预测标签可以是数字或类别。例如,我们可以构建一个预测房价的模型,这意味着我们想要预测一个数字标签。在这种情况下,我们将讨论一个回归模型。否则,我们可能还想定义一个模型,根据给定的特征预测一个类别,比如“猫”或“不是猫”。在这种情况下,我们将讨论一个分类模型。
Overview of supervised learning (not exhaustive).
在无监督学习中,我们希望定义一个模型,揭示一些数据中的结构,这些数据只通过它们的特征来描述,而没有标签。例如,无监督学习算法可以帮助回答诸如“我的数据中有组吗?”或者“有什么方法可以简化我的数据描述?”。
该模型可以在数据中寻找不同种类的底层结构。如果它试图在数据中找到组,我们将讨论一个聚类模型。聚类模型的一个示例是根据客户的配置文件对公司客户进行细分的模型。否则,如果我们有一个模型来转换数据,并用较少的特征来表示它们,我们会谈到一个降维模型。这方面的一个例子是将一些汽车的多种技术特征总结成几个主要指标的模型。
Overview of unsupervised learning (not exhaustive).
总之,监督学习模型将标签与其特征描述的每个数据点相关联,而非监督学习模型在所有数据点中寻找结构。
从某种意义上说,监督学习类似于从一本图画书中学习水果的名称:你将水果的特性——特征——与写在页面上的名称——标签联系起来。监督学习算法的经典例子是线性回归、逻辑回归、支持向量机、神经网络等等。
另一方面,无监督学习就像拿着同一本水果图画书,分析所有的水果以检测模式,然后决定按颜色和大小对水果进行分组。无监督学习算法的经典例子是 k 均值聚类、层次聚类、主成分分析、自动编码器等等。
结论
让我们以提到机器学习并不那么新来结束这篇文章,驱动今天的应用程序的许多算法已经存在多年了。然而,随着时间的推移,我们取得了一些重大进步:我们建立了比以往任何时候都大的数据集,我们提高了计算能力,我们想象出了新的前沿模型。如果这些进步已经使我们有可能在许多任务上接*甚至超越人类的能力,那么毫无疑问,我们只是触及了可能的表面!
我们真的希望你喜欢这篇文章。不要犹豫,留下你的反馈,在评论区告诉我们你对即将到来的视频感兴趣的话题。
感谢您的阅读,我们将在迈向数据科学节目中再见!
与 Baptiste Rocca 共同撰写的关于该主题的前一篇帖子:
[## 从线性回归到神经网络的温和旅程
一些机器学习和深度学习概念的软介绍。
towardsdatascience.com](/a-gentle-journey-from-linear-regression-to-neural-networks-68881590760e) [## 机器学习中不*衡数据集的处理
面对不*衡的班级问题,应该做什么,不应该做什么?
towardsdatascience.com](/handling-imbalanced-datasets-in-machine-learning-7a0e84220f28)
初学者机器学习入门
原文:https://towardsdatascience.com/introduction-to-machine-learning-for-beginners-eed6024fdb08?source=collection_archive---------3-----------------------
初学者机器学习入门
在过去的几年中,我们已经将机器学习视为一个热门词汇,其原因可能是应用程序产生了大量的数据,过去几年中计算能力的增加以及更好的算法的开发。
从自动化日常任务到提供智能见解,机器学习被用于任何地方,每个行业都试图从中受益。您可能已经在使用利用它的设备。比如 Fitbit 这样的可穿戴健身追踪器,或者 Google Home 这样的智能家居助手。但是使用 ML 的例子要多得多。
- 预测-机器学习也可以用于预测系统。以贷款为例,为了计算错误的概率,系统需要对可用数据进行分组。
- 图像识别-机器学习也可以用于图像中的人脸检测。在几个人的数据库中,每个人都有一个单独的类别。
- 语音识别——它是将口语单词翻译成文本。它被用于语音搜索等等。语音用户界面包括语音拨号、呼叫路由和设备控制。它也可以用来进行简单的数据输入和编写结构化文档。
- 医疗诊断— ML 经过训练,能够识别癌组织。
- 金融行业和贸易—公司在欺诈调查和信用检查中使用 ML。
机器学习简史
Image: Linked In | Machine Learning vs Deep learning
第一个手动操作的计算机系统 ENIAC(电子数字积分器和计算机)是在 20 世纪 40 年代发明的。在那个时候,“计算机”这个词被用来称呼具有密集的数值计算能力的人,所以,ENIAC 被称为数值计算机器!嗯,你可能会说跟学习无关?!错了,从一开始这个想法就是建造一台能够模仿人类思维和学习的机器。
EIMC — Electronic Numerical Integrator and Computer | Image: www.computerhistory.org
在 20 世纪 50 年代,我们看到第一个声称能够打败跳棋世界冠军的电脑游戏程序。这个程序帮助跳棋玩家提高了他们的技能很多!大约在同一时间,弗兰克·罗森布拉特发明了感知器,这是一个非常非常简单的分类器,但当它在网络中大量组合时,它就变成了一个强大的怪物。嗯,怪物是相对于时间而言的,在那个时间里,它是一个真正的突破。然后,我们看到神经网络领域由于难以解决某些问题而停滞了几年。
多亏了统计学,机器学习在 20 世纪 90 年代变得非常有名。计算机科学和统计学的交叉催生了人工智能中的概率方法。这使得该领域进一步转向数据驱动的方法。有了大规模的可用数据,科学家们开始构建能够分析和学习大量数据的智能系统。作为一个亮点,IBM 的深蓝系统击败了国际象棋世界冠军,特级大师加里·卡斯帕罗夫。是的,我知道卡斯帕罗夫指控 IBM 作弊,但这已经是历史了,深蓝现在正在博物馆里安息。
什么是机器学习?
根据亚瑟·塞缪尔的说法,机器学习算法使计算机能够从数据中学习,甚至改进自己,而无需显式编程。
机器学习(ML)是一种算法,它允许软件应用程序在预测结果时变得更加准确,而无需显式编程。机器学习的基本前提是建立可以接收输入数据并使用统计分析来预测输出的算法,同时随着新数据的出现更新输出。
机器学习的类型?
机器学习可以分为 3 种类型的算法。
- 监督学习—[链接将在未来的博客中发布]
- 无监督学习—[链接即将出现在未来的博客中]
- 强化学习—[链接将在未来的博客中发布]
3 Types of Learning
监督学习算法综述
在监督学习中,人工智能系统提供了带标签的数据,这意味着每个数据都贴上了正确的标签。
目标是很好地逼*映射函数,以便当您有新的输入数据(x)时,可以预测该数据的输出变量(Y)。
Example of Supervised Learning
如上例所示,我们最初获取了一些数据,并将其标记为“垃圾邮件”或“非垃圾邮件”。该标记数据由训练监督模型使用,该数据用于训练模型。
一旦它被训练,我们可以通过用一些测试新邮件测试它来测试我们的模型,并且模型的检查能够预测正确的输出。
监督学习的类型
- 分类:一个分类问题是当输出变量是一个类别时,比如“红”或“蓝”或“病”和“没病”。
- 回归:回归问题是当输出变量是一个实值时,比如“美元”或者“重量”。
无监督学习算法综述
在无监督学习中,人工智能系统呈现的是未标记、未分类的数据,系统的算法在没有事先训练的情况下对数据进行操作。输出取决于编码算法。让系统接受无监督学习是测试人工智能的一种方式。
Example of Unsupervised Learning
在上面的例子中,我们给了我们的模型一些角色,它们是“鸭子”和“不是鸭子”。在我们的训练数据中,我们不为相应的数据提供任何标签。无监督模型能够通过查看数据类型来区分两种特征,并对数据中的底层结构或分布进行建模,以便了解更多信息。
无监督学习的类型
- 聚类:聚类问题是你想要发现数据中的内在分组,比如按照购买行为对客户进行分组。
- 关联:关联规则学习问题是你想要发现描述大部分数据的规则,比如购买 X 的人也倾向于购买 y
强化学习概述
强化学习算法或代理通过与其环境交互来学习。代理通过正确执行获得奖励,通过错误执行获得惩罚。代理通过最大化它的奖励和最小化它的惩罚在没有人类干预的情况下学习。它是一种动态编程,使用奖惩系统来训练算法。
Example of Reinforcement Learning
在上面的例子中,我们可以看到代理有两个选项,即有水的路径或有火的路径。强化算法对奖励系统起作用,即,如果代理使用火道,则奖励被减去,代理试图学习它应该避开火道。如果它选择了水路或者安全的路径,那么一些点将会被加到奖励点上,代理将会试着学习什么路径是安全的,什么路径是不安全的。
它基本上是利用获得的回报,代理提高其环境知识来选择下一个行动。
摘要
在这篇博客中,我已经向你介绍了机器学习的基本概念,我希望这篇博客是有帮助的,并且会激发你对这个主题产生足够的兴趣。
用 ML 介绍 C#中的机器学习。网
原文:https://towardsdatascience.com/introduction-to-machine-learning-in-c-with-ml-net-bf45502d8110?source=collection_archive---------4-----------------------
当想到数据科学和机器学习时,两种编程语言 Python 和 R 立即浮现在脑海中。这两种语言支持所有常见的机器学习算法、预处理技术等等,因此可以用于几乎所有的机器学习问题。
然而,有时个人或公司不能或不想使用 Python 或 r。这可能是因为许多原因之一,包括已经有了另一种语言的代码库或没有 Python 或 r 的经验。当今最流行的语言之一是 C#,它用于许多应用程序。为了在 C#中使用机器学习的力量,微软创建了一个名为 ML.NET 的包,它提供了所有基本的机器学习功能。
在本文中,我将向您展示如何使用 ML.NET 创建一个二进制分类模型,讨论其 AutoML 功能,并向您展示如何使用张量流模型与 ML.NET。二进制分类模型的完整代码可以在 my Github 上找到。
将 ML.NET 添加到 C#项目中
将 ML.NET 添加到你的 C#或 F#项目中实际上是相当容易的。唯一需要的就是安装微软的T3。ML 包。根据你的使用情况,你可能还需要安装一些额外的包,比如微软的 。微软图像分析公司。ML.TensorFlow 或 微软。ML 变压器 。
加载数据集并创建数据管道
在 ML.NET 加载和预处理数据集与使用其他机器学习包/框架非常不同,因为它要求我们显式地陈述我们的数据结构。为此,我们在名为 DataModels 的文件夹内创建一个名为model input . cs的文件。在这个文件中,我们将陈述数据集的所有列。
对于本文,我们将使用可以在 Kaggle 上免费下载的信用卡欺诈检测数据集。这个数据集包含 31 列。交易的类别(0 或 1)、交易的金额、交易发生的时间以及 28 个匿名特征。
这里,我们为数据集中的每一列创建一个字段。重要的是指定正确的数据类型和列索引。
既然我们已经对数据进行了建模,我们还需要对我们的输出进行建模。这可以通过与上述脚本类似的方式来完成。
这里我们有两个字段。分数字段以百分比表示输出,而预测字段是布尔值。
既然我们已经建模了输入和输出数据,我们可以使用 LoadFromTextFile 方法加载实际数据。
创建和训练模型
要使用 model 创建和训练模型,我们需要创建一个管道,其中包含所需的数据预处理和训练算法。对于这个特殊的数据集,很难做任何预处理,因为它有 28 个匿名特征,因此我选择保持简单,只连接所有特征(这必须总是在 ML 中完成。网)。
对于模型,我选择了 LightGBM 算法。这个算法实际上并没有包含在微软的 中。ML 因此你需要安装 微软。ML . light GBM来使用。
现在我们可以使用 Fit 方法训练模型,并使用ml context . model . save保存它。
评估模型
现在我们的模型已经训练好了,我们需要检查它的性能。最简单的方法是使用交叉验证。ML.Net 为我们提供了各种不同数据集的交叉验证方法。因为我们的数据集是一个二元分类数据集,我们将使用 mlContext。binary classification . CrossValidateNonCalibrated方法对我们的模型进行评分。
做预测
使用 ML.NET 对新数据进行预测非常简单。我们只需要创建一个prediction engine,专门为我们的模型做的另一个表示,并调用它的 Predict 方法,传递它一个 ModelInput 对象。
自动毫升
ML.NET 的另一个伟大之处是它出色地实现了自动 ML 。使用 Auto-ML,我们可以通过指定我们正在处理的问题并提供我们的数据来构建基本的机器学习解决方案。
要在 ML.NET 开始使用 Auto-ML,您需要下载“ML.NET 模型构建器(预览)”Visual Studio 扩展。这可以通过扩展选项卡来完成。
成功安装扩展后,可以通过在解决方案浏览器中右键单击您的项目并选择添加- >机器学习来使用 Auto-ML。
这将打开“模型构建器”窗口。模型构建器将指导您完成构建机器学习模型的过程。
有关如何完成所有步骤的信息,请务必查看官方入门教程。完成所有步骤后,模型构建器将自动生成代码。
使用预先训练的张量流模型
ML.NET 的另一个伟大之处是它允许我们使用 Tensorflow 和 ONNX 模型进行推理。要使用 Tensorflow 模型,您需要安装微软的 。ML.TensorFlow 使用 NuGet。安装必要的包后,您可以使用 模型加载 Tensorflow 模型。LoadTensorFlowModel 方法。之后需要调用ScoreTensorFlowModel方法,并传递给它输入输出层名称。
有关如何在 ML.NET 使用 Tensorflow 模型的更多信息,请查看“使用 ML.NET c#代码运行从 Azure Cognitive Services Custom Vision 导出的 TensorFlow 模型”。
结论
ML。NET 是一个. NET 包,允许您在. NET 中创建和使用机器学习模型。在本文中,您学习了如何使用 ML.NET 创建一个信用卡欺诈检测模型。
这就是这篇文章的全部内容。如果你有任何问题或者只是想和我聊天,请在下面留下评论或者在社交媒体上联系我。如果你想获得我博客的持续更新,请确保在 Medium 上关注我,并加入我的时事通讯。
机器学习模型解释简介
原文:https://towardsdatascience.com/introduction-to-machine-learning-model-interpretation-55036186eeab?source=collection_archive---------16-----------------------
Figure 1: Photo by Christopher Gower on Unsplash
不管你在解决什么问题,一个可解释的模型总是首选的,因为最终用户和你的老板/同事都能理解你的模型真正在做什么。模型可解释性还可以帮助您调试您的模型,让您有机会看到模型真正认为什么是重要的。
此外,你可以使用可解释的模型来打击普遍认为机器学习算法是黑盒,我们人类无法获得关于它们如何工作的任何见解。
本文是我系列文章的第一篇,旨在解释我们如何实现可解释的机器学习/人工智能的不同方法。
为这个系列做计划
我的系列文章将涵盖关于如何让机器学习变得可解释的理论和实践信息。文章的结构如下:
第 1 部分:机器学习模型的可解释性
- 什么是模型解释?
- 模型解释的重要性
- 什么特性对模型很重要?
- 理解个人预测
第二部分:哪些特性是重要的
- 如何获得不同类型模型的特征重要性
- 什么是部分相关图,如何使用它们
第 3 部分:解读个人预测
- 局部可解释的模型不可知解释(LIME)
- SHapley 加法解释(shap 值)
为什么机器学习中的可解释性很重要?
即使在今天,数据科学和机器学习应用仍然被视为能够神奇地解决没有它就无法解决的任务的黑匣子。这是完全不正确的,为了数据科学项目的成功,开发团队必须对他们试图解决的问题有很好的理解,并且知道他们需要什么样的模型来解决手头的问题。
然而,考虑到大多数商业人士不会对机器学习管道有直观的理解,因此不会理解你花哨的精度指标或损失函数,你需要另一种方式向他们展示你的模型的性能。
此外,良好的性能并不总是意味着您的模型在做正确的事情,因此经常会出现以下问题:
- 我为什么要相信这个模型?
- 模型是如何做出预测的?
数据科学家和研究人员多年来一直试图回答这些问题,并提出了多种方法来提取有关机器学习模型决策过程的信息。
这些方法中的一些是特定于模型的,而另一些适用于所有的模型,不管模型有多复杂。说到复杂性,每个数据科学家都知道模型可解释性与模型性能之间的权衡,这基本上就是说,如果我们增加模型的复杂性,就更难正确解释它。
一般来说,线性模型以及基于树的模型可以很容易地解释,因为它们以直观的方式获得预测,但是您可能需要牺牲准确性,因为这些模型很简单,并且很容易根据问题欠拟合或过拟合。
另一方面,您有更复杂的模型,如集合模型(如随机森林、XGBoost 等)以及深度神经网络,由于其复杂性,这些模型尤其难以解释。
对于欺诈检测、无人驾驶汽车或贷款等现实世界的问题,该模型不仅需要表现良好,还需要易于解释,以便我们可以了解贷款被批准/未被批准的原因,并使用我们的领域专业知识来验证或纠正决策。
理解模型解释
如上所述,模型可解释性试图理解和解释机器学习模型在进行预测时采取的步骤和决策。它让我们能够质疑模型的决策,并了解以下方面。
- 什么特征/属性对模型很重要?你应该能够提取关于哪些功能是重要的,以及功能如何相互作用以创建强大信息的信息。
- 为什么模型会得出这个结论?你还应该能够提取关于特定预测的信息,以验证和证明为什么模型会产生某种结果。
模型可解释性的类型
多年来,数据科学家和研究人员开发了许多不同类型的模型可解释性技术。这些技术可以分为不同的类型,如 Christoph Molnar 的优秀免费在线书籍“可解释的机器学习,使黑盒模型可解释的指南”中所述。
内在的还是事后的?内在可解释性是指由于结构简单而被认为是可解释的模型,如线性模型或树。事后可解释性是指在训练模型后,通过应用模型可解释性方法(如特征重要性、部分相关性或时间)来解释类似神经网络或集成的黑盒模型。
特定于模型还是与模型无关?特定于模型的解释工具专用于单个模型或一组模型。这些工具在很大程度上依赖于特定模型的工作和功能。相比之下,模型不可知的工具可以用在任何机器学习模型上,不管它有多复杂。这些不可知的方法通常通过分析要素输入和输出对来工作。
本土还是全球?解释方法是解释单个预测还是整个模型行为?
哪些特征是重要的,它们如何影响预测
模型一般表现如何?什么特征驱动预测?哪些特性不值得收集它们所花费的金钱和时间?这些都是公司在考虑为某种任务构建机器学习解决方案时可能会问的重要问题。全局模型可解释性通过解释什么特征是重要的、它们如何重要以及它们如何相互作用来帮助回答这些问题。
特征重要性
特征的重要性是在我们置换了特征的值之后模型的预测误差的增加,这打破了特征和真实结果之间的关系。— 可解释的机器学习,一个让黑盒模型变得可解释的指南
Figure 2: Feature Importance Example
特征重要性是一个非常简单的概念,在大多数主要的机器学习库中都有实现,包括 Scikit Learn、XGBoost、LightGBM。
如果打乱某个特征的值会使模型误差大幅增加,则该特征被认为是重要的,因为这意味着模型依赖于该特征进行预测。相比之下,如果打乱某个特征的值对模型的误差没有影响,那么该特征就不重要。
部分相关图
虽然特性重要性向我们展示了哪些特性是重要的,但它并没有给我们关于特性中特定变化的影响的信息。部分相关性图可以显示目标和特征之间的关系是线性的、指数的还是更复杂的。
Figure 3: Partial Dependence Plot Example
部分函数告诉我们特征 s 的给定值的*均边际效应。它通过强制所有数据点具有相同的特征值(例如,将性别列的每个值替换为女性)来获得特征中每个唯一值的 PDP 估计值。
有关部分依赖图如何工作的更多信息,请查看可解释机器学习的部分依赖图部分,这是一个使黑盒模型可解释的指南。
理解个人预测
模型为什么做出这个具体的预测?随着机器学习模型越来越多地用于欺诈检测或医疗任务等应用,这个问题变得越来越重要,因为对于这些类型的应用,能够验证和证明模型产生的结果尤为重要。
LIME(局部可解释的模型不可知解释)
局部代理模型是可解释的模型,用于解释黑盒机器学习模型的个体预测— Christoph Molnar
在论文《我为什么要相信你?作者提出了一种称为局部可解释模型不可知解释(LIME)的方法,其中代理模型被训练为局部地而不是全局地*似底层黑盒模型的预测。
它通过围绕感兴趣的数据点从置换的数据点创建新的数据集,以及黑盒模型的相应预测来实现这一点。然后,LIME 使用这个新的数据集来训练一个可解释的模型,如树或线性模型,然后可以用来解释这个局部点的黑盒模型。
沙普利值
沙普利值是一种根据玩家对总支出的贡献将支出分配给玩家的方法。但是这和机器学习有什么关系呢?
在机器学习的情况下,“游戏”是对数据点的预测任务。“增益”是预测减去所有实例的*均预测,而“玩家”是数据点的特征值。
Shapley 值是一个特性值在所有可能的联合中的*均边际贡献。这是一种解释单个预测的极好方法,因为它不仅给出了每个特征值的贡献,而且这些贡献的大小也是正确的,这与 LIME 等其他技术不同。
Figure 4: Shap example
在本系列的第三部分中,我们将更仔细地研究局部解释方法,如 LIME 和 Shapley 值,我们不仅将学习这些技术的理论,还将在真实数据集上实现它们。
进一步阅读
[## 可解释的机器学习
机器学习算法通常作为黑盒运行,不清楚它们如何得出某种决定。这个…
christophm.github.io](https://christophm.github.io/interpretable-ml-book/) [## 人类可解释的机器学习的重要性
人类可解释机器学习和模型解释简介
towardsdatascience.com](/human-interpretable-machine-learning-part-1-the-need-and-importance-of-model-interpretation-2ed758f5f476)
结论
模型可解释性不仅有助于调试您的模型,使您作为机器学习工程师的生活更加轻松,而且还有助于建立人类与模型之间的信任,随着机器学习在越来越多的行业中得到使用,这变得越来越重要。
下一步是什么?
在本系列的第 2 部分中,我们将更仔细地研究特性重要性和部分依赖图,不仅深入研究这些技术的细节,还将使用 eli5 和 pdpbox 库应用我们的知识。
感谢您阅读帖子。如果你对我接下来应该报道的内容有任何反馈、建议或想法,请随时在社交媒体上发表评论或联系我。
机器学习自顶向下方法简介
原文:https://towardsdatascience.com/introduction-to-machine-learning-top-down-approach-8f40d3afa6d7?source=collection_archive---------3-----------------------
超级流畅的机器学习入门
我们从未想象过计算机会改进到什么程度,成为我们今天拥有的巨大机器,它们不仅在自己的工作上变得更好,还在征服其他工作。
在我写这篇文章的时候
- 互联网上有 4,156,513,325 个用户,如果你试图去数他们,需要 128 年以上。
- 互联网上的 1755606975 个网站。
- 仅今天就发了 168,673,726,872 封邮件。
- 仅今天就有 4723747823 次谷歌搜索。
- 仅今天就有 4033234 篇博文。
- 仅今天在 youtube 上就有 4553543234 次视频观看。
我可以永远这样下去,这些数字增长得令人难以置信地快,大量的数据存在,我们甚至可以让计算机了解这些数据,我们可以对计算机进行编程,从这些数据中获得某种经验,并形成一个简单的小型大脑(大多数情况下是愚蠢的),但致力于解决一个特定的问题,甚至一个以上的问题,只要你是忍者级别的程序员/研究员。
这个大脑我们经常称之为模型,它很可能是一个函数,如果你有大量的数据,并且想要大脑/模型变得复杂和精密,你可以让它成为一个更高次的函数(又名神经网络),我说的更高次不是指我们在学校学的三次或二次函数,我指的是更高。
这并不像听起来那么复杂,一切都很容易
好消息是(机器学习介绍)不是带你深入这个复杂的数学东西的地方。
首先,我会让你相信机器学习是一个非常有趣的领域,并告诉你一些关于机器人、人脸检测、垃圾邮件检测等等的东西,但我希望这是简短而中肯的,所以请阅读下面的内容,尝试在你的脑海中绘制一幅地图,并保持专注,从现在开始!
定义一个大纲
—机器学习系统读取数据集并优化大脑/模型以解决问题。
关注这些关键词,我们将逐一讨论。 -machine learning-System(ML-System):控制整个过程的算法 - Dataset: 提供给系统的数据。 -模型:我们优化解决问题的大脑或功能。 -问题:令人惊讶的是这正是我们要解决的问题。
机器学习系统
让我们从谈论machine learning-System(ML-System)开始,它只是一个完成工作的算法,遍历数据集,初始化模型并将数据馈送给模型以从中学习。
机器学习系统的分类:
我们可以将机器学习系统分为多个类别,如下所示。
1.模型是否经过人工监督训练(有监督、无监督、半监督和强化学习)、、用更简单的话说:
- 在监督ML-系统中,您输入算法的训练数据(数据集)包括所需的解决方案,称为 标签。
- 在无监督 ML-System 中,你馈送给算法的训练数据(数据集)是未标记的(不包括期望的解),系统尝试在没有老师的情况下学习。
- 在半监督ML-系统中,您提供给算法的训练数据(数据集)被部分标记。
- 在强化ML-系统中,它有一点不同,这里的模型被称为代理,它的工作是执行动作,他获得奖励,代理然后学习,因为他试图最大化奖励,这就像用糖果训练你的宠物。
2.模型是否可以动态增量学习(在线学习、批量学习),用更简单的话来说:
- 在批量学习中,模型不能增量学习。首先,我们让模型根据所有数据进行训练,然后将其投入生产。
- 在在线学习中,模型通过顺序输入实例进行增量训练,或者单独输入,或者通过称为小批量的小组输入。
资料组
它是提供给系统进行训练的训练数据,我们将数据集的复杂性降低到特征中,以便于模型从数据中学习
特征是被观察现象的个体可测量的属性或特征。
例如,让我们使用房价数据集,它主要是一个表,其中每行代表一所房子,列= [ 'house_id ',' house_size ',' no_of_rooms ',' price' ],而问题是预测房子的价格。
决定使用哪些功能是非常重要的一步,您必须考虑很多事情,我将在另一篇文章中带您完成这一步,但我们可以从 features = [house_size,no_of_rooms]开始,因为这是一个简单的示例。
我们正在使用的模型将试图了解如何根据给定的特征来估计这些标签(输出),换句话说,房子的价格如何受到其大小和房间数量的影响。这个过程叫做,训练 。
我们在数据集上可能面临的问题
- 训练数据量不足。 模型需要成千上万个例子来解决简单的问题,而对于图像识别等更复杂的问题,它们需要数百万个例子
在 2001 年发表的一篇著名论文中,微软研究人员 Michele Banko 和 Eric Brill 表明,一旦给定足够的数据,非常不同的机器学习算法(包括简单的算法)在复杂的问题上表现得一样好。
由此可见训练数据的数量有多重要。 - 非代表性训练数据。 使用代表您想要归纳的案例的训练数据至关重要,数据集应覆盖尽可能多的不同案例。
- 数据质量差。 这意味着它充满了意想不到的错误、噪音和异常值,这将使模型更难检测模式,并且很可能不会执行得很好。有一些时间清理数据或者丢弃有噪声的部分。
- 无关的特征。 特征选择是一个非常重要的步骤,模型可以检测出期望的标签(解)和一个不相关的特征之间的关系,这将使预测更加随机。
- 过拟合。 表示模型在训练数据上表现很好,但泛化能力不好。换句话说,模型已经很好地学习了训练数据,它记住了它,这很可能是因为模型相对于数据量和噪声来说太复杂了。(如果你在另一篇文章中遇到这个问题,我会告诉你怎么做)。
- 营养不良。 很明显是过度拟合的反义词,这种情况发生在模型过于简单无法理解数据的时候。
要知道为你的项目选择哪个模型,阅读本文 使用哪个机器学习模型?
这里有一些模型你可以看看,我会写文章解释它们是如何工作的。
监督学习算法示例
- k-最*邻
- 线性回归
- 逻辑回归
- 支持向量机
- 决策树和随机森林
- 神经网络——注意:一些神经网络可以是无监督的(如自动编码器和受限玻尔兹曼)或半监督的。
无监督学习算法示例
- 聚类(例如,k 均值、层次聚类分析 HCA)
- 可视化和维度缩减(例如主成分分析 PCA)
- 关联规则学习(例如 Eclat)
你可以阅读 5 步和 10 步,来学习机器学习发表在《走向数据科学》刊物上的文章
祝你的机器制造愉快创意 。
用口袋妖怪介绍机器学习
原文:https://towardsdatascience.com/introduction-to-machine-learning-with-pokemon-ccb7c9d1351b?source=collection_archive---------15-----------------------
使用 R 进行逻辑回归和决策树分析的指南。
Photo by Kamil S on Unsplash
R 是什么?
r 是一种免费的统计编程语言。
根据 guru99 ,
r 是一种编程语言,被数据科学家和大公司广泛使用,如谷歌、Airbnb、脸书等。用于数据分析。
什么是机器学习?
机器学习是人工智能的一个分支。机器学习的主要目的是教会程序如何训练自己并从错误中学习。目标是让程序不断学习和发展其预测的准确性,而不需要定期接受训练。如果你有兴趣了解更多,这里有一个有用的链接。
许多类型的模型可以用于机器学习,但是对于本文的目的;我将重点介绍逻辑回归和决策树。
逻辑模型
逻辑回归用于确定事件发生或不发生的概率。当因变量是分类变量时使用。
例如,预测某人是男性(1)还是女性(0)。
决策图表
决策树是用于分类和预测的标准工具。它使用一个易于理解的图表来展示测试并输出两个结果。这种模式一直持续到测试有一个合理的预测结果。
对于这个分析,我将使用一个包含 800 个口袋妖怪角色和几个变量的数据集。如果你想访问这个数据集来进行你的实验,这里有一个链接来下载它。
目标
这样做的目的是建立一个逻辑模型和一个决策树来帮助预测一个口袋妖怪是否会被归类为传奇的概率。只有少数口袋妖怪被认为是传奇,所以我们想看看我们的模型是否能准确预测它。
我的分析假设你已经熟练使用 r。
设置
library(ggplot2)
library(gplots)
library(readr)
library(rpart)
library(ROCR)
library(rpart.plot)
库 rpart , ROCR , rpart.plot 是 r 中决策树所必需的
读入文件
pkdf <- read.csv("Pokemon.csv")
head(pkdf)
We see in the last column on the right the Legendary status of the pokemon
逻辑回归模型
我们将需要使用glm()函数来获取 logistic 模型。该函数要求我们传入自变量,后跟一个波浪号(~)。**
- 第一个逻辑模型—所有变量
首先,我将尝试使用所有因变量的模型。
*pk_logit_model_1 <- glm(Legendary ~ Attack + Defense + Sp_Atk + Sp_Def + HP + Speed, data = pkdf, family = "binomial")
summary(pk_logit_mode_1)*
Logistic Model 1
在 R 中,每个变量右边的让我们知道这个变量是否重要。正如我们看到的,所有的变量都是重要的。让我们再测试几个模型,看看是否会得到不同的结果。*
2。第二个逻辑模型—移除防御变量**
对于这个模型,我将去掉防御变量,观察结果。每次删除变量时,一次删除一个变量是很重要的。
*pk_logit_model_2 <- glm(Legendary ~ Attack + Sp_Atk + Sp_Def + HP + Speed, data = pkdf, family = "binomial")
summary(pk_logit_mode_2)*
Logistic Model 2
我们可以看到所有变量都保持显著,但如果我们看一下顶部的偏差残差,我们可以看到中值偏差残差下降了,这很好。
如果你不熟悉中位数偏差残差,这里的是一个很好的解释。
3。第三个逻辑模型—移除速度变量**
为了测试另一个模型,让我们试着移除速度并查看结果。
*pk_logit_model_3 <- glm(Legendary ~ Attack + Sp_Atk + Sp_Def + HP, data = pkdf, family = "binomial")
summary(pk_logit_model_3)*
Logistic Model 3
我们可以再次看到中值偏差残差下降,这意味着我们的第三个模型更适合我们的预测。
我们如何解释基本回归系数?
让我们看看我们刚刚做的第三个模型。查看第一列,标有的估计值(系数)帮助我们更好地理解我们的模型。重点是攻击变量,其系数为 0.029982。
使用 exp(),计算一个数或数向量的指数值。
*exp(0.029982)-1*
这一行代码的输出是 0.0304 。这可以理解为,
如果攻击增加 1 点,这个口袋妖怪成为传奇的几率增加 3.04%
决策图表
我们已经为决策树模型加载了所有必要的库。使用 rpart() 函数,其结构类似于逻辑建模中使用的【glm()函数。
*pk_tree_model <- rpart(Legendary ~ Attack + Sp_Atk + Sp_Def + HP, data = pkdf, method = "class")rpart.plot(pk_tree_model, type = 1, extra=1, box.palette =c("pink", "green"), branch.lty=3, shadow.col = "gray")*
现在,我们已经完成了决策树模型,我们将把它与我们的第三个逻辑模型进行比较,看看它们在预测一个传奇口袋妖怪方面如何相互竞争。
比较两种模型
接下来的几个代码步骤是必要的,以查看哪个模型执行得最好。获得我们的结果有四个步骤。我称之为 4p。
- 预测
- 预言;预测;预告
- 性能
- 情节
我们的目标是预测每个观察值为 1 的概率。
预测
在我们的模型上使用 predict()函数,并提供我们的数据集进行测试。
*pk_predict_logit <- predict(pk_logit_model, pkdf, type="response")
pk_predict_tree <- predict(pk_tree_model, pkdf, type="prob")*
在继续之前,我们可以做一些初步的测试来了解我们的模型性能。
对 ID 为 59 的口袋妖怪进行测试
*pk_predict_logit[59]
pk_predict_tree[59]*
结果表明 Logit 是 0.002,和 Tree 是 0.974 。这意味着树(97%)非常有信心认为口袋妖怪 59 是传奇,而 Logit (0.2%)并不这么认为。我们可以通过手动拉起口袋妖怪 59 来查看,就是口袋妖怪— 波斯 。波斯不是传说中的口袋妖怪,所以我们的树模型不好。
让我们测试另一个口袋妖怪来仔细检查。
使用 ID 799 对口袋妖怪进行测试
*pk_predict_logit[799]
pk_predict_tree[799]*
结果表明 Logit 为 0.983,和树为 0.3 。这意味着树(3%)不认为口袋妖怪 799 是传奇,Logit (98%)认为它是传奇。口袋妖怪 799 是 胡帕胡帕未绑定其中,根据数据集,被归类为传奇。从而再次证明我们的逻辑模型比树表现得更好。**
下面我们可以继续测试这两种模型。
预言;预测;预告
对我们的预测输出使用预测()函数,并提供传奇变量。它用于转换输入数据。
**pk_logit_prediction <- prediction(pk_predict_logit, pkdf$Legendary)
pk_tree_prediction <- prediction(pk_predict_tree[,2], pkdf$Legendary)**
表演
在我们的预测输出上使用性能()函数,来评估谁被评估得好。
输入“tpr”表示真阳性,“fpr”表示假阳性。
**pk_performance_logit <- performance(pk_logit_prediction,"tpr","fpr")
pk_performance_tree <- performance(pk_tree_prediction,"tpr","fpr")**
情节
在我们的性能上使用 plot()函数来获得我们的两个模型表现如何的可视化表示。
**plot(pk_performance_logit,col="blue",lty=3, lwd=3)
plot(pk_performance_tree,col="black",lty=3, lwd=3, add=TRUE)**
Comparisons of the two models
蓝线代表逻辑模型,黑线代表决策树模型。
正如我们所看到的,蓝线(逻辑)在那里表现更好,这是一个更好的选择,用来帮助确定口袋妖怪有传奇分类的概率。
我的资源:
- RPub 文档
- Github 库
- 口袋妖怪数据集
Python 中 Matplotlib 的介绍
原文:https://towardsdatascience.com/introduction-to-matplotlib-in-python-5f5a9919991f?source=collection_archive---------16-----------------------
在matplotlib库中使用数据可视化技术的快速指南
什么是数据可视化?
是以图形、图标、演示等方式可视化数据的实践。它最常用于将复杂的数据转化为非技术受众易于理解的见解。
如果你是数据可视化的新手,这是一本很好的入门书籍— 用数据讲故事
Python 是什么?
Python 是一种编程语言,可以让你更快地工作,更有效地集成你的系统。
Python 是最流行的编程语言之一,有各种各样有用的应用。对于本文,我假设您已经掌握了 Python 语言的基本知识。
如果你不知道,这里有一些很好的资源,
- w3schools
- 数据营
- Udemy,Python Bootcamp
什么是 Matplotlib?
Python 中有成千上万个 库 ,Matplotlib 是 Python 中最强大的数据可视化工具之一。
Matplotlib 试图让容易的事情变得容易,让困难的事情变得可能。您可以生成图表、直方图、功率谱、条形图、误差图、散点图等。,只需要几行代码。
让我们开始吧!
导入库
为了让 matplotlib 在我们的环境中运行,我们需要导入它。
import **matplotlib.pyplot** as plt
在别名 plt — 下导入 matplotlib 是常见的做法,这样,我们只需键入更少的代码来引用它。
无论何时使用 matplotlib 绘图,两个主要代码行应该是:
- 图表类型—这是您定义条形图、折线图等的地方。
- 显示图表—这是为了显示图表
曲线图
#create data for plotting
x_values = [0,1,2,3,4,5]
squares = [0,1,4,9,16,25]#the default graph style for plot is a line
plt.**plot**(x_values, squares)#display the graph
plt.show
条形图
#create data for plotting
x_values = [5,6,3,7,2]
y_values = ["A", "B", "C", "D", "E"]plt.**bar**(y_val,x_values, **color = "green"**)
plt.show()
当使用条形图时,代码的变化将从 plt.plot() 变为 plot.bar() 将其变为条形图。如果你看看代码的内部,我还添加了一个参数 颜色——这有助于我们快速定制图形的颜色。
我们也可以用下面的方法水*翻转条形图,
#create data for plotting
x_values = [5,6,3,7,2]
y_val = ["A", "B", "C", "D", "E"]# Adding an "h" after bar will flip the graph
plt.**barh**(y_val,x_values, color ="**yellowgreen**")
plt.show()
Notice the change in the color argument
散点图
#create data for plotting
x_values = [0,1,2,3,4,5]
squares = [0,1,4,9,16,25]plt.**scatter**(x_values,squares, **s=10,** color = "pink")
plt.show()
你能看出模式吗?现在代码从 plt.bar() 变成了 plt.scatter()。我还加了 s 的参数。s 代表大小,它允许我们控制我们想要图上的点有多大。
直方图
#generate fake data
x = [2,1,6,4,2,4,8,9,4,2,4,10,6,4,5,7,7,3,2,7,5,3,5,9,2,1]#plot for a histogram
plt.**hist**(x, **bins = 10**, color='blue', **alpha=0.5**)
plt.show()
查看代码片段,我添加了两个新参数。
- bin-是直方图特有的参数,允许用户自定义想要多少个 bin。
- Alpha 显示数据点透明度级别的参数。
如果我同时调整仓位和 alpha,我会得到这样的结果,
x = [2,1,6,4,2,4,8,9,4,2,4,10,6,4,5,7,7,3,2,7,5,3,5,9,2,1]
num_bins = 10plt.hist(x, **bins= 4**, color='blue', **alpha=0.1**)
plt.show()
概观
我们只是触及了 matplotlib 强大功能的表面。一旦你更深入地研究这个主题,你会发现你可以有多少定制能力来创建丰富多彩的、详细的和生动的图形。
matplotlib 库和 python 中的其他流行库提供了更多的图形,包括 seaborn ,pandas plot,和 plotly 。探索所有不同的选项并找到适合您的编码和分析风格的库是值得的。
请继续关注——我将分享一个关于在 matplotlib 中定制图表的教程。
矩阵轮廓简介
原文:https://towardsdatascience.com/introduction-to-matrix-profiles-5568f3375d90?source=collection_archive---------3-----------------------
一种新的时间序列挖掘数据结构
在时间序列分析中,人们通常对两件事感兴趣;异常和趋势。例如,医生检查 EKG(心电图——心跳读数),看是否有异常事件表明患者存在风险。在零售业工作的个人需要了解销售什么商品以及何时销售(季节性)以增加利润。发现时间序列中异常和趋势的一种方法是执行相似性连接。本质上,您可以通过计算每对片段之间的距离来比较时间序列的片段。虽然使用嵌套循环实现一个简单的算法只需很少的努力,但使用这种方法可能需要几个月或几年的时间才能得到中等大小的时间序列的答案。利用矩阵轮廓算法大大减少了计算时间。
Matrix Profile 是一种相对较新的数据结构,于 2016 年推出,由加州大学河滨分校的埃蒙·基奥和新墨西哥大学的阿卜杜拉·穆恩开发。使用矩阵轮廓的一些优点是它是领域不可知的、快速的、提供精确的解决方案(当需要时是*似的)并且只需要单个参数。
本文的主要目标是让您熟悉这些好处,以便您可以利用它们。由于矩阵轮廓主要是可视化的,所以我们在本文中利用这一点,尽可能避开数学符号,而将重点放在可视化上。如果你想要学术描述,请阅读基奥博士网页上的研究出版物。
这篇介绍性文章将涵盖以下内容:
- 矩阵轮廓由什么组成?
- 什么是不和?
- 什么是主题?
- 哪些算法用于计算矩阵轮廓?
- 这些算法有什么区别?
- 从哪里可以得到这些算法?
- 一个简短但实用的不和谐发现的例子。
矩阵简介概述
矩阵轮廓有两个主要组成部分;一个距离轮廓和轮廓索引。距离轮廓是最小 Z 归一化欧几里德距离的矢量。轮廓索引包含其第一个最*邻的索引。换句话说,它是其最相似的子序列的位置。
计算矩阵轮廓的算法使用滑动窗口方法。窗口大小为 m ,算法:
- 计算加窗子序列相对于整个时间序列的距离
- 设置一个排除区域以忽略无关紧要的匹配
- 用最小值更新距离轮廓
- 设置第一个最*邻索引
上面概述的距离计算发生 n-m + 1 次;其中 n 是时间序列的长度,而 m 是窗口大小。由于子序列是从时间序列本身中提取的,因此需要一个排除区来防止的琐碎匹配。例如,匹配自身的代码片段或非常接*自身的代码片段被认为是微不足道的匹配。在当前窗口索引之前和之后,禁止区仅仅是窗口大小的一半( m )。计算最小距离和最*邻索引时,这些索引处的值将被忽略。显示从第二个窗口开始的距离轮廓计算的可视化如下所示。
第二个值窗口,从 X2 到 X5,在时间序列上滑动,计算每个子序列的点积。计算完所有的点积后,将排除区域应用于距离,最小距离存储在矩阵配置文件中。扔掉多余的距离,只保留最小距离,将空间复杂度降低到 0(n)。
主题和主题
简单地说,母题是时间序列中的重复模式,而不一致是异常。计算出矩阵的轮廓后,很容易找到前 K 个基序或不一致。矩阵轮廓在欧几里德空间中存储距离,这意味着接* 0 的距离最类似于时间序列中的另一个子序列,而远离 0 的距离,比如 100,不像任何其他子序列。提取最小的距离给出了主题,最大的距离给出了主题。
矩阵轮廓算法
有一些算法可以计算矩阵轮廓。下表提供了算法的非穷举列表和关于它们的简短描述。
下面的图说明了使用 STAMP、STOMP 或 SCRIMP++比简单的方法有明显的优势。时间序列长度为 1,024,窗口大小为 32,naive 算法需要 50 多秒才能完成!另一方面,其他算法只需几分之一秒就能完成。
矩阵轮廓挖掘算法
一旦计算出矩阵轮廓,就必须使用额外的算法来从中提取信息。在讨论主题和不一致时,我简单地提到了这一点。以下是在矩阵配置文件上运行的算法的非详尽列表。
例子
对于我们的实际示例,我们将检查 2018 年的“纽约市黄色出租车乘客数量”。纽约市公开了许多数据集,以便每个人都可以探索它们。原始数据集带有许多其他属性,并且每分钟都提供详细信息。我汇总并整理了数据,以获得每小时的乘客数量。为了使这个例子简短,我就不详细介绍数据是如何聚合的了。我也避免在整个例子中展示代码。对于那些感兴趣的人,本文有一个公共代码库。
上面显示的原始数据为我们正在处理的问题提供了一些背景信息。您可能已经在数据中直观地看到了一些模式,但是想象一下,如果这是一年多的数据,或者我们查看每分钟的乘客数。如果没有某种类型的转换,很难直观地看到发生了什么。我们将计算不同窗口大小的矩阵轮廓,看看是否有什么有趣的东西突出出来。
上面使用的不同窗口大小说明了选择适当值的重要性。我不明白纽约出租车系统在 4、8 甚至 12 小时周期内的复杂细节。然而,我能够使用搜索引擎研究每天甚至每周的事件。由于在 24 小时和 7 天的窗口内有一些明显的不一致(图中的峰值),我们将把重点放在那些矩阵曲线上。为了提取不一致,我们使用“前 K 个不一致”算法。
上面的图用红色显示了前 5 个不一致。我花了一些时间研究这些可能与什么有关,并在情节中对它们进行了注释。对于每日矩阵配置文件,夏令时似乎对乘客数量有巨大影响。在夏令时,我们在凌晨 2 点左右各慢一个小时。乘客计数受到重复计数的影响,或者计数的乘客非常少。例如,在夏令时开始,我们失去了凌晨 2 点,但一些系统仍然设法在这个时候计数乘客。在这个特定的数据集中,仍然计算了 3 名乘客。
用 7 天矩阵图来观察时间序列,我们会得到稍微不同的结果。独立日和圣诞节在 7 天内有不同的波动。这并不罕见,因为大多数人在独立日会花时间在户外,在圣诞节会和家人在一起。
收尾工作
在本文中,向您介绍了 Matrix Profile 以及如何使用它来分析时间序列数据。这是一种鲜为人知的方法,因为它仍然是新的,但它是一种快速和领域不可知的方法。一旦你有了矩阵的轮廓,提取共同的模式(图案)和异常(不一致)是很容易的。在我们简短的纽约出租车例子中,我通过可视化说明了异常提取。
请记住,我只介绍了矩阵概要文件和一些概念。它提供了更多的功能。流数据分析的增量模式、语义分段和片段发现是更多的功能。我强烈建议任何对 Matrix Profile 或时间序列分析感兴趣的人查看补充部分。
承认
感谢 Tawni Marrs、Andrew Van Benschoten、Francisco Bischoff 和 Jackson Green 花时间阅读本文。最重要的是,我要感谢埃蒙·基奥、阿卜杜拉·穆恩和他们的合作者。没有他们的研究努力,这篇文章就不会存在。
补充的
- 本文的源代码:
https://github . com/matrix-profile-foundation/article-matrix-profile-intro
2.关于矩阵简介的研究论文在埃蒙·基奥的网页上:
【https://www.cs.ucr.edu/~eamonn/MatrixProfile.html 号
3.一个志愿者组织,矩阵档案基金会,链接可以在这里找到:
【https://matrixprofile.org/
4.矩阵轮廓算法的 Python 实现可在此处找到:
https://github.com/matrix-profile-foundation/matrixprofile
5.矩阵分析算法其余实现可在此处找到:
https://github.com/franzbischoff/tsmp
6.矩阵轮廓算法的 Golang 实现可在此处找到:
https://github . com/matrix-profile-foundation/go-matrix profile
Mesa 简介:Python 中基于代理的建模
原文:https://towardsdatascience.com/introduction-to-mesa-agent-based-modeling-in-python-bcb0596e1c9a?source=collection_archive---------0-----------------------
基于 Python 的 NetLogo、Repast 或 MASON 的替代品,用于基于代理的建模
Simulation result showing segregation between blue and red agent
基于代理的建模依赖于模拟自主代理的动作和交互来评估它们对系统的影响。它通常用于预测给定复杂现象时我们将获得的投影。主要目的是在给定一组特定规则的情况下,获得关于代理将如何行为的解释性见解。基于 Agent 的建模已经广泛应用于生物学、社会科学、网络和商业等众多行业。本文涵盖了使用名为 Mesa 的开源 python 模块启动基于代理的建模项目的必要步骤。本教程有 4 个部分:
- 设置
- 谢林分离模型
- 形象化
- 结论
1.设置
对于 Mesa 来说,设置非常简单。确保创建一个新的虚拟环境。我把这个环境命名为 mesaenv。打开您的终端,将目录更改为 mesaenv,并使用以下代码激活虚拟环境:
虚拟环境
根据您的使用情形,运行以下命令来激活虚拟环境。
#Anaconda
conda activate mesaenv#Terminal
source bin/activate
Python 模块
本教程需要三个模块:
- *顶山
- matplotlib
- 朱皮特
python3 -m pip install mesa
python3 -m pip install matplotlib
python3 -m pip install jupyter
基本文件夹
创建一个名为 Mesa 的基本文件夹,用于存储所有 python 文件。在本节末尾的基本文件夹中应该有以下文件:
- Model.py
- Run.py
- Server.py
如果您在教程中迷失了方向,请随意下载它。完成后,让我们继续下一部分。
2.谢林分离模型
在本教程中,我们将使用著名的谢林分离模型作为用例。请注意,mesa 官方网站上的介绍性教程是基于波尔兹曼财富模型的。谢林隔离模型是一个更好的用例,用来解释我们如何利用基于主体的建模来解释为什么种族隔离问题难以根除。尽管实际的模型非常简单,但它提供了关于个体如何自我隔离的解释性见解,即使他们没有明确的愿望这样做。我们来看看 Mesa 官方 github 页面提供的对这个模型的解释:
谢林隔离模型是一个经典的基于主体的模型,它证明了即使是对相似邻居的轻微偏好也能导致比我们直觉预期更高的隔离程度。该模型由正方形网格上的代理组成,每个网格单元最多可以包含一个代理。代理有两种颜色:红色和蓝色。如果他们八个可能的邻居中有一定数量的人是同一种颜色,他们会感到高兴,否则会不高兴。不开心的代理会随机选择一个空单元格移动到每一步,直到他们开心为止。模型一直运行,直到没有不开心的代理。
默认情况下,代理需要满意的相似邻居的数量设置为 3。这意味着代理会非常满意他们的大多数邻居是不同的颜色(例如,一个蓝色代理会满意五个红色邻居和三个蓝色邻居)。尽管如此,该模型始终导致高度隔离,大多数代理最终没有不同肤色的邻居。
Model.py
创建一个名为 model.py 的新 python 文件。
代理:我们将从单个代理类开始。
代码非常简单:
- 初始化代理类。
- 创建一个步骤功能。
- 计算相似邻居的数量。
- 如果代理不满意,请将代理移到空的位置。
型号:为型号类。我们将逐一浏览每一部分,以便更清楚地了解基于代理的建模是如何工作的。首先,创建一个谢林类,并将一个 init 函数定义为构造函数。
class Schelling(Model):
def __init__():
变量:系统将由至少一个基本代理类和一个模型类组成。我们先从写模型开始。我们需要定义 5 个主要变量:
- Width :网格的横轴,与高度一起用于定义系统中代理的总数。
- 高度:网格的纵轴,与宽度一起定义系统中代理的总数。
- 密度:定义系统中代理的群体密度。从 0 到 1 的浮点值。
- 分数少数:蓝色和红色的比例。蓝色代表少数,而红色代表多数。从 0 到 1 的浮点值。如果该值高于 0.5,蓝色反而会成为多数。
- 同向性:定义代理快乐所需的相似邻居的数量。整数值范围从 0 到 8,因为你只能被 8 个邻居包围。
self.height = height
self.width = width
self.density = density
self.minority_pc = minority_pc
self.homophily = homophily
记住在 init 函数中添加所需的参数作为输入参数。
网格:我们需要使用 mesa 下的空间模块来设置网格。
from mesa.space import SingleGridself.grid = SingleGrid(height, width, torus=True)
调度器:接下来,我们需要一个调度器。调度程序是一个特殊的模型组件,它控制代理的激活顺序。最常见的调度程序是随机激活,它以随机顺序每步激活所有代理一次。还有一种叫同时激活。查看 API 参考以了解更多信息。
from mesa.time import RandomActivationself.schedule = RandomActivation(self)
数据收集:数据收集对于确保我们在模拟的每一步后都获得必要的数据至关重要。您可以使用内置的数据收集模块。在这种情况下,我们只需要知道代理人是否快乐。
from mesa.datacollection import DataCollectorself.happy = 0self.datacollector = DataCollector( {"happy": "happy"},
{"x": lambda a: a.pos[0], "y": lambda a: a.pos[1]}
)
代理设置:我们现在将使用以下代码设置代理:
init 函数的最后一部分是设置以下参数:
self.running = True self.datacollector.collect(self)
一旦满足条件,运行变量可有条件地关闭模型。一旦所有的代理都满意了,我们就把它设置为假。
步骤:这个类需要一个表示每次运行的步骤函数。
- 在每一步重置快乐代理的计数器。
- 开始收集数据并确定满意的代理人数。
- 一旦所有代理都满意,就停止模型。
Run.py
创建一个名为 run.py 的新 python 文件,并输入以下代码。
Server.py
创建一个名为 server.py 的新 python 文件。
导入:将以下导入语句添加到文件中:
from mesa.visualization.ModularVisualization import ModularServerfrom mesa.visualization.modules import CanvasGrid, ChartModule, TextElementfrom mesa.visualization.UserParam import UserSettableParameter from model import Schelling
HappyElement: 创建一个名为 HappyElement 的类,并添加两个函数:
- 初始化
- 提供;给予
Draw 函数:定义一个名为谢林 _draw 的函数。
在运行服务器时,该部件充当可视化部件。
- 首先,我们定义基础波特拉尔。描绘是一个字典(可以很容易地转换成 JSON 对象),它告诉 JavaScript 方如何绘制它。
- 我们根据代理的类型改变描绘的颜色和笔触。在这种情况下,我们将有红色和蓝色的代理。
- 初始化画布和图表。
- 设置模型的参数。 UserSettableParameter 表示用户可以在网页中修改该参数。它有 6 个参数(类型、名称、初始值、最小值、最大值、每步值)。
- 最后,我们用上面定义的所有配置初始化服务器。
3.形象化
让我们通过在终端运行下面的代码来测试一下。确保你在基本文件夹(台面)。
mesa runserver
将启动一个 web 浏览器,您应该会看到以下输出:
帆布
我们之前定义的画布网格的可视化。每个点代表一个代理。
Image by Author
环境
您可以修改设置来测试它将如何影响模拟。修改这不会影响当前模拟。记得点击重置按钮进行更改。
Image by Author
每秒传输帧数
您可以定义自己的每秒帧数来加快模拟速度。
Image by Author
开始、步进、复位
您可以使用以下按钮:
- 开始/停止:开始模拟。一旦启动,你可以点击相同的按钮来关闭它。
- 步骤:只运行一个步骤来查看变化。
- 复位:根据设置复位板卡。如果您在模拟运行时使用它,电路板将被重置,模拟将照常运行。
Image by Author
运转
点击开始按钮,您应该会看到画布的以下变化。
Gif by Author
图表
底部有一个图表,显示了满意的代理人数和满意的步骤数。
Image by Author
结果
模型应该在某一点停止,这取决于您设置的设置。你可以注意到代理人几乎是隔离的。
Image by Author
4.结论
让我们回顾一下今天所学的内容。
我们从设置和安装必要的 python 模块的一些简单步骤开始。
然后,我们学习了谢林分离模型,以及如何使用 Mesa 轻松地对其建模。我们创建了 3 个 python 文件,并进一步深入研究了 Mesa 中可用组件的基本用法。
之后,我们运行服务器来查看可视化效果。我们修改了一些设置,并进行模拟。事实上,官方的 Mesa github 为我们提供了更多可以探索的例子。查看以下链接了解更多信息。
希望你喜欢这个教程。祝您愉快,下次教程再见。
参考
- https://github.com/projectmesa/mesa
- https://mesa . readthe docs . io/en/master/tutorials/adv _ tutorial . html
- https://mesa . readthe docs . io/en/master/tutorials/intro _ tutorial . html
- https://github.com/projectmesa/mesa/tree/master/examples
- https://mesa.readthedocs.io/en/master/apis/api_main.html
使用 TensorFlow 的 Keras API 介绍多层神经网络
原文:https://towardsdatascience.com/introduction-to-multilayer-neural-networks-with-tensorflows-keras-api-abf4f813959?source=collection_archive---------11-----------------------
了解如何使用 TensorFlow 的高级 API Keras 构建和训练多层感知器!
Keras
的开发始于 2015 年初。时至今日,它已经发展成为构建在Theano
和TensorFlow
之上的最流行和最广泛使用的库之一。它的一个突出特点是,它有一个非常直观和用户友好的 API,允许我们只用几行代码来实现神经网络。
Keras
也从 1.1.0 版本集成到了TensorFlow
中。它是contrib
模块的一部分(包含由TensorFlow
贡献者开发的包,被认为是实验代码)。
在本教程中,我们将通过浏览以下内容来了解这个高级TensorFlow
API:
- 前馈神经网络的基础
- 加载和准备流行的 MNIST 数据集
- 构建图像分类器
- 训练神经网络并评估其准确性
我们开始吧!
本教程改编自 Next Tech 的 Python 机器学习 系列的 Part 4 ,带你从 0 到 100 用 Python 进行机器学习和深度学习算法。它包括一个浏览器内沙盒环境,预装了所有必要的软件和库,以及使用公共数据集的项目。这里 可以免费上手 !
多层感知器
多层前馈神经网络是一种特殊类型的具有多个单个神经元的全连接网络。它们也被称为多层感知器 ( MLP )。下图说明了由三层组成的 MLP 的概念:
上图中描绘的 MLP 有一个输入图层、一个隐藏图层和一个输出图层。隐藏层中的单元完全连接到输入层,输出层完全连接到隐藏层。如果这样的网络有不止一个隐含层,我们也称之为深度人工神经网络。
我们可以向 MLP 添加任意数量的隐藏层来创建更深层次的网络架构。实际上,我们可以将神经网络中的层数和单元数视为我们希望针对给定问题任务进行优化的附加超参数。
如上图所示,我们将第 i 层中的第 i 个激活单元表示为 a_i^(l).为了使数学和代码实现更加直观,我们将使用上标中的作为输入层,使用 h 上标作为隐藏层,使用 o 上标作为输出层。
例如, a_i^(in) 是指输入层的第 i 个值, a_i^(h) 是指隐藏层的第 i 个单元, a_i^(out) 是指输出层的第 i 个单元。这里,激活单元 a_0^(in) 和 a_0^(out) 是偏置单元,我们设置为等于 1 。输入层中单元的激活仅仅是其输入加上偏置单元:
层 l 中的每个单元通过一个权重系数连接到层 l + 1 中的所有单元。例如,层 l 中第 k 个单元到层 l + 1 中第 j 个单元的连接将写成 w_{k,j}^(l) 。回头参考前面的图,我们将连接输入到隐藏层的权重矩阵表示为 W^(h) ,将连接隐藏层到输出层的矩阵表示为 W^(out) 。
我们通过矩阵总结了连接输入层和隐藏层的权重:
其中 d 是隐藏单元的数量, m 是包括偏置单元在内的输入单元的数量。因为理解这种符号对于理解本教程后面的概念很重要,所以让我们在一个简化的 3–4–3 多层感知器的描述性图示中总结一下我们刚刚学到的内容:
MNIST 数据集
为了查看通过tensorflow.keras
( tf.keras
)高级 API 进行的神经网络训练是什么样的,让我们实现一个多层感知器来对来自流行的混合国家标准与技术研究所( MNIST )数据集的手写数字进行分类,该数据集用作机器学习算法的流行基准数据集。
为了跟随本教程中的代码片段,您可以使用这个 Next Tech 沙箱,它已经安装了 MNIST 数据集和所有必要的包。否则,您可以使用您的本地环境,在这里下载数据集。
MNIST 数据集分为四个部分,如下所示:
- 训练集图像 :
train-images-idx3-ubyte.gz
— 6 万个样本 - 训练集标签:
train-labels-idx1-ubyte.gz
—60000 个标签 - 测试集图像 :
t10k-images-idx3-ubyte.gz
— 1 万个样本 - 测试集标签:
t10k-labels-idx1-ubyte.gz
—10000 个标签
训练集由来自 250 个不同人的手写数字组成(50%是高中生,50%是人口普查局的员工)。测试集包含来自不同人的手写数字。
注意TensorFlow
也提供了相同的数据集,如下所示:
但是,我们将使用 MNIST 数据集作为外部数据集,分别学习数据预处理的所有步骤。通过这种方式,您可以了解需要如何处理自己的数据集。
第一步是通过在终端中运行以下命令来解压缩 MNIST 数据集的四个部分:
load_mnist
函数返回两个数组,第一个是一个 n x m 维NumPy
数组(images
),其中 n 是样本的数量, m 是特征的数量(这里是像素)。MNIST 数据集中的图像由 28 x 28 像素组成,每个像素由一个灰度强度值表示。这里,我们将 28 x 28 像素展开成一维的行向量,表示我们的images
数组中的行(每行或每幅图像 784)。由load_mnist
函数返回的第二个数组(labels
)包含相应的目标变量,即手写数字的类标签(整数 0-9)。
然后,按如下方式加载和准备数据集:
[Out:]
Rows: 60000, Columns: 784
Rows: 10000, Columns: 784
(60000, 784) (60000,)
(10000, 784) (10000,)
为了了解 MNIST 的这些图像,让我们通过 Matplotlib 的imshow
函数来可视化数字 0-9 的例子:
我们现在应该可以看到一个 2 x 5 子图形的图,显示了每个唯一数字的代表性图像:
现在让我们开始建立我们的模型!
使用 TensorFlow 的 Keras API 构建 MLP
首先,让我们为NumPy
和TensorFlow
设置随机种子,以便获得一致的结果:
为了继续准备训练数据,我们需要将类标签(整数 0–9)转换为独热格式。幸运的是,Keras
为此提供了一个方便的工具:
First 3 labels: [5 0 4]First 3 labels (one-hot):
[[0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0.]
[1\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0\. 0.]
[0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0\. 0.]]
现在,让我们实现我们的神经网络!简而言之,我们将有三层,其中前两层(输入层和隐藏层)各有 50 个带有tanh
激活函数的单元,最后一层(输出层)有 10 层,用于 10 个类别标签,并使用softmax
给出每个类别的概率。Keras
让这些任务变得非常简单:
首先,我们使用Sequential
类初始化一个新模型,以实现一个前馈神经网络。然后,我们可以添加尽可能多的层。然而,由于我们添加的第一层是输入层,我们必须确保input_dim
属性匹配训练集中的特征(列)数量(在神经网络实现中为 784 个特征或像素)。
此外,我们必须确保两个连续层的输出单元(units
)和输入单元(input_dim
)的数量匹配。我们的前两层各有 50 个单元和一个偏置单元。输出图层中单元的数量应等于唯一分类标注的数量-一次性编码分类标注数组中的列数。
注意,我们使用glorot_uniform
to 作为权重矩阵的初始化算法。 Glorot 初始化 是深度神经网络更鲁棒的初始化方式。偏差被初始化为零,这更常见,事实上是Keras
中的默认设置。
在编译我们的模型之前,我们还必须定义一个优化器。我们选择了随机梯度下降优化。此外,我们可以设置权重衰减常数和动量学习的值,以调整每个时期的学习速率。最后,我们将成本(或损失)函数设置为categorical_crossentropy
。
二元交叉熵只是逻辑回归中成本函数的技术术语,分类交叉熵是通过 softmax 对多类预测的推广。
编译完模型后,我们现在可以通过调用fit
方法来训练它。这里,我们使用小批量随机梯度,批量大小为每批 64 个训练样本。我们训练 MLP 超过 50 个历元,我们可以通过设置verbose=1
在训练过程中跟踪代价函数的优化。
validation_split
参数特别方便,因为它将在每个时期后保留 10%的训练数据(这里是 6000 个样本)用于验证,这样我们可以监控模型在训练期间是否过度拟合:
打印成本函数的值在训练期间非常有用,可以快速发现训练期间成本是否在下降,并尽早停止算法。否则,需要调整超参数值。
为了预测类标签,我们可以使用predict_classes
方法直接返回整数形式的类标签:
First 3 predictions: [5 0 4]
最后,让我们在训练集和测试集上打印模型准确性:
Training accuracy: 98.81
Test accuracy: 96.27
我希望你喜欢这篇关于使用TensorFlow
的keras
API 来建立和训练一个用于图像分类的多层神经网络的教程!注意,这只是一个非常简单的神经网络,没有优化的调整参数。
在实践中,你需要知道如何通过调整学习率、动量、重量衰减和隐藏单元的数量来优化模型。您还需要学习如何处理消失梯度问题,即随着网络中图层的增加,误差梯度会变得越来越小。
我们将在 Next Tech 的 Python 机器学习(第四部分) 课程中讨论这些主题,以及:
- 分解
*TensorFlow*
的机制,如张量、激活函数、计算图、变量、占位符 - 低级
*TensorFlow*
和另一个高级 API,*Layers*
- 建模时序数据使用 递归神经网络【RNN】和 长短期记忆【LSTM】网络
- 用深度 卷积神经网络 (CNN)对图像进行分类。
这里 可以免费上手 !
朴素贝叶斯分类器简介
原文:https://towardsdatascience.com/introduction-to-naïve-bayes-classifier-fa59e3e24aaf?source=collection_archive---------5-----------------------
机器学习和深度学习之旅
从理论到实践,学习朴素贝叶斯的基本原理
Source: https://thatware.co/naive-bayes/
本博客将涵盖以下问题和主题:
1.什么是朴素贝叶斯分类器?
2.如何在朴素贝叶斯分类器中计算参数并进行预测?
3.拉普拉斯*滑
4.python 中的应用
- 什么是朴素贝叶斯分类器?
朴素贝叶斯分类器属于概率分类器家族,使用贝叶斯定理。之所以称之为‘幼稚’,是因为它要求输入变量之间刚性的独立性假设。因此,称之为简单贝叶斯或独立贝叶斯更为恰当。自 20 世纪 60 年代以来,该算法得到了广泛的研究。尽管简单,朴素贝叶斯分类器仍然是解决文本分类问题的流行方法之一,即判断文档属于一个类别或另一个类别的问题,如垃圾邮件检测。
朴素贝叶斯分类器的目标是计算条件概率:
对于每个 K 可能的结果或类别 Ck。
设 x=(x1,x2,…,xn) 。利用贝叶斯定理,我们可以得到:
联合概率可以写成:
假设所有特征 x 相互独立,我们可以得到:
因此,公式可以写成:
因此,这是朴素贝叶斯分类器的最终公式。
2。 如何在朴素贝叶斯分类器中计算参数并进行预测?
最大似然估计(MLE)用于估计参数——先验概率和条件概率。
先验概率等于 y 发生的某些情况的数量除以记录总数。
p(x1=a1|y=C1) 的条件概率等于 x1 等于 a1 和 y 等于 C1 的情况数除以 y 等于 C1 的情况数。
朴素贝叶斯分类器使用以下公式进行预测:
例如,下表中的 15 条记录用于训练朴素贝叶斯模型,然后对新记录 X(B,S)进行预测。
使用上面的公式来估计先验概率和条件概率,我们可以得到:
最后,截止到 X(B,S)我们可以得到:
P(Y = 0)P(X1 = B | Y = 0)P(X2 = S | Y = 0)>P(Y = 1)P(X1 = B | Y = 1)P(X2 = S | Y = 1)所以 y=0。
3。拉普拉斯*滑
在统计学中,拉普拉斯*滑是一种*滑分类数据的技术。引入拉普拉斯*滑来解决零概率问题。应用这种方法,先验概率和条件概率可以写成:
K 表示 y 中不同值的个数, A 表示 aj 中不同值的个数。通常公式中的λ等于 1。
通过应用拉普拉斯*滑,先前示例中的先验概率和条件概率可以写成:
4。python 中的应用
步骤 1:创建数据集。
步骤 2:通过计算先验和条件概率来训练朴素贝叶斯模型。
第三步:做一个预测。
概要:
朴素贝叶斯分类器易于快速训练,可作为基准模型。当变量选择适当时,朴素贝叶斯可以表现得和其他统计模型一样好,甚至更好,如逻辑回归和 SVM。朴素贝叶斯需要对独立预测器的强假设,因此当模型表现不佳时,导致这种情况的原因可能是预测器之间的相关性。
你可以点击以下链接阅读更多博客:
[## 机器学习和深度学习之旅
这一系列博客将从理论和实现两个方面对深度学习进行介绍。
medium.com](https://medium.com/@songyangdetang_41589/table-of-contents-689c8af0c731)
参考:
[1] Christopher M. Bishop,(2009),模式识别和机器学习
https://en.wikipedia.org/wiki/Naive_Bayes_classifier
https://en.wikipedia.org/wiki/Additive_smoothing
面向 Noobs 的自然语言处理介绍
原文:https://towardsdatascience.com/introduction-to-natural-language-processing-for-noobs-8f47d0a27fcc?source=collection_archive---------14-----------------------
Photo by fabio on Unsplash
使用 Kaggle 竞争的 NLP 及其基本流水线概述
这篇文章是我试图给出一个可能对新手有帮助的基本概念的概述。为了更好地理解,我将关注一个完整的 Kaggle 竞赛 Quora 虚假问题分类。在这里,我们提供了 131 万个带标签的问题和 37.6 万个问题,我们必须预测这些问题的标签。这个竞赛是一个二元分类问题的例子。我已经包含了可以用来解决这个问题的 python 代码示例。代码使用了 Keras 库,非常容易理解。这场竞赛的基线解决方案是在 Kaggle 内核上。
所以先从基础开始吧。
介绍
NLP 是计算机科学的一个分支,它用自然语言处理人和机器之间的交互。它是语言学和计算机科学的交叉,因此它使机器能够理解并以自然语言回复人类的查询。自然语言处理的主要问题是人类语言是不明确的。人类非常聪明,能够理解上下文和单词的意思,但对计算机来说,这个问题完全是另一个层面,因为计算机既不理解概念也不理解上下文。为了让计算机理解概念,它们需要对世界、语言句法和语义有一个基本的理解。
文本表示
我们可以理解和阅读一段文本,但对计算机来说,每段文本都是一系列数字,不代表任何概念。一个简单的例子,字母“A”在英语中有特殊的含义,它被认为是所有字母表中的第一个字母。但是计算机认为它是 65(因为 65 是字母“A”的 ASCII 码)。ASCII 是基于英文字符的传统编码系统。这些字符的集合在 NLP 中通常被称为标记。
一个标记是某个特定文本中的一个字符序列的实例,这些字符被组合在一起以在自然语言中产生某种意义。
在 NLP 管道中表示任何文本的最简单方法是通过一键编码的向量表示法。如果一个句子包含某个单词,那么向量中相应的条目表示为“1”,否则为“0”。例如,让我们考虑下面两句话:
- “自然语言处理是最好的领域”
- “我是自然语言处理的新手”
Table 1. One hot encoding of all words in sentence 1 and 2
Table 2. Collapsed One hot encoded vector for sentence 1 and 2
一种流行的编码是将分类变量表示为二进制向量。一种单词的热编码用于对文本进行编码,其中除了当前单词之外,每个单词都用零表示。如果我们有一千个唯一单词的语料库,那么每个单词表示将需要大小为 1000 的向量。尽管大小依赖于词汇,但即使在今天,一键编码表示仍在产品中使用。
表 1 显示了句子 1 和 2 中所有单词的一次性编码。表 2 所示的表示称为折叠或“二进制”表示。
现代 NLP 系统有一个单词字典,其中每个单词都有一个整数表示。所以那句“自然语言处理是最好的领域!”可以表示为“2 13 6 34 12 22 90”(忽略标点符号,将每个单词都视为小写)。这种表示在内存使用方面更有效,并且还保留了语言语义。
基本 NLP 流水线
Figure 1: Basic NLP pipeline
NLP 中有很多任务可以使用上面显示的管道。大多数 Kaggle 比赛都清理了数据,这在现实生活中不会发生,因为这些数据集是由比赛协调员收集和预处理的。在现实世界的场景中,我们必须总是假设数据需要一些预处理。预处理之后,我们需要将文本分解成记号和句子。在分解文本之后,我们使用预先训练的嵌入来初始化我们的模型。
为了这篇文章的简单,我从我们的管道中跳过了文本分析。文本分析是任何 NLP 管道中非常重要的一部分。根据分析的见解,可以修改管道流程以提高应用程序的性能。
文本预处理
文本数据可能非常混乱。所以大多数时候我们需要对文本进行预处理。预处理可以包括去除最常见的拼写错误、替换文本中的数字、替换俚语词、消除常见的语法错误、匿名化数据、去除停用词等。
代码示例:
Code sample 1: Replacing empty records
Code sample 2: Declaring function to clear text
Code sample 3: Cleaning question text
在上面的代码样本中 train_df、 test_df 是熊猫 dataframe。首先,我们使用fillna()函数删除数据集中的空记录。然后我们声明 clean_text 函数来分离令牌。在代码示例 3 中,我们通过使用 pandas dataframe 的 apply() 函数,调用 clean_text 函数将其应用于我们的训练和测试数据集。
文本规范化
文本规范化是将文本转换成单一规范形式的过程。
有许多文本规范化技术,如标记化、词条化、词干化、句子分割、拼写纠正等。其中,标记化是最常用的文本规范化方法。
标记化是将一段文本转换成在自然语言中有意义的一系列单词或特殊字符的过程。
例如文本“NLP 是最好的!”可以转换成列表“NLP”、“is”、“the”、“best”和“!”(注意特殊字符"!"与“最佳”分开,因为它在英语中有特殊的含义)。像中文这样的一些语言没有用空格分隔的单词,所以这些语言的标记化就更加困难。
词汇化是确定两个单词是否有相同词根的任务。例如,单词“got”和“gone”是动词“go”的形式。词干化类似于词汇化,但它只是从单词的末尾剥离。使用词汇化或词干化意味着从数据中丢弃一些信息。拼写校正可以在你的自然语言处理系统中使用,以消除输入错误,提高自然语言处理系统的性能。然而,NLP 系统被假定为对由于未知令牌引起的输入的小变化是鲁棒的。
代码示例:
Code sample 4: Declaring and fitting tokenizer on training data
Code sample 5: Using trained tokenizer to tokenize all questions
在上面的代码示例中,我们通过使用一个标记器对象的 fit_on_texts() 函数来训练一个标记器。该对象可用于将文本转换为输入数据的整数表示形式。之后,我们可以通过使用 Keras 包中的 pad_sequences() 函数来限制输入序列的大小。
单词嵌入
单词嵌入是文档词汇在向量空间中的表示。嵌入向量的大小范围从 50 到 600,可以捕获语法和语义信息。如果有足够的计算资源可用,那么甚至可以使用更大的向量大小。单词嵌入的性能可能因为所使用的不同算法或嵌入向量的大小而不同。但是在某些时候,增加嵌入大小并不能提高性能。
语言模型可以代替自然语言处理系统中的单词嵌入。LM 不同于单词嵌入,因为它们可以在语料库上被训练和微调。单词嵌入被视为单个层,不能进一步调整。统计语言模型是单词序列的概率分布。一个这样的例子是 N-gram 模型。N-gram 模型计算单词“w”出现在单词“h”之后的概率。
代码示例:
Code sample 6: Reading embedding file format
为了在代码中使用单词嵌入,我们读取并处理嵌入文件。在每一行中,嵌入文件包含一个单词及其嵌入向量。在代码示例 6 中,我们拆分了这一行,并创建了一个字典来存储每个单词的嵌入向量。
Code sample 7: Extracting embedding vectors and calculating mean and standard deviation
Code sample 8: Recreating embedding matrics
在读取嵌入文件后,我们可以创建一个使用单词和嵌入矩阵的列表。注意,代码示例 8 使用标记器*对象来访问词汇单词。这里,我们使用正态分布重新创建嵌入矩阵。这有助于初始化字典 embeddings_index 中不存在的单词向量。*
* [## 单词嵌入和 Word2Vec 简介
单词嵌入是最流行的文档词汇表示之一。它能够捕捉…的上下文
towardsdatascience.com](/introduction-to-word-embedding-and-word2vec-652d0c2060fa)
要详细了解单词嵌入和 word2vec,请阅读上面的文章。*
建筑模型
机器学习管道中的模型是一系列数学运算,可以学习估计未知数据的输出。选择您的型号非常重要,因为它可以决定您系统的性能。
新手的话可以从非常基础的机型入手。但是您应该至少用几个模型进行试验,看看哪个参数设置能得到最好的结果。一旦你有了六个或更多运行良好的模型,你就可以把它们整合成一个巨大的模型。
最初,您可以选择使用双 LSTM 或 GRU 层和*均池层进行测试。实验之后,您可以通过使模型更深入或使用更先进的模型来对模型进行更改。为了跟踪 NLP 的进展,你可以访问这个站点,看看哪个模型在特定的任务中表现得更好。
下图给出了我们为第一个测试选择的模型的概念表示。
Figure 2: Conceptual representation of our model
在上图中,您可以看到我们模型的概念性布局。模型中的层代表特定的数学运算。一个模型至少可以有两层,输入层和输出层。Keras 中的输入层用于实例化一个张量。模型中的输出层是具有多个节点的神经网络。
模型中的嵌入层对输入序列和嵌入矩阵进行点积,将每个词索引转换成对应的嵌入向量。
丢弃层以给定的百分比随机丢弃输入。这一层将输入单位转换为零。这个过程有助于防止过度拟合。
门控递归单元是一种不存在消失梯度问题的递归层。双向 GRU 的输出是前向和后向 GRU 的组合
汇集操作通过执行数学*均、最大值等来减小输入序列的大小。因此,*均池层执行*均池,同时最大池层执行最大池。级联层组合不同的输入序列。
密集层是一个简单的神经网络,具有固定的节点数和指定的激活函数。
为了完全理解递归神经网络和 GRU 网络的工作原理,你可以阅读下面的文章。
* [## 递归神经网络图解指南
理解直觉
towardsdatascience.com](/illustrated-guide-to-recurrent-neural-networks-79e5eb8049c9) [## 了解 GRU 网络
在这篇文章中,我将试图给出一个相当简单和易懂的解释,一个真正迷人的类型…
towardsdatascience.com](/understanding-gru-networks-2ef37df6c9be)
代码示例:
Code sample 9: Model definition code
在代码示例 9 中,输入层接受大小等于 ques_len 的输入。嵌入层以嵌入矩阵及其维数为参数。嵌入层的输出大小为ques _ lenxembedding _ matrix . shape[1]。空间丢弃层随机丢弃嵌入层的输出,分数为 0.2。
接下来的两层是双向 GRU,这是一种递归神经网络。全局*均池 1D 和全局最大池 1D 从第二双向 GRU 层的输出中提取*均和最大特征。输出 avg_pool、和 max_pool 被连接以馈入密集层。最后一层是输出层,给出一个介于 0 和 1 之间的数字。
初始化模型
迁移学习是通过从已经学习过的相关任务中迁移知识来提高在新任务中的学习。
在这一阶段,我们试图在我们的自然语言处理系统中利用以前的知识。使用在不同设置中训练的独立模型可以提高我们的模型的性能。这个过程被称为知识转移。在 NLP 系统中初始化神经网络的最流行的方法是单词嵌入。
NLP 的最新发展清楚地表明迁移学习是前进的方向。使用预先训练的 LMs,新的最先进的模型变得越来越好。LMs 是在一个巨大的数据集上预先训练的,它们也基于 Transformer 架构。
如果你想了解更多关于变压器模型的信息,请阅读下面的文章。
[## 你需要的只是关注
主导序列转导模型是基于复杂的递归或卷积神经网络在一个…
arxiv.org](https://arxiv.org/abs/1706.03762)
在编码样本 9 中,我们使用嵌入 _ 层初始化我们的模型,它被初始化为嵌入 _ 矩阵的权重。
培训模式
在您决定第一次使用哪个模型后,您可以训练您的模型。您应该总是在十分之一的训练数据集上开始测试您的模型,因为这会使测试更快。有些问题是,不同的预处理方法可能会产生不同的性能。
Code sample 10: Training our model using model.fit() method
在代码示例 10 中,我们添加了每次保存模型的功能,如果它的验证准确性增加的话。最后,我们调用函数 fit(),来使用 train_X,train_y (我们的特征和标签)和一系列其他参数训练模型。如果我们想以更快的速度进行训练,我们可以随时增加批量。历元的数量表示相同的训练数据将被输入模型的次数。
测试和评估模型
在训练模型之后,我们必须测试我们的模型的准确性,并评估它在看不见的数据上的表现。为此,我们预测结果并与实际标签进行比较。如果模型的性能不符合我们的预期,我们需要在我们的管道中做出改变。在 Kaggle 比赛中,排行榜分数是评估我们模型的一个很好的方式。*
自然语言处理(NLP)简介
原文:https://towardsdatascience.com/introduction-to-natural-language-processing-nlp-323cc007df3d?source=collection_archive---------6-----------------------
你有没有想过你的私人助理(比如 Siri)是怎么打造的?你想自己做吗?超级!先说自然语言处理。
Source: http://www.contrib.andrew.cmu.edu/~dyafei/NLP.html
那么,什么是自然语言处理(NLP)?
NLP 是一个跨学科领域,涉及计算机和自然人类语言(例如英语)——语音或文本之间的交互。NLP 支持的软件在日常生活中以各种方式帮助我们,例如:
- 个人助理 : Siri、Cortana、谷歌助理。
- 自动完成:在搜索引擎中(例如谷歌)。
- 拼写检查:几乎无处不在,在你的浏览器,你的 IDE ( 如 Visual Studio),桌面应用(如微软 Word)。
- 机器翻译:谷歌翻译。
好了,现在我们明白了,NLP 在我们日常的计算机交互中扮演着重要的角色;让我们来看一些 NLP 的业务相关用例示例:
- 快餐连锁店每天都会收到大量的订单和投诉;手动处理这将是令人厌倦的和重复的,并且在时间、劳动和成本方面效率低下。由于最*在对话式人工智能方面的进步,他们可以建立虚拟助手来自动化这些过程并减少人工干预。
- 品牌推出新产品,并在社交媒体*台上营销;他们可以使用覆盖范围和互动次数等指标来衡量活动的成功率。然而,他们不能自动理解消费者的公众情绪。这项任务可以使用 情感分析 来自动化,这是一项文本分类任务,其中机器学习模型被训练来量化情感状态和主观信息。
Source: https://clevertap.com/blog/natural-language-processing
NLP 主要分为两个领域:语言学和计算机科学。
语言学方侧重于理解语言的结构,包括以下子领域[ Bender,2013 ]:
- 语音学 :研究人类语言的声音。
- 音系学 :研究人类语言中的声音系统。
- :研究词的构成和内部结构。
- 句法 :研究句子的构成和内部结构。
- 语义学 :对句子意义的研究。
- :研究句子及其语义用于特定交际目的的方法。
****计算机科学方面是在子领域如人工智能的帮助下,将语言知识和领域专长转化为计算机程序。
让我们谈谈科学
NLP 的科学进步可以分为基于规则的系统、经典的机器学习模型和最*的深度学习模型。
- 基于规则的系统**在很大程度上依赖于制作特定领域的规则(例如正则表达式)。它可以自动执行简单的任务,例如从非结构化数据(例如网页、电子邮件)中提取结构化数据(例如日期、姓名)。然而,由于人类语言的复杂性,基于规则的系统不够健壮,难以维护,并且不能跨不同领域通用。**
- 经典的机器学习方法可以解决更具挑战性的问题(例如垃圾邮件检测)。使用特征工程(例如单词包、词性标签)来构建机器学习模型(例如朴素贝叶斯)。这些模型利用训练数据中的系统模式,可以对看不见的数据进行预测。
- 深度学习模型是目前 NLP 研究和应用中最流行的。它们甚至比经典的机器学习方法更能概括。它不需要手工制作的特征或特征工程,因为它们自动作为特征提取器工作,实现端到端的模型训练。深度学习模型的学习能力比浅层/经典的 ML 模型更强大,这为在各种具有挑战性的 NLP 任务中获得最高分数铺*了道路(例如机器翻译)。
计算机如何理解文本?
计算机理解数字,但不能理解字符、单词、或句子,所以在建立 NLP 模型之前需要一个中间步骤,就是文本表示。我将把重点放在单词级的表达上,因为它们很容易理解。使用其他表示技术,例如字符或子词。
在经典的 NLP/ML 时代(深度学习之前),文本表示技术主要建立在一个基本思想上: one-hot encodings ,其中一个句子由一个形状矩阵( N x N )表示,其中 N 是句子中唯一记号的数量。例如,在上图中,句子(猫坐在垫子上)被表示为一组稀疏向量(大部分为零)。这种方法有两个的显著缺点:**
- 巨大的存储容量问题,因为稀疏表示矩阵。
- 缺乏语义理解**。它不能理解单词之间的关系(如学校和书)。
2013 年,来自谷歌的研究人员推出了一种新的文本表示模型,这在 NLP 中是革命性的,命名为word 2 vec[miko lov 等人,2013 。这种浅层深度学习模型可以在密集向量中表示单词,并捕捉相关术语之间的语义(例如巴黎和法国、马德里和西班牙)。进一步的研究建立在 word2vec 之上,如GloVePennington 等人,2014和fast textBojanowski 等人,2016 。****
2018 年末,来自谷歌的研究人员再次提出了另一个模型( BERT ),它被认为是当今最先进的 NLP 研究的基础[ Devlin 等人,2019 ],完全基于 Transformer 架构[ Vaswani 等人,2017 ]。
任务和研究
让我们看看一些 NLP 任务,并根据对英语语言的研究进展对它们进行分类(阅读: #BenderRule )。
1.大部分已解决:
- 文本分类(例如 Gmail 中的垃圾邮件检测)。**
- 词性(词性)标注:给定一个句子,确定每个单词的词性标注(如名词、动词、ADV、ADJ)。**
- 命名实体识别( NER ):给定一个句子,确定命名实体(例如人名、地点、组织)。**
2.稳步前进:
- 情感分析:给定一个句子,确定它的极性(如积极、消极、中性),或情绪(如高兴、悲伤、惊讶、愤怒等)****
- 共指解析:给定一个句子,确定哪些词(“提及”)指的是相同的对象(“实体”)。例如(曼宁是一位伟大的 NLP 教授,他在这个领域工作了二十多年)。
- 词义消歧( WSD ):很多词有不止一个意思;我们必须根据上下文选择最有意义的意思(例如我去银行取些钱,这里的银行是指金融机构,而不是河边的土地。**
- 机器翻译。
3.仍然具有挑战性:
- 对话代理和聊天机器人,尤其是开放域的。
- 问题回答。
- 抽象概括。
- 低资源语言的 NLP(如非洲语言,参见马萨坎和∀等人,2020 )。
NLP 实时演示
- 空间命名实体识别
- 空间语义相似度
- AllenNLP 情绪分析
- AllenNLP 文本到 SQL
- 用变压器拥抱脸写字
- 拥抱脸多任务模型
- 斯坦福 CoreNLP 情绪分析
在线综合学习计划
1。基础:
- 学习用 Python 编程( Udacity 课程)。
- 数学基础(线性代数,概率,统计),可汗学院曲目就足够了。我在这篇文章中更详细地讨论了如何为机器学习学习数学。
2。机器/深度学习:
- 经典机器学习(吴恩达在 Coursera 上的课,用 Python 解决的作业)。
- 深度学习(吴恩达在 Coursera 上的专业化)。
3。自然语言处理:
- 经典的 NLP,虽然现在使用的不是很广泛,但是它涵盖了一些基本的概念和永恒的技术( Jurafsky 和 Manning class)。
- 斯坦福 CS224N:具有深度学习的 NLP。
- CMU CS11–747:自然语言处理的神经网络。
- CMU 低资源 NLP 训练营。
4。语言学:
- Emily Bender 的语言学书籍(上册:词法和句法,下册:语义和语用)。
- YouTube 上的语言学速成班。
- 莱顿大学:人类语言的奇迹:语言学导论,Coursera 的在线课程。
5.杂项主题:
- NLP 中 伦理的资源集合。
- 能源消耗和环境问题:NLP 中深度学习的能源和政策考虑, Sturbell 等,2019 。**
- 关于随机鹦鹉的危险:语言模型会不会太大? 🦜 , 本德,格布鲁等人,2021 。
- 大规模预训练模型会解决语言吗? NLP 的聪明汉斯时刻已经到来 。
更喜欢书吗?
- 丹·茹拉夫斯基和詹姆斯·h·马丁,语音和语言处理。
- 雅各布·爱森斯坦的自然语言处理。
- Yoav Goldberg 的教程,自然语言处理的神经网络模型入门。
- 伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔,深度学习。
让我们破解一些代码!
现在我们已经讨论了什么是 NLP,以及它背后的科学,让我们进入实用部分。这里列出了在您的下一个项目中使用的最广泛的开源库(排名不分先后):**
- 空间
- 变形金刚
- Gensim
- AllenNLP
- NLTK
- 第三节
我希望这篇文章能让你对这个激动人心的领域有一个大致的了解。如果您有任何建议或问题,请在回复中留言或联系我[Ibrahim sharaf . github . io]。
自然语言处理和人工智能中的偏见介绍
原文:https://towardsdatascience.com/introduction-to-natural-language-processing-nlp-and-bias-in-ai-877d3f3ee680?source=collection_archive---------13-----------------------
人工智能中处理自然数据和消除偏差的实用指南
Photo by Bewakoof.com Official on Unsplash
自然语言处理(NLP)是一个正在被深度学习革命的领域。从语音助手到 Gmail 的 Smart Compose,深度学习已经使机器能够以更直观的方式理解我们。
当然,处理自然数据与处理表格数据有很大不同,因为我们现在需要用机器可以理解的方式来表示单词和句子。
在这篇文章中,我将介绍 NLP 的关键概念,如单词嵌入,我们将看到算法如何变得有偏差,以及我们如何消除这种偏差。
我们开始吧!
关于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
So much talking!
如何表示文字?
通常,当使用 NLP 应用程序时,我们会访问包含数千个不同单词的词典。现在,我们需要用神经网络可以理解的方式来表达每个单词。
一键向量
使用一键编码是在字典中表示单词的一种常见方式。例如,如果您有一个 10 000 个单词的字典,并且“King”是第 4914 个单词,那么它的独热向量表示将是填充有 0 的 10000×1 向量,但是在位置 4914 是 1。
One-hot vector representations of possible words in a dictionary. Source
这种表示法的缺点是它将每个单词单独作为一个独特的元素。这意味着它不会识别苹果和桔子都是水果,或者国王和王后是相关的单词。因此,它不允许算法容易地概括单词的意思。
为什么?
假设你有线性代数的基础知识,你意识到上面给出的任意两个向量之间的点积都将是 0!因此,算法没有办法理解某些词是相关的。
单词嵌入
将单词表示为特征的集合,而不是一个热点向量,会很有用。例如,可以有“性别”特征、“食物”特征、“年龄”特征等。
这形成了单词嵌入的基础。这允许建立矩阵,该矩阵展示不同的单词,每个特征有相应的分数。
Example of word embedding
这样,每个单词现在都是一个向量,其中每个值都是某个特征的分数。
从上图来看,我们来考虑一下“君主”和“国王”。它们各自的向量是[0.5,0.5,1]和[0,0,1]。现在,我们知道这些词是相关的,两个向量之间的点积不再是 0!于是,算法现在可以理解“君主”和“国王”是有关系的,就像“君主”和“人”没有关系一样。
我们可以使用 t-SNE 进一步简化这种表示,并将维度空间减少到 2D。
Example of reducing the dimension space with t-SNE. Source
正如您所看到的,相似的单词被分组在一起,这显示了使用单词嵌入的优势。
使用自然语言处理进行词语类比
现在,让我们将 NLP 应用于单词类比。在继续之前,如果你想继续编码,你可以找到完整的笔记本。
单词类比任务看起来像:
男人对女人就像国王对 _____(女王)
为了完成这样的任务,算法必须有办法理解两个单词是相似的。
一种简单的方法是应用余弦相似性。这度量了两个嵌入向量之间的相似程度。数学上,余弦相似性表示为:
Cosine similarity equation
根据上面的等式,如果两个向量非常相似,值将接* 1。否则,它将呈现较小的值。然而,如果向量相似但方向相反,则值将更接*-1。
Cosine similarity between different words. Source
在 Python 中实现余弦相似性:
现在,我们可以用它来计算不同单词之间的余弦相似度:
上面的单元格输出以下内容:
如你所见,父亲和母亲是关联词,而球和鳄鱼不是。同样,巴黎和罗马相似,但相反,所以余弦相似度给出一个接*-1 的负数。
太好了!有余弦相似度工作,如何应用于单词类比?
如前所述,单词类比包括根据两个其他单词的关系找到与另一个单词相关的单词。例如:
男人对女人就像国王对王后一样
从数学上来说,这意味着每对字向量之间的差大致相等。所以每个差的余弦相似度也要相等。
将每个单词向量定义为 e ,下面的等式描述了单词类比的逻辑:
The math of word analogy
将此写入代码:
现在,我们可以运行下面的代码单元格,我们得到:
厉害!看来算法只用余弦相似度就能有效理解基本的单词类比!
花些时间去体会这种方法是如何简单、直观、高效地表示单词和理解它们的意思。
消除偏见
我们有一个算法可以进行单词类比。然而,事实证明,我们的单词表征是有偏差的。
查看性别向量的一种方法是,我们可以从女人向量中减去男人向量:
我们得到了:
这就是性别的编码方式。现在,让我们通过输出不同姓名之间的余弦相似度和性别向量来进一步探究性别偏见:
如您所见,女性名字的余弦相似度为正,男性名字的余弦相似度为负。
现在,让我们运行相同的操作,但是使用其他随机单词:
可以看到,工程师和技术更接*男人,而前台和文学更接*女人。
很明显,我们的算法有偏差,我们需要修正它。
为此,我们需要识别偏差分量,并将其从单词向量中移除。偏置分量只是单词向量在偏置向量上的投影:
Bias component equation, where g is the gender vector. Source
然后,我们简单地从单词向量中减去它,以获得无偏的单词表示:
代表 2D *面中的矢量,这是消除偏差前后的样子:
Word vectors before and after removing bias. Source
对上述逻辑进行编码,我们首先定义一个消除性别偏见的函数:
现在,我们可以使单词对相等:
让我们看看我们是否成功地消除了偏见:
我们得到了:
太神奇了!我们确实在我们的文字表述中消除了任何性别偏见!
在这篇文章中,您了解了自然语言处理中单词是如何表示的,您了解了如何构建一个可以执行单词类比的简单算法,您了解了如何消除算法中的性别偏见。
人工智能算法中的偏见有时可能是一个大问题,社区越来越意识到这一点。当你开发一个算法的时候要小心,确保它尽可能的中立。
干杯!
神经网络导论
原文:https://towardsdatascience.com/introduction-to-neural-networks-1d81f471a803?source=collection_archive---------19-----------------------
什么是神经网络?
引用人类所有知识的宝库“人工神经网络[……]是受构成动物大脑的生物神经网络启发的计算系统。”
生物神经元和人工神经网络中的“神经元”都从其他神经元接收信号,并相应地产生一些输出。这两种神经网络的力量都不是来自单个神经元单独行动,而是来自许多神经元一起的累积效应。但相似之处仅限于此。生物神经元包含非常复杂的分子机制,而人工神经网络神经元包含一些简单的数学运算。
人工神经网络已经成功地应用于图像、音频、文本和医学数据。这篇文章将向你介绍人工神经网络是如何计算的。
概述
假设您想要建立一个模型,根据患者的医疗记录来预测其住院风险。您可以为医疗记录的不同组成部分分配数值以构建风险模型,例如,您可以将糖尿病诊断的权重设为“2”,将流感诊断的权重设为“1.5”,将第 4 阶段肺癌诊断的权重设为“10”,以获得以下“模型方程”:
2 *糖尿病+1.5 *流感+10 *癌症=风险。
例如,Fred 患有糖尿病和流感,但没有癌症,因此他的风险是(21) + (1.51)+ (10*0) = 3.5。
但是,您如何知道每个诊断应该具有什么样的权重(即,在这个等式中使用什么系数)?糖尿病实际上应该有 2 的权重吗?可能权重应该是 1.63,或者 6,或者 0.0001。
这就是机器学习方法可以发挥作用的地方。在受监督的机器学习中,您提供一个具有输入/输出对的模型(例如,输入= Fred 的病史,输出= Fred 是否去过医院),该模型学习将输入的每一部分分配什么权重,以便最好地预测所需的输出。换句话说,该模型计算出每个输入部分(不同的诊断)对于预测输出(未来住院)有多重要或不重要。
神经网络有很多种。最简单的神经网络是前馈神经网络,这意味着信息只通过神经元向前流动。在这篇文章的剩余部分,我将描述前馈神经网络的监督学习。
数据
如果您想要预测患者入院的风险,您可以从该患者的病历中提取诊断、程序、药物和实验室值(输入“X”),然后检查该患者后来是否入院(输出“y”,正确答案)。你想用“X”来预测“y”,也就是用他们的病历来预测他们会不会去医院。你还需要许多训练样本,也就是说,你需要成千上万的样本病人,而不仅仅是一个。
前馈神经网络的剖析
这个神经网络有三层:输入层、隐藏层和输出层。输入和输出之间的一切都被称为“隐藏层”如果你愿意,你可以建立一个有数百个隐藏层的神经网络。
输入层只接受输入数据的一个例子:例如,一个病人的病历。在这里,从上到下的原始输入值以红色显示为 0.5、2.8、0 和-0.1,对应于我标记为 A、B、C 和 d 的输入神经元。这些输入值有一个含义。根据您正在解决的问题和使用的数据,其含义是不同的。或许在这里,输入 A、B 和 C 是特定的实验室值,而 D 是过去一年中体重变化的百分比(例如-0.1 表示患者在过去一年中体重减轻了 10%)。)
输入可以是任何正数或负数。通常,原始值被“归一化”以将值压缩为小值,因为如果一些输入是巨大的(例如 183 cm 的身高)而一些输入是微小的(例如 0.6 mg/dL 肌酸酐),则神经网络具有更难的学习时间。)
隐藏层可以被认为是在神经网络的计算中捕捉一些中间值。如果你听到人们谈论输入数据的“隐藏表示”(或“潜在空间”),他们通常指的是神经网络的隐藏层。在这幅图中,“潜在空间”是三维的,因为有 3 个隐藏的神经元:E、F 和 g。如果你制作了一个有 300 个隐藏神经元的神经网络,你可以说有一个“300 维潜在空间”关键是隐藏层捕获一些介于输入和输出之间的中间数字表示。
输出层输出最终答案。这里只显示了一个输出神经元。也许这个输出节点产生了一个入院概率。如果你想同时预测许多不同的事情,你也可以有多个输出节点。例如,您可能有两个输出节点:一个预测住院风险,另一个预测死亡率。
权重:连接神经元的蓝线就是神经网络的权重。它们代表乘法运算。我用红色写下了第一批重量的值。请注意,该图中没有写出通向输出层的权重的示例值。将节点 A 连接到节点 E 的权重值“3”表示您获取节点 A 中的当前值,将其乘以 3,并将结果用作节点 E 的值的分量。
偏差:标有“偏差”的绿线是神经网络的偏差。它们代表加法运算。应用于节点的偏移值“6”意味着您获取该节点的值,并向其添加“6”。
权重和偏差最重要的区别是,权重表示乘法,偏差表示加法。
“机器学习”的“学习”部分指的是用于计算出权重和偏差的良好设置的算法。权重和偏差是“可训练参数”,因为我们使用神经网络训练过程来计算权重和偏差的良好值。
网络结构从何而来?
当你在设计一个神经网络时,你选择它的结构。
您可以根据数据的大小选择输入图层的大小。如果您的数据每个示例包含 100 条信息,那么您的输入层将有 100 个节点。如果您的数据每个示例包含 56,123 条数据,则您的输入层将有 56,123 个节点。
您还可以选择隐藏层的数量,以及每个隐藏层中的节点数量。通常,一个好的经验法则是,输入层中的节点数和隐藏层中的节点数之间不应有太大差异。例如,您不希望输入大小为 300,000,隐藏层大小为 2,因为这将导致丢弃大量信息。一些神经网络有数百个隐藏层,但使用只有 1 或 2 个隐藏层的神经网络来解决许多有趣的问题是可能的。
您可以根据想要预测的内容选择输出图层的大小。如果您想要预测糖尿病的风险,您将有 1 个输出节点。如果您想要预测 10 种疾病的风险,您将有 10 个输出节点。
训练网络
训练神经网络包括查看数据集中的所有训练示例,以学习权重和偏差的良好值。培训可以分为几个具体步骤:
(1)初始化:为模型中的每个权重和偏差选择随机数。在这一点上,模型什么都不知道。
(注意:在实践中,权重的随机初始化不是完全随机的。您不会将一个权重初始化为 99,003,而将另一个权重初始化为 0.000004。以有原则的方式设置随机初始化对成功的神经网络训练很有帮助。一种流行的权重初始化方法称为“Glorot”或“Xavier”初始化。每个权重被设置为一个小的随机数,例如在-0.01 和+0.01 之间。这个数字是从基于神经网络结构的具有零均值和方差的正态分布中提取的。)
(2)正向传递:给神经网络一个训练示例:例如,输入“X”可以是来自单个患者病历的数据,对应的正确答案“y”可以是该单个患者后来是否入院。对于这个训练示例,神经网络将使用随机初始化的权重来计算它自己的答案。神经网络的答案很可能不会与正确答案“y”匹配,因为神经网络还没有学到任何东西。
(2)反向传递:在你刚刚给出的例子上,量化你的网络有多错误。这就涉及到一个“损失函数”——比如【输出答案——正确答案】2(这是一个*方误差损失)。如果您的网络计算出“0.4”作为其输出答案,但正确答案是 1(即患者入院),那么损失将是[0.4–1]2 = 0.36。
一旦你知道了损失,你就可以计算神经网络所有权重的导数,告诉你如何调整权重,这样神经网络下次就不会出错。回想一下微积分,导数可以被认为是测量曲线上特定位置的斜率。这里我们关心的斜率是损失函数的斜率,因为损失函数告诉我们我们有多错。我们想知道如何“下坡”——也就是说,如何“下坡”以使我们的损失函数更小。计算导数(斜率)告诉我们如何将每个权重推向正确的方向,以使神经网络在未来减少错误。
注意:(a)如果你正在使用 Tensorflow 这样的流行机器学习框架,你实际上并没有自己计算任何导数——导数的计算已经内置在软件中。(b)在大多数其他关于反向传播的在线资源中,导数通常被称为“梯度”“梯度”只是一个多变量的导数。
该方法被称为“反向传播”,因为你正在通过你的整个神经网络“反向传播错误”,以找出如何使神经网络变得更好。在下一次向前传递/向后传递之前,每个权重和偏差将被稍微修改。
(3)重复向前传球和向后传球进行数千次训练示例。对于每个训练示例,神经网络的权重都会变得更好一点。最终,有了足够多的训练样本,神经网络变得非常擅长使用输入来预测输出,你就有了一个有用的模型!
详细例子:向前传球
这是一个向前传递的详细示例,其中神经网络使用一些输入数据来计算答案。
上图显示了导致隐藏节点 E 的所有权重,以金色突出显示。权重的当前值从上到下是 3、1、5 和-4。在右下角,您可以看到输入到节点 E 的值是如何计算的。您将输入值 0.5(对应于输入节点 A)乘以链接输入节点 A 和隐藏节点 E 的权重,在本例中值为 3。将输入值 2.8(对应于输入节点 B)乘以链接输入节点 B 和隐藏节点 E 的权重。对所有输入节点执行此操作,并将结果相加:(0.5 来自节点 A)(3 来自 A-E 权重)+ (2.8 来自节点 B)(1 来自 B-E 权重)+ (0 来自节点 C)(5 来自 C-E 权重)+ (-0.1 来自节点 D)(-4 来自 D-E 权重)= 4.7。
“偏向”的绿线呢?回想一下,偏见意味着加法。分配给该层的偏移值为-2。这意味着我们从刚刚计算的值中减去 2:4.7–2 = 2.7。因此,值 2.7 是我们提供给隐藏节点 e 的最终值
在上图中,导致隐藏节点 F 的权重都用金色突出显示。这些权重的值从上到下依次是-1.5,-3,7.1,5.2。我们执行与之前相同的计算:(a)将输入值(红色)乘以相应的权重值(金色);(b)将这些相加;添加偏差项(绿色)。
在上图中,我们看到了导致隐藏节点 G 的权重以金色突出显示,以及提供给节点 G 的值的计算。
非线性
到目前为止,我们只做过乘法和加法运算。然而,仅使用乘法和加法会限制我们从输入到输出的转换种类。我们假设输入和输出之间的关系是线性的。在对真实世界建模时,拥有更大的灵活性是件好事,因为输入和输出之间的真实关系可能是非线性的。我们如何让神经网络代表一个非线性函数?
我们加入“非线性”:每个神经元对它接收的值应用一个非线性函数。一个流行的选择是 sigmoid 函数。因此,在这里,节点 E 将对 2.7 应用 sigmoid 函数,节点 F 将对-11.67 应用 sigmoid 函数,节点 G 将对 1.51 应用 sigmoid 函数。
这是 sigmoid 函数:
关键点:
(sigmoid 函数不是线性的,这有助于神经网络学习输入和输出之间更复杂的关系
(sigmoid 函数将其输入值压缩到 0 和 1 之间。
将神经网络表示为矩阵
如果你在网上阅读有关神经网络的内容,你可能会看到“Wx+b”形式的矩阵方程,用来描述神经网络的计算。原来我刚才描述的所有加法和乘法都可以用矩阵乘法来概括。
概述如何执行矩阵乘法:
矩阵乘法应用于我们的例子:
这里,我将所有第一层权重排列在标有 w 的金色矩阵中。我将输入 x 排列为红色向量。偏置单位显示为绿色,对于给定的层都是一样的(在这种情况下,它们都是-2)。
如果通过矩阵乘法和偏置加法,您会看到我们获得了与之前完全相同的答案:节点 E 为 2.7,节点 F 为-11.67,节点 g 为 1.51。
回想一下,这些数字中的每一个随后都被 sigmoid 函数压缩在 0 和 1 之间:
获得输出
这里显示了输出的最终计算结果。节点 E 输出值 0.937,节点 F 输出值 0.000009,节点 G 输出值 0.819。按照与前面相同的方式,我们将每个数字乘以相应的重量(黄金),将它们相加,加上偏差,然后应用非线性,得到最终输出 0.388。
这就是“正向传递”:神经网络如何根据输入数据计算输出预测。
后传呢?
在这里,我会向你推荐马特·马祖尔的精彩文章“一步一步反向传播的例子”如果你完成了他的反向传播的例子,我保证你会对反向传递的工作原理有很好的理解,也就是说,神经网络如何调整每一个权重以在下一次得到更正确的答案。
修改神经网络以获得更正确答案的过程也称为“梯度下降”“梯度”只是损失函数的导数,“下降”表示我们试图“下降导数”,或者使损失函数变小。如果你把损失函数想象成一座小山,我们正在努力“下山”,这样我们的损失就更小,我们的答案就更少错误(更正确)。
滑雪下降损失功能
结束了!敬请关注未来关于多类与多标签分类、不同种类的非线性、随机与批量、小批量梯度下降的帖子!
原载于 2019 年 1 月 17 日http://glassboxmedicine.com。
用张量流进行神经类型转换的介绍
原文:https://towardsdatascience.com/introduction-to-neural-style-transfer-with-tensorflow-99915a5d624a?source=collection_archive---------18-----------------------
学会复制 Prisma 背后的逻辑,生成艺术!
Photo by Juan Di Nella on Unsplash
神经风格转移是卷积神经网络最具创造性的应用之一。通过拍摄内容图像和风格图像,神经网络可以将内容和风格图像重新组合,有效地创建艺术图像!
这些算法非常灵活,内容和风格的几乎无限可能的组合产生了非常有创意和独特的结果。
Source: Deeplearning.ai
事实上,一家公司优化了算法,并发布了一款名为 Prisma,的移动应用程序,该程序使用神经风格转移将艺术风格应用到从您的手机拍摄的图片上!
Example of generated images using Prisma
在这篇文章中,我们将重新创建由 Gatys 等人 提出的算法,以实现如上所示的类似结果。请注意,我是在笔记本电脑上工作的,因此,如果您在 CPU 更好的台式机上工作,结果可能会略有不同。
一如既往,随时查阅完整笔记本你有没有被卡住过。
我们开始吧!
关于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
Let’s make some art!
第一步:装载 VGG-19
从头开始构建算法将需要大量的时间和计算能力,这不是每个人都可以轻易获得的。
相反,我们将加载现有网络的权重来实现神经类型转移。
将神经网络用于不同目的的过程被称为迁移学习。
让我们像这样加载模型:
model = load_vgg_model(“pretrained-model/imagenet-vgg-verydeep-19.mat”)
太好了!现在,我将使用卢浮宫的一张图片作为内容图片。您可以加载任何您想要的图片,但请确保图片不要太大:
content_image = scipy.misc.imread(“images/louvre.jpg”)imshow(content_image)
在我的例子中,输出如下:
步骤 2:定义内容成本函数
为了让我们的算法生成漂亮的图像,我们需要确保生成图像的内容与输入图像的内容相匹配。
换句话说,生成的图像还应该有金字塔、周围的建筑、云彩、太阳等。
因此,我们希望生成的图像和内容图像的层激活相似。因此,内容成本函数可以定义为:
Content cost function
根据上面的等式,n_H 和 n_W 分别是图像的高度和宽度,其中 n_c 是隐藏层中的通道数。
为了计算成本,更有效的方法是将 3D 体积展开成 2D 矩阵,因为这将加速计算。
Unrolling the convolution layer to compute the cost. Source
现在,我们编码这个逻辑:
步骤 3:定义风格成本函数
现在,我们需要一个风格的图像。就我而言,我将使用莫奈的印象派作品,但也可以随意使用任何其他类型的艺术作品:
Can someone tell me the name of this painting?
定义风格成本函数比定义内容成本函数稍微复杂一些。让我们把它分解成更小的部分。
步骤 3.1:定义 Gram 矩阵
样式矩阵也被称为 Gram 矩阵,它代表一组向量的点积。
这捕获了每个向量之间的相似性,因为如果两个向量彼此相似,那么它们的点积将会很大,因此克矩阵将会很大。
Gram matrix. Source
这就是 Gram matrix 如何有效地测量图像的风格。
将它写入代码:
步骤 3.2:定义风格成本
现在,我们要确保生成的图像和样式图像的样式是相似的。
换句话说,我们希望最小化两个 Gram 矩阵之间的距离。这表示为:
Style cost function
逻辑编码:
步骤 3.3:分配样式权重
在上一步中,我们只获取了单一图层的样式成本。将所有图层的样式成本结合起来以生成更好的图像将是有用的。
从数学上讲,风格成本变成了:
Combined style cost for all layers
其中λ是每层的权重。
因此,我们添加了这个代码单元:
第 3.4 步:结合一切
现在,我们简单地将所有内容合并到一个单一的风格成本函数中:
步骤 4:定义总成本函数
现在我们有了内容和样式的成本函数,我们可以将两者结合起来,以获得将被优化的总成本函数:
Total cost function
其中α和β是任意权重。
第五步:解决优化问题并生成图像
现在,最精彩的部分!一切就绪,就可以解决优化问题,生成艺术形象了!
在我的例子中,我得到以下结果:
Content image to generated image
当然,如果你训练网络的时间更长,学习率更小,你可以得到好得多的结果。
恭喜你!你刚刚在 TensorFlow 里进行了神经风格转移!可以随意改变内容和样式图像,可以随意调整迭代次数和学习率。
下次见!
来源: Deeplearning.ai
OpenVINO 简介
原文:https://towardsdatascience.com/introduction-to-openvino-897e705a1f0a?source=collection_archive---------6-----------------------
理解 OpenVINO 工具包功能的综合指南
Photo by Christian Wiediger on Unsplash
OpenVINO 代表开放视觉推理和神经网络优化。它是英特尔提供的一个工具包,用于促进深度学习模型的更快推理。它帮助开发人员创建具有成本效益且健壮的计算机视觉应用。它在边缘实现深度学习推理,并支持跨计算机视觉加速器(CPU、GPU、英特尔 Movidius 神经计算棒和 FPGA)的异构执行。它支持大量开箱即用的深度学习模型。你可以查看这个链接来了解更多关于模型动物园的信息。
先决条件
如果您想运行本文末尾提供的代码示例,那么请确保您已经正确下载并配置了 OpenVINO toolkit。
[## 开始使用|英特尔发布的 OpenVINO 工具包
使用该计算机视觉工具包的资源和培训材料快速上手。
software.intel.com](https://software.intel.com/en-us/openvino-toolkit/documentation/get-started) [## 选择并下载|英特尔发布的 OpenVINO 工具包
下载英特尔发布的 open vino toolkit for Linux、Windows 或 macOS 版本。
software.intel.com](https://software.intel.com/en-us/openvino-toolkit/choose-download)
概观
执行过程如下—
- 我们将预先训练好的模型输入到模型优化器中。它优化模型并将其转换为中间表示形式(。xml 和。bin 文件)。
- 推理机有助于模型在不同设备上的正确执行。它管理在不同*台上正确运行代码所需的库。
OpenVINO 工具包的两个主要组件是模型优化器和推理引擎。因此,我们将深入了解它们的细节,以便更好地理解它们的角色和内部工作方式。
模型优化器
Model optimizer 是一个跨*台的命令行工具,有助于在培训和部署环境之间进行转换。它调整深度学习模型,以便在端点目标设备上实现最佳执行。
工作
模型优化器将模型加载到内存中,读取它,构建模型的内部表示,优化它,并产生中间表示。中间表示是推理机接受和理解的唯一格式。
模型优化器不推断模型。它是一个离线工具,在推理发生之前运行。
模型优化器有两个主要目的:
- 产生一个有效的中间表示。模型优化器的主要职责是生成两个文件(。xml 和。bin),它们形成中间表示。
- 产生优化的中间表示。预训练模型包含对训练很重要的层,例如下降层。这些层在推理过程中没有用,可能会增加推理时间。在许多情况下,这些层可以从生成的中间表示中自动移除。但是,如果一组层可以表示为一个数学运算,因此可以表示为一个层,则模型优化器可以识别这种模式,并用一个层来替换这些层。结果是一个比原始模型层数更少的中间表示。这减少了推断时间。
操作
- 重塑 —
- 模型优化器允许我们重塑输入图像。假设您已经使用 256 * 256 的图像大小训练了您的模型,并且您想要将图像大小转换为 100 * 100,那么您可以简单地将新的图像大小作为命令行参数传递,模型优化器将为您处理剩下的工作。
2.配料 —
- 我们可以在推理时改变模型的批量大小。我们可以将批处理大小的值作为命令行参数传递。
- 我们也可以像这样传递我们的图像大小[4,3,100,100]。这里,我们指定需要 4 个尺寸为 1001003 的图像,即具有 3 个通道且宽度和高度为 100 的 RGB 图像。这里需要注意的重要一点是,现在的推断会更慢,因为我们使用一批 4 张图片进行推断,而不是只使用一张图片。
3.修改网络结构 —
- 我们可以修改我们网络的结构,也就是说,我们可以从顶部或底部去掉一些层。我们可以指定一个特定的层,从这里开始执行,或者从这里结束执行。
4.标准化和规模化 —
- 我们可以对输入数据执行标准化(均值减法)和标准化等操作。
量化
这是优化过程中的重要一步。大多数深度学习模型通常使用 FP32 格式作为输入数据。FP32 格式消耗大量内存,因此增加了推断时间。因此,直觉上我们可能认为,我们可以通过改变输入数据的格式来减少我们的推理时间。还有各种其他格式,如 FP16 和 INT8,我们可以使用,但我们需要小心执行量化,因为它也可能导致精度损失。
使用 INT8 格式可以帮助我们显著减少推理时间,但目前只有某些层与 INT8 格式兼容:卷积、ReLU、池化、Eltwise 和 Concat。因此,我们本质上执行混合执行,其中一些层使用 FP32 格式,而一些层使用 INT8 格式。有一个单独的层来处理这些转换。也就是说,我们不必明确指定从一层到另一层的类型转换。
校准层处理所有这些复杂的类型转换。它的工作方式如下—
- 最初,我们需要定义一个阈值。它决定了我们愿意接受的准确度下降。
- 然后,校准图层获取数据的子集,并尝试将图层的数据格式从 FP32 转换为 INT8 或 FP16。
- 然后检查精度下降,如果低于指定的阈值,则进行转换。
推理机
在使用模型优化器创建中间表示(IR)之后,我们使用推理引擎来推理输入数据。
推理机是一个 C++库,有一组 C++类来推断输入数据(图像)并得到一个结果。C++库提供了一个 API 来读取中间表示,设置输入和输出格式,并在设备上执行模型。
由于推理机的存在,模型的异构执行成为可能。它为不同的设备使用不同的插件。
异构插件
- 我们可以在多个设备上执行相同的程序。我们只需要将目标设备作为命令行参数传入,推理引擎会处理剩下的事情,也就是说,我们可以在 CPU、GPU、VPU 或任何其他与 OpenVINO toolkit 兼容的设备上运行相同的代码。
- 我们还可以在不同的设备上执行程序的各个部分,即程序的某些部分可能在 CPU 上运行,而其他部分可能在 FPGA 或 GPU 上运行。如果我们指定 HETERO: FPGA,CPU,那么代码将主要在 FPGA 上运行,但是如果它遇到与 FPGA 不兼容的特定操作,那么它将切换到 CPU。
- 我们还可以在特定设备上执行某些层。假设你想只在你的 GPU 上运行卷积层,那么你可以明确地指定它。
- 这里需要注意的重要一点是,在指定不同的硬件时,我们需要注意数据格式。并非所有设备都支持所有数据类型。例如,配备 Movidius 芯片的神经计算棒 NCS2 不支持 INT8 格式。你可以查看这个链接来获得关于支持的设备及其各自格式的完整信息。
代码示例
英特尔提供的原始代码样本可以在这里找到。
我修改了代码样本,使其更简单,我的版本可以在这里找到。
这里我只解释 OpenVINO 的具体代码。
# Initialize the classinfer_network = Network()# Load the network to IE plugin to get shape of input layern, c, h, w = infer_network.load_model(args.model, args.device, 1, 1, 2, args.cpu_extension)[1]
我们正在初始化网络类,并使用load_model
函数加载模型。
load_model
函数返回插件和输入形状。
我们只需要输入形状,这就是为什么我们在函数调用后指定了[1]。
infer_network.exec_net(next_request_id, in_frame)
exec_net
函数将启动一个异步推理请求。
我们需要传入请求 id 和输入框。
res = infer_network.get_output(cur_request_id)for obj in res[0][0]: if obj[2] > args.prob_threshold: xmin = int(obj[3] * initial_w) ymin = int(obj[4] * initial_h) xmax = int(obj[5] * initial_w) ymax = int(obj[6] * initial_h) class_id = int(obj[1])
这是代码中最重要的部分。
get_output
函数将给出模型的结果。
每个检测用以下格式表示—
[image_id,class_label,confidence,x_min,y_min,x_max,y_max]
这里,我们已经提取了边界框坐标和类 id。
[## dhairya 10/人数-葡萄酒
这个项目使用 Python 和 OpenVINO toolkit 来计算给定帧中的人数。OpenVINO toolkit 是…
github.com](https://github.com/Dhairya10/people-count-vino)
参考
该项目大量借鉴了英特尔 IOT 开发套件的商店通道监视器 python 项目。
[## 英特尔-物联网-开发套件/商店-过道-监视器-python
这个参考实现在 C++中也是可用的。这个参考实现计算人数…
github.com](https://github.com/intel-iot-devkit/store-aisle-monitor-python)
要探索英特尔的其他激动人心的项目,请查看英特尔物联网开发套件。
[## 英特尔物联网开发套件
用 C 语言编写的用于低速 IO 通信的 Linux 库,绑定了 C++、Python、Node.js 和 Java。支持通用 io…
github.com](https://github.com/intel-iot-devkit)
说到这里,我们已经到了这篇文章的结尾。非常感谢你的阅读。
我的 LinkedIn 、 Twitter 和 Github 。
你可以查看我的网站了解更多关于我和我的工作。
造纸厂简介
原文:https://towardsdatascience.com/introduction-to-papermill-2c61f66bea30?source=collection_archive---------3-----------------------
如何将您的 Jupyter 笔记本转变为工作流程工具
Figure 1. Papermill and Jupyter Project logos
1.介绍
Jupyter 笔记本是探索性数据分析(EDA)的黄金标准,也是记录数据科学项目的绝佳工具。虽然数据科学家通常在其中迭代工作(不遵循自上而下的单元顺序),但它可以从第一个到最后一个单元运行,逐步再现数据分析。
使用 Jupyter 笔记本执行重复性任务和 ETL 时出现的一个问题是,它缺乏自动化和日志记录功能。缺乏自动化意味着您必须在需要时打开相应的笔记本并手动运行它,并且缺乏日志记录,您无法控制执行过程中可能出现的错误和异常。
1.1 进入造纸厂
Papermill 是一个可以让我们参数化执行笔记本的工具。它在数据工作流工具上通过顺序执行每个单元格来转换您的 Jupyter 笔记本,而无需打开 JupyterLab(或笔记本)。它试图填补自动化和日志记录的空白,为我们提供了一种将笔记本作为文件执行的方式,并为每次执行生成一份报告。
目标:本文的目标是集成 Papermill 和 Jupyter 笔记本来创建数据工作流。为了说明这一点,我们将开发一个 Python 笔记本,使用天气预报 API ( PyOWM )运行一个简单的分析,执行数据辩论,生成一些可视化结果,并创建一个最终报告。
Jupyter 笔记本和其他具有更多数据分析细节的文件可以在 GitHub 项目资源库 中找到。要重现分析,您需要安装paper mill _ env . YAML上列出的库。
2.配置我们的开发环境
2.1 安装 Papermill 和 JupyterLab
我们将首先使用 Conda (1,2) 创建一个开发环境,并安装 JupyterLab 和其他用于分析的库 (3) 。
**# 1) Create a conda environment** conda create -n papermill python=3.7**# 2) Activate it** conda activate papermill **# 3) Install the libraries using pip (or conda)** pip install papermill pyowm jupyterlab pandas seaborn boto3 pdfkit
有关如何使用 conda 和其他开源工具来组织您的项目的更多信息,请查看我以前的文章 “创建坚实的数据科学开发环境”。
安装 Papermill 后,我们可以通过终端 (4) 获得更多信息。
**# 4) Papermill Documentation** papermill -hUsage: papermill [OPTIONS] NOTEBOOK_PATH OUTPUT_PATHThis utility executes a single notebook in a subprocess.Papermill takes a source notebook, applies parameters to the source
notebook, executes the (4)notebook with the specified kernel, and saves the
output in the destination notebook.The NOTEBOOK_PATH and OUTPUT_PATH can now be replaced by `-` representing
stdout and stderr, or by the presence of pipe inputs / outputs. Meaning
that`<generate input>... | papermill | ...<process output>`with `papermill - -` being implied by the pipes will read a notebook from
stdin and write it out to stdout.Options:
-p, --parameters TEXT... Parameters to pass to the parameters cell.
-r, --parameters_raw TEXT... Parameters to be read as raw string.
-f, --parameters_file TEXT Path to YAML file containing parameters.
-y, --parameters_yaml TEXT YAML string to be used as parameters.
-b, --parameters_base64 TEXT Base64 encoded YAML string as parameters.
--inject-input-path Insert the path of the input notebook as
PAPERMILL_INPUT_PATH as a notebook
parameter.
--inject-output-path Insert the path of the output notebook as
PAPERMILL_OUTPUT_PATH as a notebook
parameter.
--inject-paths Insert the paths of input/output notebooks
as
PAPERMILL_INPUT_PATH/PAPERMILL_OUTPUT_PATH
as notebook parameters.
--engine TEXT The execution engine name to use in
evaluating the notebook.
--request-save-on-cell-execute / --no-request-save-on-cell-execute
Request save notebook after each cell
execution
--prepare-only / --prepare-execute
Flag for outputting the notebook without
execution, but with parameters applied.
-k, --kernel TEXT Name of kernel to run.
--cwd TEXT Working directory to run notebook in.
--progress-bar / --no-progress-bar
Flag for turning on the progress bar.
--log-output / --no-log-output Flag for writing notebook output to the
configured logger.
--stdout-file FILENAME File to write notebook stdout output to.
--stderr-file FILENAME File to write notebook stderr output to.
--log-level [NOTSET|DEBUG|INFO|WARNING|ERROR|CRITICAL]
Set log level
--start_timeout INTEGER Time in seconds to wait for kernel to start.
--report-mode / --no-report-mode
Flag for hiding input.
--version Flag for displaying the version.
-h, --help Show this message and exit.
正如我们从 Papermill 文档 中看到的,基本用法非常简单,我们只需要提供目标 Jupyter 笔记本的路径和输出笔记本的名称(作为日志工作)。我们将在本文后面探讨一些额外的选项。
2.2 安装 Jupyter 内核
尽管 Jupyter 笔记本以运行 Python 而闻名,但我们可以通过安装不同的内核来使用几乎任何编程语言。有了特定的内核,我们可以在 Papermill 定义的环境中运行我们的笔记本,避免了缺少库的问题 (5) 。
**# 5) Install Jupyter kernel for papermill environment** pip install ipykernelipython kernel install --user --name=papermill-tutorial
3.创建工作流
我们将使用 Jupyter 笔记本进行天气预报数据分析。其想法是创建一个简单的工作流,使用名为 的 Python API 获取特定城市的数据,执行数据争论,创建一些图表并在 pdf 报告上组织信息。
3.1 使用 PyOWM 天气 API
如库主页所述,“PyOWM 是 OpenWeatherMap web APIs 的客户端 Python 包装库”。它通过提供一个“简单的对象模型”来方便访问天气数据。使用这个库的唯一要求是一个 API 密匙,可以在 OpenWeather 链接上免费获得。
3.2 工作流第 1 部分:使用 PyOWM API 获取天气数据
工作流的第一部分包括使用 PyOWM 库获取关于预定义的city
(圣保罗,BR 在原始笔记本上)的信息。我们迭代forecast
对象,在 DataFrame 上组织返回的信息,使我们在接下来的步骤中更加轻松。
3.3 工作流第 2 部分:使用 PyOWM API 获取天气数据
在工作流程的第二部分,我们将汇总白天的数据,并在一个图中绘制温度信息,在另一个图中绘制降雨、湿度和云量百分比信息。
3.4 工作流程第 3 部分:创建 PDF 格式的天气报告
在我们工作流程的最后一部分,我们将使用为城市和地块收集的数据创建天气报告。我们将使用库 pdfkit 将我们的 HTML 模板转换成 pdf 文件。
3.5 使用造纸厂前的最终测试
在我们的 Jupyter 笔记本上完成分析后,建议通过重启内核并运行所有单元来测试工作流( Run > Run all cells )。如果我们观察到所有的单元都被成功地执行了,并且输出完全符合我们的预期,那么我们的笔记本就可以和 Papermill 一起使用了。我们的工作流 can 生成的圣保罗市(巴西)的预期天气报告如图 2 所示。在接下来的会话中,我们将配置 Jupyter 笔记本,以接受任何城市作为工作流的参数,并使用 Papermill 自动执行它。
Figure 2. The weather forecast report created with our workflow for the city of Sao Paulo, BR.
4.为 Papermill 配置笔记本
现在我们已经为生产准备好了笔记本,我们只需要对配置进行一些更改,就可以在 Papermill 中使用它了。您可以选择使用 Jupyter Lab 或与 Papermill 集成的 Jupyter Notebook。对于每个*台,带有参数的单元的配置是不同的,因此我们在进行这一步时需要注意。
4.1 在 Jupyter Lab 上定义参数
当使用 Jupyter Lab 运行笔记本时,我们必须为工作流中使用的参数创建一个缺省值的单元格。接下来,我们选择带有参数的单元格,单击笔记本工具(左侧面板上的扳手图标)和高级工具(图 3) 。
Figure 3. Configuring a notebook cell to receive the parameters from Papermill on JupyterLab.
在单元元数据框中,我们需要添加以下描述:
{
"tags": [
"parameters"
]
}
不要忘记点击方框上方的勾号图标保存它。现在,您的 Jupyter 实验室笔记本已准备好接收来自 Papermill 的参数。
4.2 在 Jupyter 笔记本上定义参数
要在 Jupyter 笔记本上配置参数单元格,我们需要点击视图>单元格工具栏>标签。然后将标签parameters
写入并添加到相应的笔记本单元格中(图 4)。
Figure 4. Configuring a notebook cell to receive the parameters from Papermill on JupyterNotebook.
5.执行 Papermill
我们可以通过命令行或者使用 Python API 来执行 Papermill 。为了使用终端运行 Jupyter 笔记本,我们运行命令 (6):
**# 6) To execute Papermill from the terminal** papermill weather_forecast_using_pyowm.ipynb \
weather_forecast_using_pyowm_output.ipynb \
-p city 'Sao Paulo,BR' \
-k papermill-tutorial
前两个参数是目标 Jupyter 笔记本的名称(来自会话 3)和输出笔记本的名称(输入的执行版本)。-p
代表参数,所以我们描述每个参数的名称及其各自的值(在我们的例子中,我们只有city
)。最后,-k
代表内核,我们选择在第 5 步中创建的papermill-tutorial
内核。
如果我们想要使用 Papermil Python API 来运行相同的过程,我们必须键入以下命令:
5.1 输出笔记本
Papermill Python API 可用于将笔记本的执行与其他操作集成在一起。例如,如果在执行过程中出现错误,我们可以解析输出文件,识别问题并将其保存在数据库结构中。
朱庇特笔记本文件(。ipynb 扩展)是 JSON 文件,包含每个单元格文本、源代码、输出和元数据的信息。Papermill 会创建一个输出文件,该文件对应于使用用户指定的参数执行的输入笔记本。它基本上包含了记录流程所需的所有信息,这意味着我们可以将它作为类似日志的数据来记录我们的工作流执行。因此,保存输出 JSON 文件的一种方法是使用 NoSQL 键值数据库( Amazon DynamoDB 、 MongoDB 、 CassandraDB 、 BigTable 等)。
6.最后的想法
Papermill 是一个简单方便的工具,可以将 Jupyter 笔记本转换为数据工作流。它扩展了笔记本电脑的使用可能性,打破了可视化/文档环境的障碍,成为一个生产就绪的*台。在创建最终的 ETL 以在更复杂的数据管道工具如 Airflow 或 Luigi 上运行之前,它可以作为一个快速便捷的工具用于数据工作流的原型化。
我们试图向读者简单介绍 Papermill,但是将该工具与其他资源集成的可能性是无限的。我们相信一个活跃的社区将围绕它成长,将这个项目转化为一个更成熟的工具。
非常感谢你阅读我的文章!
- 你可以在我的个人资料页面 找到我的其他文章🔬
- 如果你喜欢并且想成为中级会员,你可以使用我的 推荐链接 来支持我👍
其他资源
[## 创建可靠的数据科学开发环境
如何使用 Conda、Git、DVC 和 JupyterLab 来组织和复制您的开发环境。
towardsdatascience.com](/creating-a-solid-data-science-development-environment-60df14ce3a34) [## 使用 Jupyter 笔记本自动生成报告(使用 Jupytext 和 Papermill)
Jupyter 笔记本是交互式运行代码和用数据编写叙述的最佳可用工具之一…
medium.com](https://medium.com/capital-fund-management/automated-reports-with-jupyter-notebooks-using-jupytext-and-papermill-619e60c37330) [## 使用 Papermill 自动化 Jupyter 笔记本
Jupyter 笔记本是探索数据、测试假设、协作和报告发现的绝佳方式。与 Jupyter 一起…
medium.com](https://medium.com/y-data-stories/automating-jupyter-notebooks-with-papermill-4b8543ece92f) [## 数据管道、Luigi、气流:你需要知道的一切
这篇文章是基于我最*给同事们做的关于气流的演讲。
towardsdatascience.com](/data-pipelines-luigi-airflow-everything-you-need-to-know-18dc741449b7)
主成分分析(PCA)简介-使用 Python 代码
原文:https://towardsdatascience.com/introduction-to-principal-component-analysis-pca-with-python-code-69d3fcf19b57?source=collection_archive---------15-----------------------
PCA 介绍——原因、时间和方式
动机
想象一个有 100000 个句子的文本数据。文本中唯一单词的总数是 10000(词汇量)。如果每个句子由长度等于词汇大小的向量表示。在这个长度为 10000 的向量中,每个位置属于一个唯一的单词。对于我们这个句子的向量,如果某个词出现 k 次,那么这个词的索引对应的向量中元素的值就是 k 。对于词汇表中没有出现在我们句子中的每一个单词,向量元素是 0。这被称为一键编码。
现在,如果我们为这些句子中的每一个创建向量,我们有一组 100000 个向量。在矩阵形式中,我们有一个 100000*10000 大小的矩阵。这意味着我们的矩阵中有 10⁹元素。在 python 中,要估计占用的内存,
import numpy as np
import sys
sys.getsizeof(np.zeros((100000,10000)))
>>> 8000000112
这个数字以字节为单位,转换成 8000 兆字节。
如果我们能够在一个更小的矩阵上工作,一个具有更少但更重要的特征的矩阵,会怎么样?比方说,大约 100 个特征可以捕获数据的大部分信息。拥有更多功能通常是好事。但是更多的特征通常也包括噪声。噪声会降低任何机器学习算法的鲁棒性,尤其是在小数据集上(阅读维度的诅咒了解更多)。此外,我们将节省 100-1000 倍的内存消耗。当您将应用程序部署到生产环境中时,这一点非常重要。
带着这个目的,我们来讨论一下 PCA 是如何帮助我们解决这个问题的。
方差作为信息
在机器学习中,我们需要算法的功能来找出有助于区分数据类别的模式。特征的数量越多,差异(数据的变化)就越大,因此模型发现很容易做出“分割”或“边界”。但并不是所有的功能都能提供有用的信息。他们也会有噪音。如果我们的模型开始适应这种随机噪声,它将失去其鲁棒性。事情是这样的— 我们希望从可用的特征空间中组合出 m 个 特征,以获得最大的方差。注意,我们要组合而不是仅仅选择 m 特征。
从数学角度来说
假设一个数据点由矢量 x 表示,原本具有 n 特征。
vector x
我们的工作是将它转换成一个向量 z ,维数比n 少,比如说 m
vector z
这是通过线性变换实现的。具体来说,我们将一个矩阵乘以 x ,将其映射到一个 m- 维空间。考虑一个大小为 nm 的矩阵*。使用 W ,我们希望将 x 转换为 z 为—**
PCA transformation. Wt is the transpose of W
对上述等式的简单解释—假设您有一个包含列的原始数据框—
Original Dataframe
在 PCA 之后,如果我们选择,比方说 3 个分量,数据帧看起来像这样—
在哪里,
c1,c2,..而 d1,d2,…是标量。w 矩阵是
W — a 5*2 matrix
考虑下面的示例图。指向东北的轴沿其方向覆盖了更多的分布。那么第二大“覆盖”轴指向西北。
Image credits: https://i1.wp.com/enhancedatascience.com/wp-content/uploads/2017/05/PCA1.png?resize=629%2C424
如何获得 W?
上面的描述对于一个关于 PCA 的小对话来说已经足够好了。但是如果你对 W 的计算很好奇,这一节是给你的。如果你对数学不感兴趣,你可以跳过它。
我们讨论过 PCA 是关于计算方差最大化的轴。考虑一个单轴 w** ,我们希望沿着它最大化方差。数学上,**
为了计算方差,我们需要均值。在统计学中,最好称之为期望,用 E 表示。随机变量的期望就是它的均值。在我们的例子中,我们将原始特征的期望值 x 表示为μ。对于我们转换后的特征, z 我们的期望值是 wt μ(见下图)*
如果你感到困惑,参考下面的等式,取 LHS 和 RHS 的*均值
matrix multiplication is commutative
设变换特征的*均值为
随机变量 z 的样本方差由下式给出:
用期望和从期望操作中取出 w 来表示(因为它是一个常数,不依赖于 z
原来, z 的方差就是wt * x(sigma) w的协方差。协方差是多维随机变量的方差,在我们的例子中是 x 。它是一个大小为 kk 的方阵,其中 k 是 x 的尺寸。是一个对称矩阵。关于协方差矩阵的更多信息
在我们最大化方差之前,我们对我们的 w 矩阵的范数施加一个重要的条件。标准应该是 1
Norm = 1
为什么?否则,最大化方差的简单方法就是增加范数,而不是以最大化方差的方式重新调整主轴。这个条件包括使用拉格朗日乘数
如果我们对上面的表达式求导,我们得到—
看看最后一个表情。协方差矩阵乘以 w 等于标量α乘以 w 。这意味着, w 是协方差矩阵的特征向量,α是对应的特征值。利用这个结果,
var(z) is the eigenvalue
如果要使 var(z) 最大化,那么α必须是所有特征值中最大的。并且对应的特征向量是主分量
这为我们提供了第一个主成分,与任何其他成分相比,沿着该主成分解释的方差是最大的。以上是第一个轴的推导。类似地导出其他轴。重点是深入研究 PCA 背后的数学。
数学说够了!给我看看代码
我们使用的数据集是 Coursera 的课程评论,可在 Kaggle 上获得。这个练习的代码可以在我的 GitHub repo 上找到。
顾名思义,由评论(句子)和评分(1,2,3,4,5)组成。我们收集了 50,000 条评论,使用 TF-IDF 对它们进行清理和矢量化。
TF-IDF 是一种给句子中的每个单词分配分数的评分方法。如果该词在所有评论中不常出现,但在总体上频繁出现,则得分高。比如课程这个词出现频率很高,但是几乎每隔一个复习就出现一次。所以这个词的 TF-IDF 分数会在下面。另一方面,差这个词出现频率很高,而且只针对负面评论。所以它的分数更高。**
因此,对于每次审查,我们有固定长度的 TF-IDF 向量。向量的长度就是词汇量的大小。在我们的例子中,TF-IDF 矩阵的大小为 50000*5000。而且 99%以上的元素都是 0。因为如果一个句子有 10 个单词,5000 中只有 10 个元素是非零的。
我们使用主成分分析来降低维数。但是怎么决定要带多少组件呢?
让我们来看一下解释的方差图与组件或轴数的关系
Variance explained vs the number of components
如您所见,前 250 个组件解释了 50%的变化。前 500 个组件占 70%。如您所见,增量收益减少了。当然,如果你取 5000 个组件,解释的方差将是 100%。但是那么做 PCA 有什么意义呢?
— — — —
我已经开始了我的个人博客,我不打算在媒体上写更多令人惊叹的文章。通过订阅帮助空间来支持我的博客
主成分分析导论
原文:https://towardsdatascience.com/introduction-to-principle-component-analysis-d705d27b88b6?source=collection_archive---------15-----------------------
由 In Visal,Yin Seng,Choung Chamnab & Buoy Rina 撰写—本文于 2019 年 7 月 20 日提交给“脸书开发商圈:金边”小组。这里是原幻灯片包—
为什么是 PCA?
据 DataCamp 称,可通过以下方式查看五氯苯甲醚:
- 应用线性代数中更有用的方法之一
- 从混乱的数据集中提取有意义信息的非参数方法
- 揭示数据背后隐藏的低维结构
- 这些结构更容易可视化,并且通常可以被内容专家解释
形式定义
根据维基百科:
“主成分分析(PCA)是一种统计过程,它使用正交变换将一组可能相关的变量(每个变量都具有不同数值的实体)的观察值转换为一组称为主成分的线性不相关变量的值。”
对上述定义的第一反应是“管它呢?”。
从我的经验来看,任何数学或统计定理的正式定义一开始都是难以理解和令人生畏的。这并不是因为这些定义含糊不清,而是因为我们最初缺乏对主题的理解。在掌握和理解了这个主题之后,我们将会体会到形式定义的简洁。
正交投影
在深入 PCA 的计算之前,让我们回顾一下作为 PCA 支柱的正交投影概念。
Illustration of orthogonal projection
- Ai 向量在主分量上的投影通过勾股定理将剩余方差与残差*方联系起来。
- 选择最大化方差的分量与选择最小化残差*方和的分量是一样的。
Maximising variance = minimizing the residuals
- 在 分量 x 上的投影具有比 分量 和 分量 y. 更小的损失方差
- 在 分量 y 上的投影比 分量 和 分量 x. 具有更高的损失方差
计算主成分
根据下面的散点图,X1 和 X2 是数据集的特征。这个数据集的主要成分的方向是什么?
Raw dataset
可通过以下步骤计算 PCA:
- 从质心(Xavg,Yavg)开始
- 确定投影误差/残差之和最小化的方向。我们称之为“第一”主成分。
- “第二”主分量是与第一主分量正交的方向。
这是一个 顺序 算法。
Step-1 & Step-2
Step-3
还有另外两种更好的算法来计算 PCA:
- 样本协方差矩阵的特征分解
- 数据矩阵的奇异值分解(下一节)
在 Scikit Learn 中计算 PCA
使用 sklearn.decomposition 包中的 PCA 函数可以很容易地计算 PCA。
我们首先从 sklearn.decomposition 导入 PCA,并初始化数据 2D numpy 数组。
Import PCA function and initialize data array
接下来,我们通过设置 n_components = 2 来创建一个名为“pca”的 PCA 对象。需要数据作为输入参数的 Fit()方法执行 PCA 计算。
一旦“pca”对象适合输入数据,它现在可以用于通过“变换”功能将数据变换成主成分。
The principal components of the data
我们可以通过提取已解释的方差来对分量的显著性进行排序。
- 解释的方差越高,该成分越重要。
- 具有较小解释方差的分量可以被丢弃,而不会丢失重要信息。
Extracting the components ‘ explained variance
Histogram of the components’ explained variance
从 Numpy SVD 计算 PCA
计算 PCA 的另一种方法是使用 Numpy 对原始数据执行奇异值分解(SVD)。
SVD
我们首先导入整个 Numpy 库,并应用线性代数模块中的‘SVD’函数。“svd”函数返回三个矩阵 U、S 和 Vt。
主成分是通过取 U 和 s 的点积得到的。
The principal components = dot product of U and S
应用程序
MNIST 数据集的 2D 可视化
- 数据集包含手写数字的图像:10 个类别,每个类别指一个数字。
- 代表数字的 8×8 图像的 1797 个样本和 64 个特征
MNIST images
因为有 64 个特征,所以不可能可视化特征关系。PCA 通过将 64 维特征空间减少到 2D 空间(2 个主成分)来拯救我们。
为此,我们从 sklearn.datasets 导入 load_digits 并创建一个名为“pca”的 PCA 对象。n_components 设置为 2。通过调用“fit_transform”函数来获得主分量,该函数执行计算并返回主分量。然后,将得到的主成分进行交会图。
Performing PCA on MNIST dataset
Cross-plot of principal component 1 and 2
MNIST 数据集的降维
为了证明主成分分析在降低特征空间维数方面的鲁棒性,我们在 MNIST 数据集上执行了两种情况的 SVM 分类,并比较了结果的准确性。
- 情况 1:使用原始的 64 个特征来分类 MNIST 数字。
- 案例 2:使用 10 个主成分对 MNIST 数字进行分类。
如下图,精度差只有~1%。
SVM classification — Case 1
SVM classification — Case 2
图像压缩
PCA 的另一个有趣的应用是图像压缩(有损!).如下图,400*600 像素的图像需要 240000 字节来存储。
240,000 bytes required to store an image of 400*600 pixels
我们可以对原始图像应用 SVD,并截断不太重要的分量。在这种情况下,400 个主成分中只有 50 个被保留,其余的被截断。
Applying SVD on the original image and keeping only the top 50 components
通过仅使用前 50 个组件,存储压缩图像所需的存储器仅为 50,050 字节。
Only 50,050 bytes required to store
下面给出了使用 SVD 执行图像压缩的 Python 代码:
Image compression with SVD
下图显示了随着保留组件数量(k)的增加,图像质量的变化。正如所料,k 越高,图像质量越好,所需内存也越高。保留组件的最佳数量(k)是一个主观问题,并且是特定于应用的。
总结
PCA 是应用线性代数的迷人案例之一,它在数据科学中有更多的应用,超出了本文的范围。我们不太可能需要从头开始编写 PCA 代码;然而,当我们需要使用机器学习库来使用 PCA 时,对 PCA 如何工作有一个坚实的理解将是有用的。
特别感谢主要贡献者 Visal 的、Yin Seng、Choung Chamnab ,是他们使这项工作成为可能。
PyTorch 简介
原文:https://towardsdatascience.com/introduction-to-py-torch-13189fb30cb3?source=collection_archive---------7-----------------------
(source: https://pytorch.org)
PyTorch 是一个开源的机器学习库,用于开发和训练基于神经网络的深度学习模型。它主要由脸书的人工智能研究小组开发。PyTorch 可以和 Python 以及 C++一起使用。自然,Python 的接口更加完善。Pytorch(由脸书、微软、SalesForce、优步等巨头支持)在研究实验室非常受欢迎。Pytorch 在许多生产服务器上还没有,这些服务器由 TensorFlow(由 Google 支持)这样的 fromeworks 控制,它正在快速发展。
与大多数其他流行的深度学习框架不同,如 TensorFlow ,它们使用静态计算图,PyTorch 使用动态计算,这允许在构建复杂架构时有更大的灵活性。Pytorch 使用了 Python 的核心概念,如类、结构和条件循环——这些概念对我们来说非常熟悉,因此理解起来更加直观。这使得它比 TensorFlow 等引入自己编程风格的其他框架简单得多。
为了对这个库有所了解,让我们来看看 PyTorch 的一个基本实现。
安装 PyTorch
PyTorch 有一个 Windows 版本,但我宁愿远离它。事实上,如果你真的感兴趣,你最好不要再看窗外了。跳到 SageMaker 。而如果你不想花一分钱,就试试 Google Colab 。
但是如果必须的话,可以在 Anaconda 上安装 PyTorch,使用
现在,让我们从构建神经网络开始。让我们拿起我们的好老 MNIST 数据集。
导入模块
第一步当然是导入相关的库。
收集数据
当然,这个过程的第一步是收集训练模型所需的数据。这里,我们将使用打包到 PyTorch 中的 MNIST 数据集。
这两行是打包了功能的代码。本质上,它从 torchvision.dataset 模块中选取数据集。该数据被归一化,然后加载到张量中。在此基础上,将其装入数据加载器。
建立网络
做完这些,我们从真正的代码开始。如前所述,PyTorch 使用基本的、熟悉的编程范例,而不是发明自己的范例。PyTorch 中的神经网络是一个对象。它是定义这个网络的类的一个实例,继承自 torch.nn 模块
torch.nn .模块提供开发和训练、测试和部署神经网络所需的核心功能。当我们子类化它时,我们通常会覆盖其中的两个方法。框架会处理剩下的事情。
我的意思是。
正如我们所看到的,上面的两种方法给了我们定义神经网络所需要的一切。这个网络有四层(两层隐藏)。前两个是卷积,接下来的两个是线性的、完全连接的层。前三层的激活函数是 Relu,最后一层是 SoftMax。
构造者构建网络。forward()方法定义了它如何向前移动。
训练网络
既然模型已经准备好了,我们就必须使用现有的数据来训练模型。这是通过方法训练()完成的
接收的参数是模型(我们实例化的网络模型)、设备(运行负载的设备 gpu/cpu 的种类)、train_loader(用于训练数据)、优化器(用于训练模型)以及纪元编号(仅用于显示在日志中)。
上面方法中的第一行调用 model.train() —一个从 nn.Module 继承的方法。接下来,我们对从加载器中提取的训练数据批次进行循环。
然后我们初始化优化器。下一行负责正向传播——我们根据当前模型计算输入数据的输出。
接下来的两行负责向后传播。我们通过比较输出和目标来计算损失。然后,我们基于这个损失更新模型。我们对整个数据集都这样做。
测试网络
同样,我们有一个测试方法,可以根据给定的测试数据集来验证网络的性能。
本质上,这种方法只是在整个测试数据中循环,找出所有的损失。它计算正确和错误预测的数量,并打印格式化的日志。
放在一起
有了框架后,我们必须开始将这些片段拼接成一个应用程序,该应用程序可以构建、训练和验证神经网络模型
我们从播种模块开始。
当然,PyTorch(或任何 ML 库)是为 GPU 设计的,但它也可以为 CPU 设计。为了指示执行模式,我们需要实例化设备
下一步是创建我们上面定义的神经网络模型的实例。
下一步是创建一个优化器实例。对于这个例子,我们将使用随机梯度下降来训练这个模型。我们使用 0.01 的学习率和 0.9 的动量
有了舞台设置,剩下的就是用我们拥有的数据来训练网络。
正如我们在教科书中所学的,这是一个 for 循环,它一遍又一遍地向前和向后传播。在每个时期,我们测试我们生成的模型。
与张量流相比,这当然更直观。它的性能成本较低,但研究人员更喜欢 PyTorch 提供的清晰度。
当我们运行上面的代码时,我们得到类似如下的输出:
我们可以看到传入数据的模型训练。我们还可以注意到,该模型在第 9 步之前一直在改进,然后就饱和了——可能过度适应了训练集。我们可以调整超参数来改进这个模型。但我猜 99%对我们的目的来说应该是好的。我们可以使用“提前停止”在步骤 9 中获取模型。
最后,我们保存训练好的模型,以便在现场部署。
当然,这只是一瞥。PyTorch 为不同类型的模型和网络以及不同类型的用例加载了功能。大量的书籍、博客和视频可以给你更多更详细的信息。
他们自己的网站对学习这门学科很有帮助。
PyTorch BigGraph 简介—带示例
原文:https://towardsdatascience.com/introduction-to-pytorch-biggraph-with-examples-b50ddad922b8?source=collection_archive---------6-----------------------
Network Photo by Alina Grubnyak on Unsplash
PyTorch BigGraph 是一个为机器学习创建和处理大型图形嵌入的工具。目前在基于图的神经网络中有两种方法:
- 直接使用图形结构,并将其输入神经网络。然后在每一层都保留图形结构。graphCNNs 使用这种方法,例如参见我的帖子或这篇文章。
- 但是大多数图表都太大了。所以创建图的大嵌入也是合理的。然后把它作为传统神经网络的特征。
PyTorch BigGraph 处理第二种方法,下面我们也将这样做。仅供参考,让我们先讨论一下尺寸。图通常由它们的邻接矩阵编码。如果你有一个有 3000 个节点的图,每个节点之间有一条边,那么你的矩阵中就有大约 10000000 个条目。即使这很少,但根据上面链接的论文中的,这显然会使大多数 GPU 崩溃。
如果你想一想推荐系统中常用的图表,你会发现它们通常要大得多。现在已经有一些关于 BigGraph 的方式和原因的优秀帖子,所以我不会在这方面花更多时间。我对将 BigGraph 应用于我的机器学习问题很感兴趣,为此我喜欢举最简单的例子并让事情运转起来。我构建了两个例子,我们将一步一步来看。
整个代码都经过了重构,可以在 GitHub 获得。它改编自 BigGraph 存储库中的示例。
第一个示例是 LiveJournal 图表的一部分,数据如下所示:
# FromNodeId ToNodeId0 1
0 2
0 3
...
0 10
0 11
0 12
...
0 46
1 0
...
第二个例子是简单的带边的 8 个节点:
# FromNodeId ToNodeId
0 1
0 2
0 3
0 4
1 0
1 2
1 3
1 4
2 1
2 3
2 4
3 1
3 2
3 4
3 7
4 1
5 1
6 2
7 3
嵌入 LiveJournals 图形的一部分
BigGraph 是为机器的内存限制而设计的,所以它是完全基于文件的。您必须触发进程来创建适当的文件结构。如果你想再次运行一个例子,你必须删除检查点。我们还必须预先分成训练和测试,再次以文件为基础。文件格式为 TSV,用制表符分隔值。
让我们开始吧。第一段代码声明了两个助手函数,取自 BigGraph 源代码,设置了一些常量并运行文件分割。
helper functions and random_split_file call.
这通过创建两个文件 data/example_1/test.txt 和 train.txt 将边分成测试和训练集。接下来,我们使用 BigGraphs 转换器为数据集创建基于文件的结构。我们将“分区”成 1 个分区。为此,我们已经需要部分配置文件。这是配置文件的相关部分,I/O 数据部分和图形结构。
entities_base = 'data/example_1' def get_torchbiggraph_config(): config = dict(
# I/O data
entity_path=entities_base,
edge_paths=[],
checkpoint_path='model/example_1', # Graph structure
entities={
'user_id': {'num_partitions': 1},
},
relations=[{
'name': 'follow',
'lhs': 'user_id',
'rhs': 'user_id',
'operator': 'none',
}],
...
这告诉 BigGraph 在哪里可以找到我们的数据,以及如何解释我们的制表符分隔的值。有了这个配置,我们可以运行下一个 Python 代码片段。
convert data to _partitioned data.
结果应该是数据目录中的一堆新文件,即:
- 两个文件夹 test_partitioned,train_partitioned
- h5 格式的边缘每个文件夹一个文件,用于快速部分读取
- dictionary.json 文件包含“user_ids”和新分配的 id 之间的映射。
- entity_count_user_id_0.txt 包含实体计数,在本例中为 47。
dictionary.json 对于稍后将 BigGraph 模型的结果映射到我们想要的实际嵌入非常重要。准备够了,我们来训练嵌入。看一下 config_1.py ,它包含三个相关的部分。
# Scoring model - the embedding size
dimension=1024,
global_emb=False, # Training - the epochs to train and the learning rate
num_epochs=10,
lr=0.001, # Misc - not important
hogwild_delay=2,
) return config
为了进行训练,我们运行以下 Python 代码。
train the embedding.
通过这段代码,我们可以根据测试集上预先安装的一些指标来评估模型。
evaluate the embedding.
现在让我们尝试检索实际的嵌入。同样,因为一切都是基于文件的,所以它现在应该位于 models/ 文件夹中的 h5 位置。我们可以通过在字典中查找用户 0 的映射来加载用户 0 的嵌入,如下所示:
output the embedding.
现在让我们转到第二个例子,一个构造好的例子,我们希望可以在这个例子上做一些有用的事情。liveJournal 数据实在太大了,无法在合理的时间内浏览一遍。
对构建示例的链接预测和排序
好的,我们将重复第二个例子的步骤,除了我们将产生一个 10 维的嵌入,所以我们可以查看和使用它。此外,对我来说,10 维对 8 个顶点来说已经足够了。我们在 config_2.py 中设置这些东西。
entities_base = 'data/example_2'
def get_torchbiggraph_config():
config = dict(
# I/O data
entity_path=entities_base,
edge_paths=[],
checkpoint_path='model/example_2', # Graph structure
entities={
'user_id': {'num_partitions': 1},
},
relations=[{
'name': 'follow',
'lhs': 'user_id',
'rhs': 'user_id',
'operator': 'none',
}], # Scoring model
dimension=10,
global_emb=False, # Training
num_epochs=10,
lr=0.001, # Misc
hogwild_delay=2,
)
return config
然后,我们像以前一样运行相同的代码,但是一次完成,处理不同的文件路径和格式。在这种情况下,我们在数据文件顶部只有 3 行注释:
作为最终输出,你应该得到一堆东西,特别是所有的嵌入。让我们做一些嵌入的基本任务。当然,我们现在可以使用它,并将其加载到我们喜欢的任何框架中, keras , tensorflow ,但是 BigGraph 已经为常见任务带来了一些实现,如链接预测和排名。所以让我们试一试。第一个任务是链路预测。我们预测实体 0-7 和0-1的得分,因为我们从数据中知道0-1的可能性更大。
作为比较器,我们加载了“DotComparator ”,它计算两个 10 维向量的点积或标量积。结果显示输出的数字很小,但至少 score_2 比 score_1 高得多,正如我们所预期的那样。
最后,作为最后一段代码,我们可以生成一个相似项目的排名,它使用与前面相同的机制。我们使用标量积来计算嵌入到所有其他实体的距离,然后对它们进行排序。
在这种情况下,顶级实体的顺序是 0、1、3、7……如果你观察数据,就会发现这似乎非常正确。
更有趣
这是我能想到的最基本的例子。我没有在 freebase 数据或 LiveJournal 数据上运行原始示例,只是因为它们需要相当长的训练时间。您可以在这里找到代码和参考资料:
- PyTorch BigGraph 的 GitHub 库
- GitHub 库带示例代码
- https://arxiv.org/pdf/1903.12287.pdf,a .勒尔等人。艾尔。(2019),PyTorch-BigGraph:大规模图嵌入系统。
- https://arxiv.org/abs/1609.02907,T. N .基普夫,m .韦林(2016),利用图卷积网络的半监督分类。
你可能遇到的问题
我在 mac 上运行代码,遇到了三个问题:
- 说明“lib …”的错误..原因:未找到映像:“解决方案是安装缺少的部分,例如使用“brew install libomp”*
- 然后我遇到了一个错误“attribute error:模块‘torch’没有属性' _ six '”,这可能只是因为不兼容的 python & torch 版本。反正我是从 python 3.6 &火炬 1.1=>python 3.7&火炬 1。X 解决了我的问题。
- 在您继续之前,检查 train.txt 和 test.txt,我在测试时看到那里有一些丢失的新行。
希望这有所帮助,并且玩起来很有趣!
量子编程导论
原文:https://towardsdatascience.com/introduction-to-quantum-programming-a19aa0b923a9?source=collection_archive---------0-----------------------
从量子位到运行真正的量子程序的量子编程演练!
Quantum Computer — Courtesy of Rigetti
问终极电脑存在!量子编程也是!在本文中,我将带您了解开始量子编程所需要知道的一切。我将从一些关于量子计算机与你的笔记本电脑等计算机有何不同的背景开始,然后解释量子编程的基础,并以你今天如何在真正的量子计算机上免费运行程序结束。
在我们开始之前,请注意这篇文章是为那些想学习量子编程全部技术细节的人准备的。这篇文章建立在量子位、量子门和量子电路图的数学基础之上。本文将不解释量子算法或它们的优点,因为那些主题值得它们自己的文章。
因为我们将通过量子编程的基础数学,读者将需要知道什么是向量、矩阵、线性组合和复数。我推荐 3Blue1Brown 学习线性代数,推荐 BetterExplained 学习什么是复数。
量子计算机
让我们从理解量子计算机到底是什么以及它们与其他计算机有何不同开始。
量子计算机是一种使用量子力学进行计算的机器。
那么这和其他电脑有什么不同呢?嗯,计算机,就其最基本的形式而言,只是一种执行计算的机器。有许多不同类型的计算机。在计算机的早期,我们实际上有机械计算机——查尔斯·巴贝奇在 1837 年设计了这样一台机器来执行通用计算。如今,我们的计算机是基于数字电子技术,使用比特和逻辑门操作。相反,量子计算机使用量子力学来执行计算。量子计算机使用的不是比特和逻辑门,而是量子比特和量子门。
那么什么是量子位和量子门呢?在物理上,它们可以是许多不同事物中的任何一种——谷歌、IBM、微软和 Rigetti 都有自己的量子位和量子门实现。目前,我们不会担心量子位和量子门的物理性质,因为在最初学习量子编程时这是不必要的。
量子编程
在我们开始之前,我强烈推荐你在 干净的精神石板 上接*量子编程。不要去寻找如何声明和设置变量,循环代码,创建函数等。你对编程的任何先入之见可能 不会 有用。量子编程不仅仅是让我们现有的程序运行得更快的某种方式——量子编程与当代编程有着根本的不同。
理解量子位
先说 什么是 一个量子位。
一个量子位是两个单位长度复数的向量。
让我们看看 为什么 量子位是这样的,以及的真正含义。量子位与比特有很大不同。对于初学者来说,一个位要么是 0,要么是 1。这里没有概率,要么已知是 0,要么已知是 1。相反,一个量子位天生就是概率性的,这意味着两个 相同的 量子位一旦被测量,可能会有 不同的 值!花点时间认真考虑一下这件事的严重性。这意味着量子计算天生就是概率性的。
这是第二个关键区别。有了位,我们可以任意多次读取该位,而不会影响该位的状态。但是有了量子比特,一旦被测量,它 解聚 (失去量子属性),坍缩到两个可测量状态中的一个(因此才有了‘量子比特’中的‘比特’)。因此,我们不能“不测量”一个量子位;一旦测得,量子性质为 被破坏 无法恢复。我们使用两个数字来量化测量量子位的概率性质:|𝛼|,量子位被测量为 0 的概率,和|𝛽|,量子位被测量为 1 的概率。
尽管|𝛼|和|𝛽|反映了量子位将被 测量为 的概率,我们认为一个量子位的内部状态是两个“概率振幅”,𝛼和𝛽.这些是复数,定义了 0 和 1 之间的叠加(叠加是线性组合),不能测量。**
换句话说,我们把一个量子位想象成两个单位长度复数的向量(向量的长度等于 1)。我们可以简明地用下图所示的数学来表达这一点(包含α和β的向量就是量子位;α和β上方的柱表示复共轭):
概括地说,量子位是两个复数的向量,𝛼和𝛽,其中向量有单位长度。量子位被测量为 0 的概率等于|𝛼|𝛼的*方。量子位被测量为 1 的概率等于|𝛽|𝛽的*方。一个量子位的状态,𝛼和𝛽,是无法测量的。只有一个量子位坍缩成的值才能被测量。
量子位符号
我们经常用 狄拉克符号 来表示量子位,也称为 布拉基特符号 。这种符号只是写向量的一种方便的方法。bra 表示行向量,记为⟨ ∣
;ket 代表列向量,被标为∣ ⟩
。例如,我们可以用 Bra-ket 符号写一个量子位的‘0’和‘1’状态如下(注意不要把 bra/ket 里面的东西和 vector 里面的东西搞混了!):
量子位既可以处于 纯态 也可以处于 混合态 。如果一个量子位的状态可以用∣0⟩
和∣1⟩
的线性组合来完全描述,那么我们说它处于纯态。我们通常用以下符号表示纯态量子位:
这里有一些纯态量子位的例子和表示它们的常用简写。
其他量子比特需要纯态的混合才能完整描述,所以我们称之为混合态量子比特。换句话说,混合态量子位由纯态的概率分布来描述。我们将在本文后面看到一个混合态量子位的例子(我会指出来)。
多量子位
到目前为止,我们只定义了单个量子位的状态。多个量子位 的组合 态是什么样子的?
多个量子位的组合状态是所有量子位的张量积。
不知道张量积是什么也不用担心;我们将通过一个例子(⊗是张量积运算的符号)。
一般来说,我们可以通过以下两个步骤来张量积任何两个矩阵:
- 标量将第一个矩阵中的每个元素乘以整个第二个矩阵
- 根据元素的原始位置组合生成的矩阵
下面是第二个例子,说明它如何适用于二维矩阵:
例如,我们也可以用 Bra-ket 符号表示多个量子位为∣0⟩⊗∣1⟩
。作为速记,我们可以省略⊗,只写∣0⟩∣1⟩
。作为更短的速记,我们可以只写一个偈,∣01⟩
。
理解量子门
现在让我们考虑一下 什么是 量子门。
量子门是酉矩阵。
让我们来了解一下 为什么 量子门是酉矩阵。首先,量子门将由物理设备实现,因此它们必须遵守量子物理定律。一个相关的物理定律是,当在过去和未来之间转换时,信息不会丢失。这就是所谓的单一性。既然我们的量子门定义了我们如何在状态间转换,它们也必须遵守么正性。
其次,注意我们的量子门将应用于量子比特。我们之前了解到量子位实际上只是向量,因此这意味着量子门必须以某种方式对向量进行操作。幸运的是,我们记得矩阵实际上只是向量的线性变换!
结合这两个想法,我们把量子门想象成 酉矩阵 。酉矩阵是任意复数方阵,使得 共轭转置 等于其 逆 。快速复习一下,矩阵的共轭转置是通过取矩阵中每个元素的共轭(a + bi
→ a — bi
),然后取矩阵的转置(元素 ij →元素 ji)得到的。我们通常用匕首表示共轭转置。
关于酉矩阵的一个关键观察是,它们 保持范数 (向量的长度)。假设我们允许改变常态的门,那麽我们量子位元的机率总和可能不是 1!这没有意义,因为所有概率的总和必须总是等于 1。
还要注意,根据定义,酉矩阵有一个逆。这意味着我们不能将量子比特“分配”到任意的状态。为了理解为什么不能,让我们假设我们确实有一个量子门,可以“分配”值,因此,将两个复数的任何向量转换为两个复数的特定向量。这个量子门将会有一些作为酉矩阵的基本表示,而这个矩阵将会有一个逆,能够将一个特定的向量转换回运算前量子位的任何状态!但是量子位在手术前可能处于任何状态,没有办法知道是哪种状态!因此,我们无法将量子位元「指派」到任意的状态。在更高的层面上,所有量子门都是可逆的事实,就是为什么我们经常把量子计算看成是 可逆计算 的一种形式。
最后,请注意,因为我们的量子门是酉矩阵,根据定义,它们是 方 ,所以我们的量子门必须具有 相等的 个输入和输出量子位(因为方矩阵将 n 个标准基向量映射到 n 列)!这与大多数逻辑门大相径庭;例如,和门接受两个输入并产生一个输出。
H 和 CNOT 量子门
现在我们知道了一点我们正在做的事情,让我们考虑一个例子, 哈达玛门 ,h
我们可以通过检查共轭转置等于其逆矩阵来检查 H 是否是酉的,或者换句话说,H 乘以其共轭转置等于单位矩阵:
另一个重要的量子门是 受控非门 ,也被称为 CNOT。CNOT 作用于两个量子位,一个控制量子位和一个目标量子位。我们可以把 CNOT 想象成一个‘if 语句’——如果控制量子位等于 1,那么 CNOT 对目标量子位应用 NOT(逆门)(因此得名,受控 NOT)。
这是代表 CNOT 的矩阵。这个矩阵将控制量子位视为 ket 中最右边的值,将目标量子位视为最左边的值。
我们来看看它对∣00⟩
的影响。
在这个例子中,我们看到 CNOT 没有修改∣00⟩
的值。这是预期的行为,因为 CNOT 只在控件为 1 时反转目标。
让我们看看它对∣01⟩
的影响。
在这里,我们可以看到控制等于 1,所以 CNOT 反转目标。因此,结果是∣11⟩
。
试着解决另外两种情况,∣10⟩
和∣11⟩
。你应该发现 CNOT 有以下行为:
∣00⟩ -> ∣00⟩
∣01⟩ -> ∣11⟩
∣10⟩ -> ∣10⟩
∣11⟩ -> ∣01⟩
请注意,当控制位为 1 时,这正是对目标位应用 NOT 的行为。
概括地说,我们可以把量子门想象成酉矩阵。这种单一性加强了一个量子位的概率总和为 1 的约束,并使量子计算是可逆的。由于酉矩阵是正方形的,我们发现量子门必须有相等数量的输入和输出量子位。我们学习了哈达玛和 CNOT,这是两个重要的量子门。存在更多的量子门。
量子电路图
现在我们知道了量子位和量子门的基础知识,让我们来看看我们的第一个量子电路图。
量子电路图是我们思考量子“程序”的方式。我们将量子位定义为行,从左到右依次应用量子门。
让我们看一下这张图的每一部分。首先,我们有两个量子位。每行对应一个量子位。顶行对应于名为 x0 的量子位,而底行对应于名为 x1 的量子位。我们认为 x0 是第 0 个量子位,因为我们从 0 开始计数(与编程的其余部分相同)。我们将x0 : ∣0⟩
和x1 : ∣0⟩
写成表示x0
和x1
从状态∣0⟩
开始。
H
是 Hadamard 门,被应用于量子位 x0。●-⊕
是 CNOT 门,●
是控制量子位,⊕
是目标量子位。-
只是帮助我们看到哪两个量子位受到影响。换句话说,我们正在应用 CNOT,其中控制是量子位 x0,目标是 x1。注意,我们应用这些门的顺序很重要。在这个图表中,我们首先应用了 H,然后应用了 CNOT。
翻译量子电路图
量子电路图只是我们程序的一种表示。它帮助我们思考我们的量子计算,但其他表示也可能是有用的。我们可以把我们的图表翻译成一串符号,这有助于我们准备把它写成计算机代码。以字符串的形式存在也使得它很容易转化为底层的数学。这个数学将告诉我们程序的预期输出。
让我们从将图表转换成一串符号开始。我们将使用 Bra-ket 符号,而不是将量子位写成行。第 0 个量子位将是∣00⟩
中最右边的量子位,就像写出二进制数时一样。这意味着量子位 x1 是∣00⟩
中最左边的量子位。(注意,量子物理的人倾向于颠倒这种顺序。总是检查量子位排序,因为它是 难以置信的 常见错误来源。)
我们还需要翻译大门。由于我们将H
应用于量子位 x0,而不对量子位 x1 应用任何东西(这相当于应用了身份门I
),我们将把它写成(I⊗H)
。最后,我们翻译 CNOT,指定哪个量子位是控制,哪个是目标。结果是CNOT[control=0, target=1] (I⊗H) ∣00⟩
(注意,这个字符串是从右向左读取的)。太好了!这在编写量子计算机上运行的代码时会很有用。
写出潜在的数学
有了量子电路图的字符串表示,就很容易把我们的程序翻译成底层的数学。有三件,CNOT[control=0, target=1]
、(I⊗H)
和∣00⟩
。每个片段都可以转换成矩阵,如下图的第一行所示:
我们甚至可以将矩阵相乘来找到结果状态向量,如上所示。这个状态向量就是量子计算完成后,我们两个量子位的预期状态。或者,我们可以认为它是我们程序的输出。它告诉我们每个可测状态的概率幅度。
还有,还记得我们的混合态量子比特吗?注意,我们不能再写纯态的量子位 x0 和 x1,因为没有办法用张量积分解矢量。所以我们的量子位处于混合状态!
测量状态向量
如果我们现在测量我们的量子位会怎么样?我们会收到什么?我们可以通过将状态向量分解成每个可测状态来找出答案。我们将在 标准基 中测量我们的量子位,也称为∣0⟩
和∣1⟩
(我们可以在其他基中测量,但现在不用担心)。因此,我们的两个量子位系统的可测量状态是∣00⟩
、∣01⟩
、∣10⟩
和∣11⟩
。
我们可以确定测量值的概率,就像我们 used|𝛼|确定单个量子位的∣0⟩
的概率一样。由于∣01⟩
和∣10⟩
的概率幅度为 0,我们知道我们永远无法测量那个状态。并且我们将以概率(1/sqrt(2)) = 1/2 来度量∣00⟩
和∣11⟩
。
现在,假设我们把这两个量子位分开一个很大的距离,然后我们测量其中一个。当我们测量它的时候,我们也会知道另一个量子位的值!这是因为我们知道量子位只能是∣00⟩
或者∣11⟩
。
这就是爱因斯坦所说的‘幽灵般的超距作用’,也被称为 量子纠缠 。我们认为信息是相互关联的,而不是相互传播的。如果它在旅行,那么它可能会比光速更快,这打破了物理定律。
运行在量子计算机上
现在我们已经了解了量子位、量子门和量子电路图的幕后发生的事情,让我们看看如何在真正的量子计算机上运行。我将使用 Rigetti 的量子计算机,因为他们目前正在向 beta 用户发放免费积分。或者,我们也可以使用 IBM 的量子计算机。
以下是 Rigetti 量子编程过程的基本概述:
- 写一个 Python 程序,指定你的量子电路和任何必要的附加代码
- 使用量子模拟器测试 Python 程序
- 在里盖蒂的量子计算机上预留时间
- 把你的程序发送到里盖蒂的服务器上
- 在 Rigetti 的服务器上执行你的程序(他们会把你的量子程序发给他们的量子计算机)
这是我们上面的量子电路图的 Python 版本。
结果将与此类似:
**[(0, 0), (1, 1), (1, 1), (0, 0), (0, 0), (0, 0), (1, 1), (0, 0), (0, 0), (1, 1)]
[(0, 0), (0, 1), (1, 1), (1, 1), (1, 1), (0, 0), (0, 0), (1, 1), (1, 0), (0, 0)]**
第一行对应于模拟器,结果似乎是合理的——大约一半时间我们得到[0,0],其余时间得到[1,1]。但是,用真正的量子计算机,除了预期的[0,0]和[1,1],我们还接收到[0,1]和[1,0]。根据数学,我们应该只接收[0,0]和[1,1],那么这是怎么回事呢?
问题是今天(2019 年 7 月)真正的量子计算机仍然很容易出错。⁴举例来说,当我们试图将量子位初始化为 0 时,我们可能会看到 2–3%的错误率。每一个单量子比特的门操作可能会有 1-2%的错误率,而两量子比特的门操作可能会有 3-4%的错误率。在测量量子位时,我们甚至有误差率!实际上,这些误差累积起来会导致不正确的值。
关闭
在这篇文章中,我们了解到量子计算机今天确实存在并工作,尽管错误率相当高。虽然这些机器的物理实现在不同的公司之间有很大的不同,但是对它们进行编程的许多概念是相同的。
我们认为量子位是两个单位长度的复数的向量,我们认为量子门是酉矩阵。我们记得量子计算是概率性的,因为两个相同的量子位一旦被测量就可能有不同的值。由于量子门是酉的,我们知道量子计算本质上是可逆的。在高层次上,我们可以将量子编程视为复数上的应用线性代数。
我们使用量子电路图来表示我们的量子程序,然后将其转换为 Python,以便在真实的量子计算机上运行。
我希望你学到了一些东西,我很高兴听到你的任何意见或建议!
常见问题解答
问:我用谷歌搜索了 CNOT 的矩阵表,它看起来和你的不一样,为什么?
a)如果你在看[[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]],这是因为他们颠倒了目标和控制量子位的排序。如果你看到的不是我在上面或者这篇文章里写的,那么它就是错的。
问:那么我们有了常规计算机的比特和三比特,量子比特是否存在类似的东西?
a)是的,qutrits。量子位是两能级量子系统的一部分。量子是三能级量子系统的一部分。还有 qudits,它概括了级别的数量。
参考
[1] L. Susskind,第一讲量子纠缠,第一部分 (2008)
[2]Qiskit 中的基向量排序 (2019),Qiskit
[3]r·史密斯,有人大喊“01000”!谁激动了? (2017),arxiv
[4] 量子比特质量 (2019),量子计算报告
推荐系统简介
原文:https://towardsdatascience.com/introduction-to-recommender-systems-6c66cf15ada?source=collection_archive---------0-----------------------
几种主要推荐算法综述。
Credit: StockSnap on Pixabay
本帖与 约瑟夫·罗卡 共同撰写。
介绍
在过去的几十年里,随着 Youtube、亚马逊、网飞和许多其他类似的网络服务的兴起,推荐系统在我们的生活中占据了越来越多的位置。从电子商务(向买家推荐他们可能感兴趣的文章)到在线广告(向用户推荐合适的内容,符合他们的偏好),推荐系统在我们日常的在线旅程中是不可避免的。
一般来说,推荐系统是一种算法,旨在向用户建议相关的项目(项目可以是要看的电影、要读的文本、要买的产品或任何其他取决于行业的东西)。
推荐系统在一些行业中非常重要,因为当它们有效时,可以产生大量的收入,或者是从竞争对手中脱颖而出的一种方式。作为推荐系统重要性的证明,我们可以提到,几年前,网飞组织了一次挑战(“网飞奖”),目标是产生一个比自己的算法性能更好的推荐系统,并赢得 100 万美元的奖金。
在这篇文章中,我们将介绍推荐系统的不同范例。对于它们中的每一个,我们将介绍它们是如何工作的,描述它们的理论基础并讨论它们的优点和缺点。
概述
在第一部分,我们将概述推荐系统的两个主要范例:协作和基于内容的方法。接下来的两节将描述各种各样的协同过滤方法,比如用户-用户、项目-项目和矩阵分解。下一节将专门介绍基于内容的方法及其工作原理。最后,我们将讨论如何评估一个推荐系统。
协作与内容
推荐系统的目的是向用户推荐相关的项目。为了完成这个任务,存在两大类方法:协同过滤方法和基于内容的方法。在深入研究特定算法的细节之前,让我们简单讨论一下这两个主要范例。
协同过滤方法
用于推荐系统的协作方法是仅基于用户和项目之间记录的过去交互来产生新推荐的方法。这些交互存储在所谓的“用户-项目交互矩阵”中。
Illustration of the user-item interactions matrix.
然后,规则协作方法的主要思想是,这些过去的用户-项目交互足以检测相似的用户和/或相似的项目,并基于这些估计的接*度做出预测。
协同过滤算法类分为两个子类别,一般称为基于记忆和基于模型的方法。基于记忆的方法直接与记录的交互值一起工作,假设没有模型,并且本质上基于最*邻居搜索(例如,从感兴趣的用户中找到最*的用户,并且在这些邻居中建议最受欢迎的项目)。基于模型的方法假设一个潜在的“生成”模型,该模型解释用户-项目交互并试图发现它以便做出新的预测。
Overview of the collaborative filtering methods paradigm.
协作方法的主要优点是它们不需要关于用户或项目的信息,因此,它们可以在许多情况下使用。此外,用户与项目的交互越多,新的推荐就越准确:对于一组固定的用户和项目,随着时间的推移记录的新交互会带来新的信息,并使系统越来越有效。
然而,由于它仅考虑过去的交互来进行推荐,协同过滤遭受“冷启动问题”:它不可能向新用户推荐任何东西或向任何用户推荐新项目,并且许多用户或项目具有太少的交互而不能被有效地处理。这个缺点可以用不同的方式来解决:向新用户推荐随机项目或者向随机用户推荐新项目(随机策略),向新用户推荐流行项目或者向最活跃的用户推荐新项目(最大期望策略),向新用户推荐一组各种项目或者向一组各种用户推荐新项目(探索策略),或者最后,在用户或者项目的早期使用非协作方法。
在下面的章节中,我们将主要介绍三种经典的协同过滤方法:两种基于记忆的方法(用户-用户和项目-项目)和一种基于模型的方法(矩阵分解)。
基于内容的方法
与仅依赖于用户-项目交互的协作方法不同,基于内容的方法使用关于用户和/或项目的附加信息。如果我们考虑电影推荐系统的例子,这个附加信息可以是例如用户的年龄、性别、工作或任何其他个人信息,以及电影(项目)的类别、主要演员、持续时间或其他特征。
然后,基于内容的方法的思想是试图建立一个模型,基于可用的“特征”,解释观察到的用户-项目交互。仍然考虑用户和电影,我们将尝试,例如,模拟年轻女性倾向于更好地评价一些电影,年轻男性倾向于更好地评价一些其他电影,等等。如果我们设法得到这样的模型,那么,为用户做出新的预测是相当容易的:我们只需要看看这个用户的个人资料(年龄、性别等),并根据这些信息,确定相关的电影建议。
Overview of the content based methods paradigm.
基于内容的方法比协作方法更少遭受冷启动问题:新用户或项目可以通过它们的特征(内容)来描述,因此可以为这些新实体提供相关建议。只有新用户或具有以前看不到的功能的项目才会在逻辑上遭受这种缺点,但是一旦系统足够老,这种情况就很少或没有机会发生。
在这篇文章的后面,我们将进一步讨论基于内容的方法,并看到,根据我们的问题,可以使用各种分类或回归模型,从非常简单到复杂得多的模型。
模型、偏差和方差
让我们更关注前面提到的方法之间的主要区别。更具体地说,让我们看看建模水*对偏差和方差的影响。
在基于记忆的协作方法中,没有假设潜在模型。该算法直接处理用户-项目交互:例如,用户通过他们与项目的交互来表示,并且使用对这些表示的最*邻搜索来产生建议。由于没有假设潜在模型,这些方法理论上具有低偏差但高方差。
在基于模型的协作方法中,假设了一些潜在的交互模型。该模型被训练成从其自己的用户和项目的表示来重建用户-项目交互值。然后可以根据这个模型提出新的建议。由该模型提取的用户和项目潜在表示具有人类难以解释的数学含义。由于假设了用户-项目交互的(相当自由的)模型,这种方法在理论上比假设没有潜在模型的方法具有更高的偏差但更低的方差。
最后,在基于内容的方法中,还假设了一些潜在的交互模型。然而,在这里,模型提供了定义用户和/或项目的表示的内容:例如,用户由给定的特征来表示,并且我们尝试为每个项目建模喜欢或不喜欢该项目的用户简档的种类。这里,对于基于模型的协作方法,假设了用户-项目交互模型。然而,该模型更受限制(因为用户和/或项目的表示是给定的),因此,该方法倾向于具有最高的偏差但最低的方差。
Summary of the different types of recommender systems algorithms.
基于记忆的协作方法
用户-用户和项目-项目的主要特征在于,它们仅使用来自用户-项目交互矩阵的信息,并且它们假设没有模型来产生新的推荐。
用户-用户
为了向用户做出新的推荐,用户-用户方法粗略地尝试识别具有最相似的“交互简档”(最*邻居)的用户,以便建议在这些邻居中最受欢迎的项目(并且对我们的用户来说是“新的”)。这种方法被称为“以用户为中心”,因为它基于用户与项目的交互来表示用户,并评估用户之间的距离。
假设我们想为一个给定的用户做推荐。首先,每个用户都可以通过其与不同项目的交互向量来表示(交互矩阵中的“其行”)。然后,我们可以计算我们感兴趣的用户和其他用户之间的某种“相似性”。该相似性度量使得对相同项目具有相似交互的两个用户应该被认为是接*的。一旦计算了与每个用户的相似性,我们可以保留与我们的用户最*的 k 个邻居,然后推荐其中最受欢迎的项目(只查看我们的参考用户还没有与之交互的项目)。
请注意,当计算用户之间的相似性时,“共同交互”的数量(多少项目已经被两个用户考虑过?)要慎重考虑!事实上,大多数时候,我们希望避免与我们的参考用户只有一个共同交互的人可能有 100%的匹配,并被认为比有 100 个共同交互并“只”同意其中 98%的人“更接*”。因此,我们认为两个用户是相似的,如果他们以相同的方式与许多共同的项目交互(相似的评级,相似的时间悬停…)。
Illustration of the user-user method. The same colour code will be used in the remaining of the post.
项目-项目
为了向用户进行新的推荐,项目-项目方法的思想是找到与用户已经“积极地”交互过的项目相似的项目。如果与两个项目交互的大多数用户以相似的方式进行交互,那么这两个项目被认为是相似的。这种方法被称为“以项目为中心”,因为它基于用户与项目的交互来表示项目,并评估这些项目之间的距离。
假设我们想为一个给定的用户做推荐。首先,我们考虑这个用户最喜欢的项目,并通过它与每个用户的交互向量(交互矩阵中的“它的列”)来表示它(和所有其他项目一样)。然后,我们可以计算“最佳项目”和所有其他项目之间的相似性。一旦计算出相似性,我们就可以保留对我们感兴趣的用户来说是新的所选“最佳项目”的 k 个最*邻居,并推荐这些项目。
请注意,为了获得更多相关的推荐,我们可以不仅仅针对用户最喜欢的项目进行这项工作,而是考虑 n 个首选项目。在这种情况下,我们可以推荐与这些首选项目中的几个接*的项目。
Illustration of the item-item method.
比较用户-用户和项目-项目
用户-用户方法基于在与项目的交互方面搜索相似的用户。因为,一般来说,每个用户只与几个项目交互,这使得该方法对任何记录的交互非常敏感(高方差)。另一方面,由于最终推荐仅基于为与我们感兴趣的用户相似的用户记录的交互,所以我们获得了更个性化的结果(低偏差)。
相反,条目-条目方法基于在用户-条目交互方面搜索相似条目。一般来说,由于许多用户已经与一个项目进行了交互,所以邻域搜索对单个交互的敏感度要低得多(方差更低)。作为对应,来自各种用户(甚至是与我们的参考用户非常不同的用户)的交互在推荐中被考虑,使得该方法不那么个性化(更有偏见)。因此,这种方法没有用户对用户的方法那么个性化,但是更加健壮。
Illustration of the difference between item-item and user-user methods.
复杂性和副作用
基于记忆的协同过滤的最大缺陷之一是它们不容易扩展:对于大型系统来说,生成一个新的推荐是非常耗时的。事实上,对于具有数百万用户和数百万项目的系统,如果不仔细设计,最*邻居搜索步骤会变得难以处理(KNN 算法的复杂度为 O(ndk ),其中 n 是用户数量,d 是项目数量,k 是考虑的邻居数量)。为了使大型系统的计算更易处理,我们可以在设计算法时利用交互矩阵的稀疏性,或者使用*似最*邻方法(ANN)。
在大多数推荐算法中,有必要非常小心,以避免流行项目的“越来越丰富”效应,并避免让用户陷入所谓的“信息限制区”。换句话说,我们不希望我们的系统倾向于推荐越来越多的流行项目,我们也不希望我们的用户只收到与他们已经喜欢的项目非常接*的项目的推荐,而没有机会了解他们可能也喜欢的新项目(因为这些项目不够“接*”以至于不能被建议)。正如我们提到的,如果这些问题会出现在大多数推荐算法中,那么对于基于记忆的协作算法来说尤其如此。事实上,由于缺乏“规范化”的模式,这种现象可能会更频繁地被强调和观察。
基于模型的协作方法
基于模型的协作方法仅依赖于用户-项目交互信息,并假设一个潜在模型来解释这些交互。例如,矩阵分解算法包括将庞大且稀疏的用户-项目交互矩阵分解成两个更小且密集的矩阵的乘积:用户因素矩阵(包含用户表示)乘以因素-项目矩阵(包含项目表示)。
矩阵分解
矩阵分解背后的主要假设是,存在一个非常低维的特征潜在空间,其中我们可以表示用户和项目,并且用户和项目之间的交互可以通过计算该空间中相应密集向量的点积来获得。
例如,考虑我们有一个用户电影评级矩阵。为了对用户和电影之间的交互进行建模,我们可以假设:
- 存在一些很好地描述(和区分)电影的特征。
- 这些特征也可以用于描述用户偏好(高值表示用户喜欢的特征,低值表示用户不喜欢)
然而,我们不想给我们的模型显式地提供这些特性(因为对于我们将在后面描述的基于内容的方法,这是可以做到的)。相反,我们更喜欢让系统自己发现这些有用的特性,并对用户和项目做出自己的表示。由于它们是习得的而不是给定的,单独提取的特征具有数学意义,但没有直观的解释(因此,很难(如果不是不可能的话)被人类理解)。然而,从这种算法中产生的结构非常接*人类可以想到的直觉分解,这并不罕见。事实上,这种分解的结果是,就偏好而言接*的用户以及就特征而言接*的项目最终在潜在空间中具有接*的表示。
Illustration of the matrix factorization method.
矩阵分解的数学
在这一小节中,我们将给出矩阵分解的一个简单的数学概述。更具体地说,我们描述了一种基于梯度下降的经典迭代方法,这种方法可以获得非常大的矩阵的分解,而无需将所有数据同时加载到计算机的存储器中。
让我们考虑评级的交互矩阵 M (nxm ),其中只有一些项目被每个用户评级(大多数交互被设置为无以表示缺少评级)。我们想分解这个矩阵
其中 X 是“用户矩阵”(nxl),其行代表 n 个用户,Y 是“项目矩阵”(mxl),其行代表 m 个项目:
这里 l 是潜在空间的维度,其中用户和项目将被表示。因此,我们寻找矩阵 X 和 Y,它们的点积最接*现有的相互作用。表示 E 对(I,j)的系综,使得 M_ij 被设置(不是没有),我们想要找到最小化“评级重构误差”的 X 和 Y
添加正则化因子并除以 2,我们得到
矩阵 X 和 Y 可以通过梯度下降优化过程获得,我们可以注意到两件事。首先,不必在每一步计算 E 中所有对的梯度,我们可以只考虑这些对的一个子集,这样我们可以“分批”优化我们的目标函数。第二,X 和 Y 中的值不必同时更新,梯度下降可以在每一步在 X 和 Y 上交替进行(这样做时,我们认为一个矩阵是固定的,并在下一次迭代中进行相反的操作之前为另一个矩阵进行优化)。
一旦矩阵被因式分解,我们就有更少的信息来操作以做出新的推荐:我们可以简单地将用户向量乘以任何项目向量,以估计相应的评级。请注意,我们还可以使用用户-用户和项目-项目方法来表示用户和项目:(*似)最*邻搜索不会在巨大的稀疏向量上进行,而是在小的密集向量上进行,这使得一些*似技术更容易处理。
矩阵分解的扩展
我们最终可以注意到,这种基本分解的概念可以扩展到更复杂的模型,例如,更通用的神经网络,如“分解”(我们不能再严格地谈论“分解”)。我们能想到的第一种直接适应关系到布尔交互。如果我们想要重建布尔交互,简单的点积并不适合。然而,如果我们在点积的基础上添加一个逻辑函数,我们会得到一个取值为[0,1]的模型,因此,更适合这个问题。在这种情况下,要优化的模型是
用 f(。)我们的后勤职能。在复杂的推荐系统中,更深层次的神经网络模型经常被用来实现接*现有技术水*的性能。
Matrix factorization can be generalized with the use of a model on top of users and items embeddings.
基于内容的方法
在前两节中,我们主要讨论了用户-用户、项目-项目和矩阵分解方法。这些方法仅考虑用户-项目交互矩阵,因此属于协同过滤范例。现在让我们描述一下基于内容的范例。
基于内容的方法的概念
在基于内容的方法中,推荐问题被分为分类问题(预测用户是否“喜欢”某个项目)或回归问题(预测用户对某个项目的评分)。在这两种情况下,我们都将设置一个基于用户和/或项目特征的模型(我们的“基于内容”方法的“内容”)。
如果我们的分类(或回归)是基于用户的特征,我们说这种方法是以项目为中心的:建模、优化和计算可以“按项目”进行。在这种情况下,我们基于用户特征逐个项目地构建和学习一个模型,试图回答“每个用户喜欢这个项目的概率是多少?”(或者“每个用户给这个物品的评分是多少?”,用于回归)。与每个项目相关联的模型自然地在与该项目相关的数据上被训练,并且一般来说,它导致相当健壮的模型,因为许多用户已经与该项目进行了交互。然而,被考虑来学习模型的交互来自每个用户,并且即使这些用户具有相似的特性(特征),他们的偏好也可能不同。这意味着,即使这种方法更健壮,它也可以被认为比以用户为中心的方法更不个性化(更有偏见)。
如果我们正在处理项目特征,那么这个方法就是以用户为中心的:建模、优化和计算可以由“用户”来完成。然后,我们根据项目特征按用户训练一个模型,试图回答问题“这个用户喜欢每个项目的概率是多少?”(或者“这个用户给每个项目的评分是多少?”,用于回归)。然后,我们可以为每个接受数据训练的用户建立一个模型:由于该模型只考虑了被考虑用户的互动,因此比以商品为中心的模型更加个性化。然而,大多数时候,用户与相对较少的项目进行交互,因此,我们获得的模型远不如以项目为中心的模型健壮。
Illustration of the difference between item-centred and user-centred content based methods.
从实践的角度来看,我们应该强调的是,在大多数情况下,向新用户询问一些信息(用户不想回答太多问题)比询问大量关于新项目的信息(添加他们的人有兴趣填写这些信息,以便将他们的项目推荐给正确的用户)要困难得多。我们还可以注意到,根据要表达的关系的复杂性,我们建立的模型可以或多或少地复杂,范围从基本模型(用于分类/回归的逻辑/线性回归)到深度神经网络。最后,让我们提一下,基于内容的方法也可以既不以用户为中心也不以项目为中心:关于用户和项目的信息都可以用于我们的模型,例如通过堆叠两个特征向量并使它们通过神经网络架构。
以项目为中心的贝叶斯分类器
让我们首先考虑以项目为中心的分类的情况:对于每个项目,我们希望训练一个贝叶斯分类器,它将用户特征作为输入,输出“喜欢”或“不喜欢”。因此,为了完成分类任务,我们需要计算
具有给定特征的用户喜欢所考虑的项目的概率和不喜欢它的概率之间的比率。定义我们的分类规则(具有简单阈值)的条件概率的比率可以按照贝叶斯公式来表示
在哪里
先验是从数据中计算出来的
假设可能性遵循高斯分布,参数也由数据确定。可以对这两种似然分布的协方差矩阵进行各种假设(无假设、矩阵相等、矩阵相等和特征独立),从而产生各种众所周知的模型(二次判别分析、线性判别分析、朴素贝叶斯分类器)。我们可以再次强调,在这里,可能性参数必须仅基于与所考虑的项目相关的数据(相互作用)来估计。
Illustration of the item-centred content based Bayesian classifier.
用户为中心的线性回归
现在让我们考虑以用户为中心的回归的情况:对于每个用户,我们希望训练一个简单的线性回归,它将项目特征作为输入,并输出该项目的评级。我们仍然将 M 表示为用户-项目交互矩阵,我们将表示要学习的用户系数的 X 行向量堆叠成矩阵,并将表示给定项目特征的 Y 行向量堆叠成矩阵。然后,对于给定的用户 I,我们通过求解以下优化问题来学习 X_i 中的系数
我们应该记住,I 是固定的,因此,第一次求和只针对与用户 I 相关的(用户,项目)对。我们可以观察到,如果我们同时为所有用户解决这个问题,优化问题与我们在“交替矩阵分解”中解决的问题完全相同,当我们保持项目固定时。这种观察强调了我们在第一部分中提到的联系:基于模型的协作过滤方法(例如矩阵分解)和基于内容的方法都假设用户-项目交互的潜在模型,但是基于模型的协作方法必须学习用户和项目的潜在表示,而基于内容的方法基于用户和/或项目的人类定义的特征建立模型。
Illustration of the user-centred content based regression.
推荐系统的评价
至于任何机器学习算法,我们需要能够评估我们的推荐系统的性能,以便决定哪个算法最适合我们的情况。推荐系统的评价方法主要可以分为两类:基于良好定义的度量的评价和主要基于人的判断和满意度估计的评价。
基于度量的评估
如果我们的推荐系统是基于输出数值的模型,例如评级预测或匹配概率,我们可以使用误差测量度量,例如均方误差(MSE ),以非常经典的方式评估这些输出的质量。在这种情况下,模型仅在一部分可用的交互上被训练,并在剩余的交互上被测试。
然而,如果我们的推荐系统基于预测数值的模型,我们也可以用经典的阈值方法将这些值二进制化(阈值以上的值为正,阈值以下的值为负),并以更“分类的方式”评估模型。事实上,由于用户-项目过去交互的数据集也是二进制的(或者可以通过阈值化来二进制化),因此我们可以在不用于训练的交互的测试数据集上评估模型的二进制化输出的准确性(以及精度和召回率)。
最后,如果我们现在考虑一个不基于数值的推荐系统,它只返回一个推荐列表(例如基于 knn 方法的用户-用户或项目-项目),我们仍然可以通过估计真正适合我们用户的推荐项目的比例来定义一个类似精度的度量。为了估计这个精度,我们不能考虑用户没有与之交互的推荐项目,我们应该只考虑来自测试数据集中有用户反馈的项目。
基于人的评估
在设计推荐系统时,我们感兴趣的不仅仅是获得能够产生我们非常确定的推荐的模型,我们还可以期待其他一些好的特性,比如推荐的多样性和可解释性。
正如在协作部分提到的,我们绝对希望避免让用户陷入我们之前称之为信息封闭的区域。“意外发现”的概念经常被用来表达一个模型有或没有创建这样一个限制区域的趋势(推荐的多样性)。可以通过计算推荐项目之间的距离来估计的意外收获,不应该太低,因为这会产生限制区域,但也不应该太高,因为这意味着我们在进行推荐时没有充分考虑用户的兴趣(探索与开发)。因此,为了在建议的选择中带来多样性,我们想要推荐既非常适合我们的用户又彼此不太相似的项目。例如,与其向用户推荐“开始战争”1、2 和 3,不如推荐“星球大战 1”、“开始黑暗之旅”和“印第安纳琼斯和夺宝奇兵”:后两者可能会被我们的系统视为用户不太感兴趣,但推荐看起来太相似的 3 个项目并不是一个好的选择。
可解释性是推荐算法成功的另一个关键点。事实上,已经证明,如果用户不理解他们为什么被推荐为特定项目,他们倾向于对推荐系统失去信心。因此,如果我们设计了一个可以清楚解释的模型,我们可以在推荐时添加一个小句子,说明为什么推荐了一个项目(“喜欢这个项目的人也喜欢这个”,“你喜欢这个项目,你可能会对这个项目感兴趣”,…)。
最后,除了多样性和可解释性本质上难以评估的事实之外,我们可以注意到,评估不属于测试数据集的推荐的质量也是相当困难的:如何在实际向用户推荐之前知道一个新的推荐是否相关?出于所有这些原因,在“真实条件”下测试模型有时会很有诱惑力。由于推荐系统的目标是生成一个动作(看电影、购买产品、阅读文章等),我们确实可以评估它生成预期动作的能力。例如,系统可以按照 A/B 测试方法投入生产,或者可以只在用户样本上进行测试。然而,这种过程要求对模型有一定程度的信心。
外卖食品
这篇文章的主要观点是:
- 推荐算法可以分为两大类:仅基于用户-项目交互矩阵的协作方法(如用户-用户、项目-项目和矩阵分解)和使用关于用户和/或项目的先验信息的基于内容的方法(如回归或分类模型)
- 基于记忆的协作方法不假设任何潜在模型,因此具有低偏差但高方差;基于模型的协作方法假设一个潜在的交互模型,该模型需要从零开始学习用户和项目表示,因此具有较高的偏差但较低的方差;基于内容的方法假设围绕明确给出的用户和/或项目特征建立潜在的模型,因此具有最高的偏差和最低的方差
- 推荐系统在许多大型行业中越来越重要,在设计系统时必须考虑一些规模因素(更好地使用稀疏性、因子分解或优化的迭代方法、最*邻搜索的*似技术……)
- 推荐系统很难评估:如果可以使用一些经典的度量标准,如 MSE、准确度、召回率或精确度,人们应该记住一些期望的属性,如多样性(意外发现)和可解释性不能以这种方式评估;真实条件评估(如 A/B 测试或样本测试)最终是评估新推荐系统的唯一真实方式,但需要对模型有一定的信心
我们应该注意到,在这篇介绍性的文章中,我们没有讨论混合方法。这些方法结合了协同过滤和基于内容的方法,在许多情况下获得了最先进的结果,并且因此被用在当今许多大规模推荐系统中。在混合方法中进行的组合可以主要采取两种形式:我们可以独立地训练两个模型(一个协作过滤模型和一个基于内容的模型)并组合它们的建议,或者通过使用先验信息(关于用户和/或项目)以及“协作”交互信息作为输入来直接构建统一两种方法的单个模型(通常是神经网络)。
正如我们在这篇文章的引言中提到的,推荐系统在许多行业中变得越来越重要,因此,在最*几年里受到了越来越多的关注。在本文中,我们介绍了更好地理解与这些系统相关的问题所需的基本概念,但我们强烈鼓励感兴趣的读者进一步探索这一领域…讽刺的是,没有给出任何具体的阅读建议!
感谢阅读!
与约瑟夫·罗卡一起写的最后一篇文章:
[## 整体方法:装袋、助推和堆叠
理解集成学习的关键概念。
towardsdatascience.com](/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205) [## 马尔可夫链简介
定义、属性和 PageRank 示例。
towardsdatascience.com](/brief-introduction-to-markov-chains-2c8cab9c98ab)
恐龙递归神经网络(RNN)简介
原文:https://towardsdatascience.com/introduction-to-recurrent-neural-networks-rnn-with-dinosaurs-790e74e3e6f6?source=collection_archive---------18-----------------------
了解关于 RNNs 的一切,并构建一个恐龙名称生成器
Photo by Daiga Ellaby on Unsplash
递归神经网络(RNN)是称为序列模型的更大算法组的一部分。序列模型在语音识别、音乐生成、DNA 序列分析、机器翻译等领域取得了巨大的进步。
在这篇文章中,介绍了 RNN 的理论,我们将通过建立一个能产生新恐龙名字的模型来巩固一切。
我们走吧!
对于机器学习、深度学习和人工智能的实践视频教程,请查看我的 YouTube 频道。
Now, that’s a specie I don’t know about…
为什么要使用递归神经网络?
假设你想建立一个神经网络来识别句子中的人名。
在这种情况下,传统的神经网络不适合这种类型的应用。首先,输入和输出不会有相同的长度,因为一个人的名字可能有很大的不同。第二,学习到的特征不会在文本的不同位置共享,导致低于标准的性能。
这就是为什么 rnn 非常受序列数据的欢迎,比如句子或音乐。
一种递归神经网络的结构
在 RNN 中,输入被馈送到网络的一个层,并且它输出预测。然后,第二输入被馈送到另一层,并且网络输出预测。然而,它也使用从前一层计算的信息。
重复该过程,直到获得最终输出。
因此,典型的 RNN 看起来是这样的:
Left: folded schema of an RNN. Right: unfolded schema of an RNN. Source
这种结构允许 rnn 将信息从早期步骤链接到当前步骤。然而,如果 RNN 很深,意味着它有许多层,它将容易出现消失或爆发渐变。
当渐变接* 0 时,渐变消失,因此权重不再更新。另一方面,爆炸梯度是当梯度太大时,并且永远不会达到优化函数的全局最小值。当然,有办法防止爆炸和消失的梯度,我们会看到当我们编码一个 RNN。
对 RNN 进行编码以生成新的恐龙名称
概观
现在,我们将使用 Python 编写一个 RNN,它将为我们生成新的恐龙名称。我们将学习如何:
- 存储文本数据,并使用 RNN 对其进行处理
- 如何合成数据
- 如何生成文本
- 如何裁剪渐变以避免渐变爆炸
我们的 RNN 将会是这样的:
RNN schema. Source
当然,如果你想继续写代码的话,可以使用全笔记本。您还将找到复制结果所需的所有实用工具。
步骤 1:导入库并浏览数据集
我们首先导入必要的库和实用程序,并查看我们将使用的数据。
你应该看到我们有相当多的恐龙名字,我们也有 27 个独特的角色。它们对应于字母表中的每个字母,我们有一个特殊的字符“\n”来定义一个新行。这将是我们的句尾字符( EOS )。
步骤 2:定义渐变裁剪函数
如前所述,rnn 容易消失或爆炸梯度,所以我们将实现梯度裁剪,以防止梯度“爆炸”。
渐变裁剪非常简单:如果计算出的渐变大于某个阈值,我们将它缩放回阈值。否则,我们就让它保持原样。像这样,我们将确保我们的优化函数会收敛。
Gradient descent with and without clipping. Source
在代码中:
步骤 3:定义采样函数
一旦我们的模型被训练,我们将需要一个函数来选择最有可能生成一个似乎合理的恐龙名字的角色。
换句话说,它需要从字符库中抽取一个字符并生成一个单词。
在代码中:
步骤 4:构建模型
现在,我们准备好构建模型了。首先,我们实现一个函数,该函数执行带有梯度裁剪的随机梯度下降的一个步骤:
完美!现在我们可以编写并训练我们的模型:
现在,我们只需要运行下面的单元格来获得新的恐龙名称:
parameters = model(data, ix_to_char, char_to_ix)
你应该看到算法在生成更可信的恐龙名字方面变得越来越好。我得到的几个例子是:
- Trokalenator
- 尼沃龙
- 卢特龙
如果您有更多的时间和计算能力,请随意调整模型并训练它更长时间,因为它应该会生成更好的名称。
就是这样!您学习了 RNNs 的基础知识,并应用它们来生成新的恐龙名称!
在未来的帖子中,我们将讨论长短期记忆(LSTM)单位,这是另一种类型的循环网络,我们将生成爵士乐。
敬请期待!
来源: Deeplearning.ai
强化学习简介—第 1 章
原文:https://towardsdatascience.com/introduction-to-reinforcement-learning-chapter-1-fc8a196a09e8?source=collection_archive---------16-----------------------
RLBook 的章节摘要。
Fig 1. Toons talking about Reinforcement Learning
这是从一本最流行的强化学习书中摘出的一章,作者是 理查德·萨顿 和 安德鲁·g·巴尔托 ( 第二版)。书可以在这里找到: 链接 。
强化学习是学习做什么——如何将情况映射到行动——以便最大化数字奖励信号。学习代理可以采取影响环境状态的行动,并且具有与环境状态相关的目标。强化学习中出现的挑战之一,而不是其他类型的学习,是探索和利用之间的权衡。在所有形式的机器学习中,强化学习是最接*人类和其他动物所做的学习。
强化学习的要素
除了 代理 和 环境 之外,人们可以识别 RL 的四个主要子元素
- 策略— 是从感知的环境状态到处于这些状态时要采取的行动的映射。策略是强化学习代理的核心,因为它本身就足以决定行为。它可能是随机的,规定了每个动作的概率。
- 奖励— 在每个时间步上,环境向强化学习代理发送一个称为奖励的单一数字。代理人的唯一目标是最大化其长期获得的总回报。因此,回报信号定义了对代理人来说什么是好信号,什么是坏信号。它可能是状态和行为的随机函数。
- 价值函数— 粗略地说,一个状态的价值就是一个主体从那个状态开始,在未来可以期望积累的报酬总额。奖励决定了环境状态的直接的、内在的可取性,而值在考虑了可能发生的状态和这些状态中可用的奖励之后,指示了状态的长期可取性。例如,一个州可能总是产生较低的即时奖励,但仍然有很高的价值,因为它经常被产生高奖励的其他州跟随,或者相反。
- 环境模型— 这模仿了环境的行为,允许对环境将如何表现做出推断。例如,给定一个状态和一个动作,模型可以预测下一个状态和下一个奖励。使用模型解决强化学习问题的方法称为基于模型的方法,与更简单的无模型方法,即试错学习器相对。
从某种意义上说,回报是第一位的,而作为回报预测的价值是第二位的。没有回报就没有价值,评估价值的唯一目的是为了获得更多的回报。然而,在做决策和评估决策时,我们最关心的是价值观。
一个例子:井字游戏
Fig 2. Sequence of Tic-Tac-Toe Moves
解决井字游戏的强化学习方法;
- 建立一个数字表,每个数字代表一种可能的游戏状态。
- 每一个数字都是我们对该州获胜概率的最新估计。
- 这个估计值就是状态的 值 ,整个表就是学习值函数。
- 假设我们总是玩 x,那么对于一行(列和对角线)中有 3 个 x 的所有状态,获胜的概率是 1.0
- 对于一行(列和对角线)中有 3 个 0 的所有州,获胜的概率是 0.0
- 我们将所有其他状态的初始值设置为 0.5 (表示我们有 50%的胜算。)
然后我们和对手打很多场比赛。要选择我们的行动:
- 我们检查每个可能的移动所产生的状态,并在表中查找它们的当前值。
- 大多数时候,我们贪婪地行动,选择能带来最大价值的行动。(最高中奖概率)
- 偶尔,我们会从其他动作中随机选择。(探索)
玩的时候,我们会改变自己所处状态的价值观:
- 在每次贪婪的移动之后,从 A 到 B,我们更新 A 的值以更接* B 的值。
- 这是通过以下公式实现的
Fig 3. Temporal Difference Learning Update
其中,
【S _ t】—旧状态的值,贪心移动前的状态(A) V(S _ t+1)—新状态的值,贪心移动后的状态(B) alpha—学习率
这个更新规则是 时间差异学习 方法的一个例子,这样称呼是因为它的变化是基于两个连续时间的估计值之间的差异V(S_t+1) — V(S_t)
。
感谢阅读!如果我从书中发现一些需要提及的见解,我会更新。
强化学习:马尔可夫决策过程(上)
原文:https://towardsdatascience.com/introduction-to-reinforcement-learning-markov-decision-process-44c533ebf8da?source=collection_archive---------0-----------------------
#InsideRL
在一个典型的强化学习(RL)问题中,有一个学习者和一个决策者,称为代理,与其交互的环境称为环境。作为回报,环境基于代理的动作提供奖励和一个新状态。因此,在强化学习中,我们不教代理应该如何做某事,而是根据它的行为给它奖励,无论是积极的还是消极的。所以我们这个博客的根本问题是,我们如何用数学方法来表述 RL 中的任何问题。这就是马尔可夫决策过程(MDP)的用武之地。
Typical Reinforcement Learning cycle
在我们回答我们的根本问题之前,即我们如何用数学方法(使用 MDP)表述 RL 问题,我们需要发展我们对以下问题的直觉:
- 代理-环境关系
- 马尔可夫性质
- 马尔可夫过程和马尔可夫链
- 马尔可夫奖励过程(MRP)
- 贝尔曼方程
- 马尔可夫奖励过程
拿起你的咖啡,直到你感到自豪才停下来!🧐
代理-环境关系
首先让我们看看一些正式的定义:
代理:做出智能决策的软件程序,它们是 RL 中的学习者。这些代理通过行动与环境互动,并根据他们的行动获得奖励。
环境:是待解决问题的演示。现在,我们可以有一个真实世界的环境或一个模拟的环境,我们的代理将与它进行交互。
Demonstrating an environment with which agents are interacting.
状态:这是代理在环境中特定时间步的位置。因此,每当代理执行一个动作时,环境给予代理奖励和代理通过执行该动作所达到的新状态。
代理不能任意改变的任何东西都被认为是环境的一部分。简单来说,动作可以是我们希望代理学习的任何决定和状态可以是在选择动作时有用的任何东西。我们并不假设环境中的一切对代理人来说都是未知的,例如,奖励计算被认为是环境的一部分,即使代理人知道一点它的奖励是如何作为它的动作和状态的函数来计算的。这是因为奖励不能由代理人任意更改。有时,代理人可能完全知道其环境,但仍然发现很难最大化奖励,就像我们可能知道如何玩魔方,但仍然无法解决它。因此,我们可以有把握地说,代理-环境关系代表了代理控制的极限,而不是它的知识。
马尔可夫性质
跃迁:从一种状态转移到另一种状态叫做跃迁。
转移概率:智能体从一种状态转移到另一种状态的概率称为转移概率。
中的 马氏性 表述为:
“鉴于现在,未来独立于过去”
从数学上讲,我们可以将这一陈述表达为:
Markov Property
S[t]表示代理的当前状态,s[t+1]表示下一个状态。这个等式的意思是,从状态 S[t]到 S[t+1]的转变完全独立于过去。因此,如果系统具有马尔可夫性质,方程的 RHS 与 LHS 的含义相同。直观上意味着我们的当前状态已经捕获了过去状态的信息。
状态转移概率:
现在我们知道了转移概率,我们可以将状态转移概率定义如下:
对于从 S[t]到 S[t+1]的马尔可夫状态,即任何其他后续状态,状态转移概率由下式给出
State Transition Probability
我们可以通过以下方式将状态转移概率公式化为状态转移概率矩阵:
State Transition Probability Matrix
矩阵中的每一行代表从我们的原始或开始状态移动到任何后续状态的概率。每行的总和等于 1。
马尔可夫过程或马尔可夫链
马尔可夫过程是记忆较少的 随机过程 即一个随机状态的序列 S[1],S[2],…。S[n]具有马尔可夫性质。所以,它基本上是一个具有马尔可夫性质的状态序列。它可以用一组状态(S)和转移概率矩阵(P)来定义。使用状态(S)和转移概率矩阵(P)可以完全定义环境的动态。
但是 随机过程 是什么意思呢?
为了回答这个问题,我们来看一个例子:
Markov chain
树的边表示转移概率。让我们从这个链条上取一些样品。现在,假设我们在睡觉,根据概率分布,有 0.6%的几率我们会跑,0.2%的几率我们会睡得更久,0.2%的几率我们会吃冰淇淋。类似地,我们可以从这条链中提取其他序列。
来自链条的一些样品:
- 睡觉——跑步——冰淇淋——睡觉
- 睡眠——冰淇淋——冰淇淋——奔跑
在上面的两个序列中,我们看到的是,每次运行链时,我们都会得到一组随机的状态(即睡眠、冰淇淋、睡眠)。霍普,现在清楚了为什么马尔可夫过程被称为随机序列集。
在进入马尔可夫奖励流程之前,让我们先来看一些有助于理解 MRP 的重要概念。
奖励和回报
奖励是代理在环境中的某个状态下执行某个动作时收到的数值。根据代理的动作,数值可以是正的,也可以是负的。
在强化学习中,我们关心的是最大化累积奖励(代理从环境中获得的所有奖励)而不是,代理从当前状态获得的奖励(也称为即时奖励)。这个代理人从环境中得到的报酬的总和称为回报。
我们可以将回报定义为:
Returns (Total rewards from the environment)
r[t+1]是代理在时间步长 t[0]执行从一个状态移动到另一个状态的动作(a)时收到的奖励。类似地,r[t+2]是代理在时间步长 t[1]通过执行移动到另一个状态的动作而收到的奖励。r[T]是代理在最后一个时间步通过执行移动到另一个状态的动作而收到的奖励。
间断和连续任务
偶发任务:这些任务有一个终止状态(结束状态)。我们可以说它们有有限的状态。比如赛车游戏,我们开始游戏(开始比赛),一直玩到游戏结束(比赛结束!).这叫插曲。一旦我们重启游戏,它将从初始状态开始,因此,每一集都是独立的。
连续任务:没有结束的任务,即没有任何终止状态。这些类型的任务将永不结束。比如学习如何编码!
现在,很容易计算出阶段性任务的回报,因为它们最终会结束,但连续任务呢,因为它会一直持续下去。从求和到无穷大的收益!那么,我们如何定义连续任务的回报呢?
这就是我们需要贴现 factor(ɤ) 的地方。
贴现因子(ɤ) :决定当前奖励和未来奖励的重要性的大小。这基本上帮助我们避免无穷大作为连续任务中的奖励。它的值介于 0 和 1 之间。值 0 意味着给予即时奖励更大的重要性,值 1 意味着给予未来奖励更大的重要性。在实践中,折扣系数 0 永远不会学习,因为它只考虑即时奖励,而折扣系数 1 将继续用于未来奖励,这可能导致无穷大。因此,折扣系数的最佳值在 0.2 到 0.8 之间。
因此,我们可以使用贴现因子定义回报如下:(假设这是等式 1,因为我们稍后将使用该等式来推导贝尔曼等式)
Returns using discount factor
让我们用一个例子来理解它,假设你住在一个面临水资源短缺的地方,如果有人来找你,说他会给你 100 升水!(请假设!)作为某个参数的函数( ɤ) 。让我们看看两种可能性:(假设这是等式 1,因为我们将在后面使用这个等式来推导贝尔曼等式)
一个带有折扣系数( ɤ) 0.8 :
Discount Factor (0.8)
这意味着我们应该等到第 15 个小时,因为下降不是非常显著,所以直到最后仍然是值得的。这意味着我们也对未来的回报感兴趣。所以,如果贴现因子接* 1,那么我们将努力达到终点,因为奖励非常重要。
二、用贴现因子( ɤ) 0.2 :
Discount Factor (0.2)
这意味着我们对早期的奖励更感兴趣,因为奖励在第一小时变得非常低。所以,我们可能不想等到最后(直到第 15 个小时),因为这将是毫无价值的。因此,如果贴现因子接*于零,那么眼前的回报比未来更重要。
那么使用哪个折扣系数值呢?
这取决于我们想要训练代理的任务。假设,在一盘棋中,目标是击败对手的王。如果我们重视直接的奖励,如棋子击败任何对手的奖励,那么代理人将学习执行这些子目标,不管他的玩家是否也被击败。所以,在这个任务中,未来的回报更重要。在某些情况下,我们可能更喜欢使用即时奖励,就像我们之前看到的水的例子一样。
马尔可夫奖励过程
到目前为止,我们已经看到马尔可夫链是如何使用状态集(S)和转移概率矩阵(P)来定义环境的动态性的。但是,我们知道强化学习的目的是最大化回报。所以,让我们把 加奖励 到我们的马尔可夫链中。这给了我们马尔科夫的奖励过程。
马尔可夫奖励过程:顾名思义,MDP 就是有价值判断的马尔可夫链。基本上,我们从代理所处的每个状态中获取一个值。
在数学上,我们将马尔可夫奖励过程定义为:
Markov Reward Process
这个等式的意思是我们从一个特定的状态 S[t]中得到多少奖励(Rs)。这告诉我们,从我们的代理所处的特定状态中可以得到直接的回报。正如我们将在下一个故事中看到的,我们如何从我们的代理所处的每个状态中最大化这些奖励。简单来说,最大化我们从每个州获得的累积奖励。
我们将 MRP 定义为(标准普尔,R,ɤ),其中:
- s 是一组状态,
- p 是转移概率矩阵,
- r 是奖励函数,我们之前看到过,
- ɤ是贴现因子
马尔可夫决策过程
现在,让我们发展对贝尔曼方程和马尔可夫决策过程的直觉。
政策功能和价值功能
价值函数决定了代理处于某个特定状态有多好。当然,要确定一个特定的状态有多好,必须依赖于它将要采取的一些行动。这就是政策发挥作用的地方。策略定义了在特定状态下要执行的操作。
策略是一个简单的函数,它为每个状态(s ∈ S)定义了动作(a∈ A)的概率分布。如果代理在时间 t 遵循策略π,那么 π(a|s) 是代理在特定时间步长(t)采取行动(a)的概率。在强化学习中,代理人的经验决定了策略的变化。数学上,策略定义如下:
Policy Function
现在,我们如何找到一个状态的值。当代理人遵循 vπ(s)表示的策略π时,状态 s 的值是从 s 开始并遵循下一个状态的策略π直到到达终端状态的期望收益。我们可以将其公式化为:(该函数也称为状态值函数)
Value Function
这个等式给出了从状态开始到后续状态的预期收益,策略为π。需要注意的一点是,我们得到的回报是随机的,而一个状态的价值是而不是随机的。它是从起始状态 s 到任何其它状态的期望收益。还要注意,终端状态的值(如果有的话)是零。让我们看一个例子:
Example
假设我们的开始状态是类 2,我们移动到类 3,然后通过,然后睡眠。简而言之,二班>三班>及格>睡觉。
我们的预期回报是 0.5 的贴现因子:
Calculating the Value of Class 2
注: 是-2+(-2 * 0.5)+10 * 0.25+0而不是*-2 -2 * 0.5+10 * 0.25+0。那么 Class 2 的值就是-0.5 。
价值函数的贝尔曼方程
贝尔曼方程帮助我们找到最优策略和价值函数。我们知道我们的政策会随着经验而改变,所以根据不同的政策,我们会有不同的价值函数。 最优价值函数是与所有其他价值函数 相比给出最大值的函数。
贝尔曼方程表明价值函数可以被分解成两部分:
- 即时奖励,R[t+1]
- 继承国的贴现值,
数学上,我们可以将贝尔曼方程定义为:
Bellman Equation for Value Function
让我们借助一个例子来理解这个等式的含义:
假设,有一个机器人处于某个状态,然后他从这个状态移动到另一个状态。现在,问题是机器人处于这种状态有多好。利用贝尔曼方程,我们可以得出,它是离开状态时得到的奖励的期望值加上它所移动到的状态(s’)的值。
让我们看另一个例子:
Backup Diagram
我们想知道状态 s 的值。状态的值是我们离开该状态时得到的回报,加上我们到达的状态的贴现值乘以我们将进入该状态的转移概率。
Value Calculation
上述等式可以用矩阵形式表示如下:
Bellman Linear Equation
其中 v 是我们所处状态的价值,它等于即时回报加上下一个状态的贴现值乘以进入该状态的概率。
本次计算的运行时间复杂度为 O(n ) 。因此,这对于解决更大的 MRP(同样对于MDP)显然不是一个实用的解决方案。在后面的博客中,我们将关注更有效的方法,如动态规划(价值迭代和策略迭代)蒙特-克拉罗方法和 TD-Learning 。
我们将在下一个故事中更详细地讨论贝尔曼方程。
什么是马尔科夫决策过程?
马尔可夫决策过程:是一个决策的马尔可夫回报过程。一切都像 MRP 一样,但现在我们有了真正的机构来做决定或采取行动。
它是一个( S , A , P , R , 𝛾 )的元组,其中:
- s 是一组状态,
- a 是代理可以选择采取的一组操作,
- p 是转移概率矩阵,
- r 是代理人的行动所累积的报酬,
- 𝛾 是贴现因子。
p 和 R 将有轻微的变化,如下所示:
转移概率矩阵
Transition Probability Matrix w.r.t action
奖励功能
Reward Function w.r.t action
现在,我们的奖励函数依赖于行动。
到目前为止,我们已经讨论了当我们的代理遵循一个策略π通过一组状态时获得奖励(r)。实际上,在马尔可夫决策过程(MDP)中,策略是做出决策的机制。所以现在我们有了一个选择采取行动的机制。
MDP 的政策取决于当前的状态。他们不依赖于历史。这就是马尔可夫性质。因此,我们目前所处的状态是历史的特征。
我们已经看到代理处于特定状态(状态-值函数)有多好。现在,让我们看看遵循状态 s 的政策π(行动-价值函数)采取特定行动有多好。
状态-动作值函数或 Q 函数
该函数指定代理在具有策略π** 的状态下采取行动(a)的效果有多好。**
数学上,我们可以将状态-动作值函数定义为:
State-action value function
基本上,它告诉我们在具有策略π的状态下执行某个动作(a)的值。
让我们看一个马尔可夫决策过程的例子:
Example of MDP
现在,我们可以看到没有更多的概率。事实上,现在我们的代理可以做出选择,比如醒来后,我们可以选择看《网飞》或者编码和调试。当然,代理人的行为是根据某个策略π来定义的,并且会得到相应的报酬。
太棒了。
恭喜你坚持到最后!👍
到目前为止,我们已经讨论了 MDP 的构建模块,在接下来的故事中,我们将讨论和贝尔曼期望方程,更多关于最优策略和最优价值函数,和高效的价值发现方法,即动态规划(价值迭代和策略迭代算法)并用 Python 编程。
希望这个故事能增加你对 MDP 的了解。很乐意在 Instagram 上与您联系。
谢谢你与我分享你的时间!
关于马尔可夫决策过程的第 1 部分、第 2 部分和第 3 部分:
- 强化学习:马尔可夫决策过程(上)
- 强化学习:贝尔曼方程与最优性(第二部分)
- 强化学习:使用动态规划解决马尔可夫决策过程
- 强化学习:蒙特卡罗学习
参考资料:
- https://web . Stanford . edu/class/psych 209/Readings/suttonbartoiprlbook 2 nded . pdf
待深
ResNets 简介
原文:https://towardsdatascience.com/introduction-to-resnets-c0a830a288a4?source=collection_archive---------1-----------------------
‘We need to go Deeper’ Meme, classical CNNs do not perform well as the depth of the network grows past a certain threshold. ResNets allow for the training of deeper networks.
本文基于何等人【2】(微软研究院)的图像识别深度残差学习
2012 年,Krizhevsky 等人[1]为深度卷积神经网络铺上了红地毯。这是该架构第一次比 ImageNet 上的传统手工特征学习更成功。他们的 DCNN 被命名为 AlexNet,包含 8 个神经网络层,5 个卷积层和 3 个全连接层。这为传统的 CNN 奠定了基础,卷积层之后是激活函数,之后是最大池操作(有时池操作被省略以保持图像的空间分辨率)。
深度神经网络的大部分成功都归功于这些附加层。其功能背后的直觉是这些层逐渐学习更复杂的特征。第一层学习边缘,第二层学习形状,第三层学习物体,第四层学习眼睛,以此类推。尽管《盗梦空间》电影中人工智能社区共享的流行模因声称“我们需要更深入”,但何等人[2]从经验上表明,传统 CNN 模型存在深度的最大阈值。
何等人[2]绘制了 20 层 CNN 与 56 层 CNN 的训练和测试误差。这个图挑战了我们的信念,即增加更多的层将创建一个更复杂的函数,因此失败将被归因于过度拟合。如果是这种情况,额外的正则化参数和算法,如 dropout 或 L2 范数,将是修复这些网络的成功方法。然而,该图显示 56 层网络的训练误差高于 20 层网络,突出了解释其失败的不同现象。
有证据表明,使用卷积和全连接层的最佳 ImageNet 模型通常包含 16 到 30 层。
56 层 CNN 的失败可以归咎于优化功能、网络初始化或著名的消失/爆炸梯度问题。消失梯度尤其容易被归咎于此,然而,作者认为批量标准化的使用确保了梯度具有健康的规范。在众多解释为什么深层网络比浅层网络表现更好的理论中,有时最好是寻找经验结果来解释,并从那里反向工作。通过引入新的神经网络层— 残差块,训练非常深的网络的问题得到了缓解。
上图是这篇文章要学习的最重要的东西。对于希望快速实现并测试它的开发人员来说,要理解的最重要的修改是“跳过连接”,即身份映射。这个身份映射没有任何参数,只是将前一层的输出添加到前面的层。然而,有时 x 和 F(x)不会有相同的维数。回想一下,卷积运算通常会缩小图像的空间分辨率,例如,32 x 32 图像上的 3×3 卷积会产生 30 x 30 图像。恒等式映射乘以线性投影 W 以扩展捷径的通道来匹配残差。这允许将输入 x 和 F(x)合并作为下一层的输入。
当 F(x)和 x 具有不同维数时使用的等式,例如 32x32 和 30x30。这个 Ws 项可以用 1x1 卷积实现,这给模型引入了额外的参数。
使用来自的 keras 实现快捷方式块 https://github . com/raghakot/keras-resnet/blob/master/resnet . py。这种快捷连接基于后续论文“深度剩余网络中的身份映射”中更高级的描述[3]。
这里可以找到 keras 中剩余网络的另一个伟大实现 →
- https://gist . github . com/mjdietzx/0cb 95922 AAC 14d 446 a 6530 f 87 B3 a 04 ce
层之间的跳过连接将先前层的输出添加到堆叠层的输出。这使得能够训练比以前更深的网络。ResNet 架构的作者在 CIFAR-10 数据集上用 100 和 1,000 个层测试了他们的网络。他们在具有 152 层的 ImageNet 数据集上进行测试,该数据集仍然比 VGG 网络[4]具有更少的参数,后者是另一种非常流行的深度 CNN 架构。深度残差网络的集合在 ImageNet 上实现了 3.57%的错误率,在 ILSVRC 2015 分类竞赛中获得了第一名。
一种类似的方法被称为“高速公路网”。这些网络也实现跳跃连接,然而,类似于 LSTM,这些跳跃连接通过参数门。这些门决定了有多少信息通过跳过连接。作者指出,当门接*关闭时,层表示非剩余函数,而 ResNet 的标识函数从不关闭。根据经验,作者注意到,高速公路网络的作者没有显示出他们用 ResNets 显示的网络深度的准确性收益。
他们用来测试跳过连接的架构遵循了 2 个启发自 VGG 网络的启发[4]。
- 如果输出特征图具有相同的分辨率,例如 32×32→32×32,那么滤波器图深度保持不变
- 如果输出特征图大小减半,例如 32 x 32 → 16 x 16,则过滤器图深度加倍。
总的来说,34 层剩余网络的设计如下图所示:
In the image above, the dotted skip connections represent multiplying the identity mapping by the Ws linear projection term discussed earlier to align the dimensions of the inputs.
Training Results of the Architectures Shown Above: The straight line depicts training error and the static line depicts testing error. The 34-layer ResNet achieves sub 30% error rate, unlike the Plain Network on the left plot. The 34-Layer ResNet outperforms the 18-Layer ResNet by 2.8%.
Table Showing Testing Error of the different depths and the use of Residual Connections
总之,跳过连接是深度卷积网络的一个非常有趣的扩展,经验表明它可以提高 ImageNet 分类的性能。这些层也可以用于需要深度网络的其他任务,例如定位、语义分割、生成对抗网络、超分辨率等。残差网络不同于 LSTMs,LSTMs 门控先前的信息,使得不是所有的信息都通过。此外,本文中显示的跳过连接基本上安排在 2 层块中,它们不使用从相同的第 3 层到第 8 层的输入。残差网络更类似于注意力机制,因为它们模拟与输入相反的网络内部状态。希望这篇文章是对 ResNets 有用的介绍,感谢阅读!
参考文献
[1]亚历克斯·克里热夫斯基、伊利亚·苏茨基弗、杰弗里·e·辛顿。基于深度卷积神经网络的图像网分类。2012.
[2]何、、任、。用于图像识别的深度残差学习。2015.
[3],何,,,任,.深剩余网络中的身份映射。2016.
[4]卡伦·西蒙扬,安德鲁·齐泽曼。用于大规模图像识别的非常深的卷积网络。2014.
RNNs 介绍,序列到序列语言翻译及注意事项
原文:https://towardsdatascience.com/introduction-to-rnns-sequence-to-sequence-language-translation-and-attention-fc43ef2cc3fd?source=collection_archive---------9-----------------------
这篇文章的目标是简要介绍 RNNs(递归神经网络),序列到序列语言翻译(seq2seq)和注意力。我会尽量使它简单。你只需要知道:
- 线性代数
- 神经网络
如果你对这些主题感到生疏,在开始阅读之前,请点击上面的链接,随意查看。
我记得当我第一次学习前馈神经网络时,我对自己说,有可能以更好的方式建立这个神经元网络吗?因为在人脑中,神经元的连接方式比前馈神经网络更复杂。事实证明,研究人员不断找到新的方法来排列神经元,让它们做一些有用的事情。rnn 就是其中之一。
在神经网络中,每个输入有一个输出。例如,你有一个图像和一个标签。你不可能在神经网络上输入一幅又一幅图像,然后得到基于所有图像的输出。神经网络的性质使它们无法处理顺序数据。
另一方面,rnn 非常适合处理顺序数据。它们有一种“记住”先前输入并基于所有输入产生输出的机制。这使得它们非常适合序列类型的数据,如文本、音频、视频或任何时序数据。
下图显示了 RNNs 的五种变体。红色向量是输入,而蓝色向量是输出。第一种是一个输入到一个输出的情况。本质上是一个神经网络。其他的能够顺序输入和输出,例如:
一对多:图片- >字幕句子
多对一:句子- >情绪(正面/负面标签)
多对多:英语中的一个句子- >土耳其语中的一个句子
其他多对多:视频的帧- >对象周围边界框的坐标
让我们通过查看具有一个隐藏层的前馈神经网络来开始深入了解。由于每一层本质上都是线性变换,因此是矩阵乘法,我用矩阵形式的一组参数来表示每一层的操作。
大小为 5 的输入经过与 5×3 矩阵的矩阵乘法,产生隐藏层的输入,大小为 3 的向量。然后,它乘以一个 3x4 矩阵,产生 4 的输出。注意这里大小为 3 的向量。在 RNNs 中,我们称之为隐藏状态。
让我们来看看稍微修改后的版本。我们只添加了虚线矩形内的区域。此外,我们还增加了一个参数矩阵,在本例中为 3x3。实际情况是,我们从底部增加了一个输入。所有输入都需要相同的大小。因为它也经历了和底部一样的蓝色矩阵乘法。请注意,我们之前的隐藏输出在与新输入组合之前会乘以一个方阵。我们永远不知道那是什么操作。这只是 RNN 在训练时学会自己做的事情。
现在,让我们扩展虚线区域,使其成为一个循环。这样,输入可以是大于或等于 1 的任何大小。
我们本质上所做的是,我们将一个递归公式应用于序列中的每个输入。我们最后得到的取决于整个输入序列。
注意:在每个时间步使用相同的函数和相同的参数集。
深入研究:
用我们最初的参数来描绘它:
你刚刚读到的是对普通 RNNs 的解释,它是 RNNs 的最基本形式。这很容易学,但是,他们很难训练。原因是,隐藏状态中的值倾向于指数爆炸或消失。更先进的 rnn,如 LSTM 和 GRUs,通过采用更复杂的机制来缓解这一问题。Michael Nguyen 在 LSTMs 和 GRUs 上发表了一篇精彩的博文。我强烈建议你去看看,以便进一步阅读。
第 2 部分:带单词的 RNNs:语言模型
给定一个单词序列,语言模型试图预测下一个单词。起初听起来可能没什么用,就像我一样。然而,它们通常是其他更有用的自然语言处理系统的组件。
让我们看一个与我们的香草 RNN 非常相似的图表。
这里,RNN 的输入是单词嵌入,而不是实际的单词。如果你不知道什么是单词嵌入,可以考虑哈希函数,但是对于向量来说。嵌入将词汇表示为低维向量,而不是将词汇表示为一次性编码向量。由于向量维数较低,它提供了更快的线性运算的好处。这就是图中 E 的意思。
We、Wh 和 U 分别是前面图中的蓝色、绿色和橙色矩阵。此图描述了语言模型的训练。“学生打开他们的考试…”来自训练语料库;这句话确实存在。我们通过比较 y_hat^(1 和 x(2、y_hat(2 和 x^(3 等对的损失函数来惩罚语言模型。请注意,当我们向右移动时,model 也保持隐藏状态,以便跟踪过去的单词。
经过一段时间的训练后,语言模型可以通过反复预测下一步来生成文本。注意,预测的单词 y_hat^(i 是下一步操作的输入。
第 3 部分:序列到序列的机器翻译
rnn 也有能力做自然语言翻译,又名。机器翻译。它涉及两个 rnn,一个用于源语言,一个用于目标语言。其中一个叫做编码器,,另一个叫做解码器。原因是,第一个将句子编码成向量,第二个将编码的向量转换成目标语言的句子。
编码器
编码器是一个 RNN。给定源句子,它产生一个编码。注意这里 RNNs 的好处。输入句子的大小可以是任意大小。
解码器
解码器是一个独立的 RNN。给定编码的句子,它产生目标语言的翻译句子。注意紫色的虚线箭头。每个预测的单词都是下一个预测的输入。这是 rnn 的重复性质,我很感兴趣的是,它们可以通过这样的连接来做重要的工作,如语言翻译。
在解码器的每一步,给定隐藏状态和输入单词向量作为输入,单词概率分布的 argmax 被选择作为最可能的单词。这就是所谓的贪婪解码。问题是,解码器是一个接一个的。在某一点上,如果句子没有意义,它就不能返回。
此外,用一个向量编码的整个句子很难翻译成一个句子。在编码步骤之后,它实质上是从句子到向量的映射。解码器很难推导出目标语言中单词的顺序。这就是注意力发挥作用的地方。
第 4 部分:注意
注意力让解码者将注意力集中在每个输出单词的输入句子的特定部分。这有助于输入和输出句子彼此对齐。
在图中,蓝色的椭圆只是带有句子编码和隐藏状态的点积。
对于上面的法语句子,关注度最高的属于“les”。这将导致解码器以“the”开始翻译的句子。当我第一次看到那个图的时候,我想,如果正确的翻译是从“pauvres”开始的,解码器就不可能得到正确的翻译。然而,由于这个神经网络应该是端到端训练的,它也将学习产生正确的注意力分数。
结束语
对于完全的初学者来说,这可能是一篇短文中的大量信息。瑞秋·托马斯在 USF 大学的一堂课上介绍 RNN 的方式激发了我写这篇博客的灵感。我想从高层次上总结一下我感兴趣的东西。如果你有任何问题,请随时联系我!🎉 🎊
使用 Python 的 SalesForce 对象查询语言(SOQL)简介
原文:https://towardsdatascience.com/introduction-to-salesforce-object-query-language-soql-with-python-1448d497cf2c?source=collection_archive---------23-----------------------
Photo by Denys Nevozhai on Unsplash
SalesForce 有自己的 SQL 语言,理解起来有点棘手。但是有时候就是这样。
SalesForce 对象查询语言示例
我们来分解一下。如果您以前使用过 SQL 查询,并且了解它们是如何工作的,那么这将更有意义。
在 SalesForce 中,我们有 对象 ,这相当于 SQL 中的数据库表。
我们还有 字段 ,等同于数据库中的列。
那么我们有 记录 ,代表数据库中的行。理想情况下,它应该是这样的:
SELECT {*fields*} FROM *object* WHERE condition
为了理解 SOQL 查询,我们需要了解所有这些数据存储在哪里。我将使用一个名为simple_salesforce
的 Python 模块。如果你还没有看我这篇关于如何获取 SalesForce 数据的文章,你可以在这里 查看 。我们实际上不能使用 Python 来查找对象,所以这里有一个关于如何查找对象的小指南
我在哪里可以找到 SOQL 对象? 1。登录 SalesForce
2。右上角应该有一个齿轮图标,点击那个
3。出现下拉菜单,点击设置
4。在标题上,点击对象管理器
5。将填充一个对象列表
List of first 5 objects
我在哪里可以找到 SOQL 字段?
这个我们就用 Python 和simple_salesforce
了。我们希望使用 Python 模块登录,然后我们将在 SalesForce 对象上使用.describe
方法。对于本例,我们将在对象帐户上使用它。所以像这样的代码就足够了:
我在哪里可以找到 SOQL 记录? 我们现在可以完整地编写 SalesForce 查询以便检索记录。我们现在可以把它添加到前面代码的末尾,我们也可以导入pandas
来把它转换成数据帧。
这只是一个关于如何从 SalesForce 提取数据的小教程。我们可以探索更多的对象和领域。
我在这里也有家教和职业指导!
如果你喜欢这些内容,请随时在 Patreon 上支持我!
如果你们有任何问题、意见或担忧,请不要忘记通过 LinkedIn 与我联系!
Scala 简介
原文:https://towardsdatascience.com/introduction-to-scala-921fd65cd5bf?source=collection_archive---------11-----------------------
source
WScala 是什么帽子?Scala 是一种高级语言,结合了函数式和面向对象编程以及高性能运行时。那么为什么要用 Scala 而不是 Python 呢?Spark 通常用于处理大数据的大多数情况。由于 Spark 是使用 Scala 构建的,因此学习它对于任何数据科学家来说都是一个很好的工具。
[source](http://Photo by Markus Spiske on Unsplash)
Scala 是一种强大的语言,可以利用许多与 Python 相同的功能,例如构建机器学习模型。我们将深入介绍 Scala,熟悉基本语法,并学习如何使用循环、映射和过滤器。在本指南中,我将使用社区版的databricks.com。
变量
在 Scala 中,我们用val
或var
声明变量,我们将讨论两者之间的区别。值得注意的是,Scala 的语法约定是 camelCase,而 Python 在声明变量时使用 snake_case。让我们在 Scala 中创建第一个变量:
**val** counterVal = 0counterVal: Int = 0
现在让我们用var
声明一个变量:
**var** counterVar = 0counterVar: Int = 0
当我们运行细胞时,它们看起来一样,输出也一样,但它们本质上是不同的。当我们试图估算每个变量的值时,我们可以看到这一点:
counterVar = 1counterVar: Int = 1
当我们试图赋予反补贴一个新的价值时,会发生这样的情况:
笔记本:1:错误:重新分配到 val count val = 1 ^
任何使用val
声明的变量都是不可变的,,因此我们不能改变它的值。当我们不希望一个变量被改变时,不管是有意还是无意,使用val
是非常好的。例如,我们可能想用一个名字作为我们的val
并存储它,这样就没有人能更改一个人的名字。
**val** firstName = "John"**val** lastName = "Doe"firstName: String = John lastName: String = Doe
注意,Scala 显示了我们的变量(字符串)在创建时的类型。
用线串
在 Scala 中,我们可以像在 Python 中一样处理字符串。字符串的一个常见用途是插入,这意味着在短语或句子中插入一个注释或单词。字符串插值如下所示:
s"Hello, $firstName $lastName"res0: String = Hello, John Doe
类似于 Python 如何使用 f 字符串,这里我们使用 s 。双引号在 Scala 中很重要,因为如果我们试图传递单引号,它会返回一个错误。Scala 使用 $ 对传递到插值中的变量进行排序。请注意它是如何自动在单词之间添加空格的:
s"Hello, ${firstName + lastName}"res1: String = Hello, JohnDoe
在上面的方法中,名字和姓氏之间没有分隔。为了获得空间,我们必须明确使用:${firstName + " " + lastName}"
。我更喜欢对每个变量使用$
而不使用{}
——你可以使用任何一种方法进行插值。
字符串索引
数据科学中最常用的技术可能是索引和使用范围。在这两种情况下,Scala 都使用了.slice()
方法,其中第一个数字是包含性的,而最后一个数字是排他性的。让我们来看一些例子。
首先我创建了一个名为“fullName”的新变量。
val fullName = firstName + " " + lastName
在 Scala 中,我们可以简单地在变量后使用()
来调用变量的第一个索引。
这将在我们的全名变量中返回J
。为了在我们的变量中索引一个索引范围,我们需要调用.slice()
并传入这个索引范围。
运行fullName.slice(3, 6)
将从名字返回n D
。Scala 包含 3,并将空间计为 4。在D
处停止,因为设置范围时 6 是唯一的。这和其他编程语言类似。熟悉这一概念需要时间,但仍会有不正确设置范围的时候。这里需要注意的一点是,您不能索引负数。对于熟悉 Python 的人来说,使用[-1]
会返回索引的结尾,而 Scala 会给出一个错误。超出变量范围的索引将只给出最后一个。要获得字符串的长度,请使用:.length()
。
数组
[source](http://Photo by Glenn Carstens-Peters on Unsplash)
rrays 基本上就是 Scala 处理列表的方式。数组有类似 Python 的方法,但也有细微的差别,这使得 Scala 数组独一无二。创建数组时,请小心选择var
,因为您可能想要更改数组值。因为数组只能改变它们的值,而不能改变数组本身的大小,所以我们将使用 ArrayBuffer 来演示。
**var** myArr = ArrayBuffer**(**2, 3 , 4, 5, 6**)**myArr: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4, 5, 6)
注意,Scala 检测到我们的数组包含所有整数类型。现在我们有了一个数组,让我们来看一些例子,看看我们可以用它们做些什么。像字符串一样,我们可以对数组进行索引和切片,以查看任何给定位置的值。
myArr(3)res0: Int = 5myArr.slice(3, 5)res1: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(5, 6)
要向数组添加元素,使用+=
添加一个值:
myArr += 10
myArrres3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4, 5, 6, 10)
您可以看到 10 作为最后一个元素被添加到数组中。我们也可以用类似的方式删除一个项目:
myArr -= 10myArrres7: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(2, 3, 4, 5, 6)
要从列表中删除多个元素,我们需要像这样使用()
:
myArr -= (2, 4)myArrres8: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 5, 6)
通过索引删除元素可以使用.remove(x)
方法完成,只需用x
输入想要删除的索引。您还可以向该方法传递一个范围来移除该范围内的索引:.remove(0, 3)
将移除索引元素 0 和 2。
映射和过滤
[source](http://Photo by Tyler Nix on Unsplash)
我们经常想要过滤列表中的元素或者映射它们。在我们看这些之前,先看看我们如何在 Scala 中使用循环来遍历数组。
**for** (n <- myArr) {
**println**(n)
}3 5 6
上面的代码将运行一个 for 循环,遍历数组中的每个元素,并打印出数组中的每个元素。<-
的使用告诉 Scala 我们想要迭代myArr
print n
中的myArr
和for
每个n
(元素)。缩进是不必要的,因为使用{}
将表示代码块的开始和结束。
Mapping 将遍历列表中的每一项,并将其转换为不同的元素。如果我们想一次改变数组中的所有值,这很好。
这里我们将使用.map()
方法将myArr
中的每个元素乘以 5:
myArr.map**(**n => n * 5**)**res22: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(15, 25, 30)
如果满足我们设定的标准或条件,过滤将返回原始数据或数组的子集。很多时候,我们希望使用 filter 来获取数据或在数组或数据集中找到某些元素。我想把myArr
过滤掉,这样它只会返回能被 2 整除的数字。
myArr.filter(n => n % 2 == 0)res26: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(6)
上面的代码迭代myArr
,返回能被 2 整除的数(基本上是偶数)。我们还可以将映射和过滤结合在一起,以增加我们的列表并检查偶数。实际上,我会在myArr
上随机添加一些数字,这样我们就可以让它变得有趣!
在这里,我们将多个元素追加到数组中:
myArr += **(**10, 3, 7, 5, 12, 20**)**res30: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(3, 5, 6, 10, 3, 7, 5, 12, 20)
现在我们将把映射和过滤结合起来返回myArr
中的偶数:
myArr.map(n => n * 5).filter**(**n => n % 2 == 0**)**res31: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(30, 50, 60, 100)
我们也可以对奇数做同样的事情,把n % 2 == 0
改成n % 3 == 0
。
映射和过滤对于数据科学工作流至关重要,这项技术在我们每次处理数据集时都会用到。
Scala 是我们作为数据科学家的一个很好的工具。我们可以用它来处理数据和建立机器学习模型。对 Scala 的介绍只涵盖了最基本的内容。现在该由您来深入研究这种语言了。
序列建模问题介绍
原文:https://towardsdatascience.com/introduction-to-sequence-modeling-problems-665817b7e583?source=collection_archive---------8-----------------------
Photo by Nick Fewings on Unsplash
考虑基于多个健康参数预测一个人的健康风险的问题,我们决定使用前馈神经网络(也称为多层神经元网络)对输入和输出之间的真实关系进行建模。
在前向神经网络(FNN)中,一个数据点的输出完全独立于先前的输入,即…第二个人的健康风险不依赖于第一个人的健康风险,依此类推。
类似地,在卷积神经网络(CNN)的情况下,在图像分类的上下文中来自 softmax 层的输出完全独立于先前的输入图像。
FNN 和 CNN 的特点是:
- 输出独立于先前的输入。
- 输入是固定长度的。
引用说明:本文的内容和结构是基于我对四分之一实验室——pad hai深度学习讲座的理解。
序列建模
序列建模是预测下一个单词/字母的任务。与 FNN 和 CNN 不同,在序列建模中,当前输出依赖于先前输入,并且输入的长度不固定。
在这一节中,我们将讨论序列建模的一些实际应用。
自动完成
让我们看看序列建模环境中的自动完成问题。在这个问题中,每当我们键入一个字符( d )时,系统试图根据先前键入的字符来预测下一个可能的字符。
换句话说,假设我们已经输入了' d ',网络试图从可能的 26 个英文字母中预测下一个字符。神经网络将具有大小为 26 的 softmax 输出,表示给定前一个字母的下一个字母的概率。由于这个网络的输入是字符,我们需要将它们转换成大小为 26 的独热编码向量,并且对应于字母表的索引的元素将被设置为 1,其他的都被设置为 0。
词性标注
在词性标注的问题中,我们给定了每个单词的单词序列,我们需要预测该单词的词性标签(例如:动词、名词、代词等……)。同样在这个问题中,输出不仅依赖于当前输入(当前字),还依赖于先前的输入。例如,如果我们知道前面的单词是形容词,那么将单词“movie”标记为名词的概率会更高。
序列分类
我们需要在每个时间步产生输出吗?
假设你想通过分析影评来预测电影的脉搏。在这种情况下,我们不需要在输入的每个单词后输出,而是我们只需要在阅读整个句子后理解情绪,即…积极或消极。用机器学习从一段文字中理解情绪,叫做情感分析。
序列学习问题建模
在上一节中,我们已经了解了序列学习问题的实际应用,但是我们如何对这样的问题建模呢?。
在序列学习问题中,我们知道时间步长“t”的真实输出取决于模型在时间步长“t”之前看到的所有输入。由于我们不知道真实的关系,我们需要得出一个*似值,使函数依赖于所有以前的输入。
这里要注意的关键点是,无论我们是预测下一个字符还是标记一个单词的词性,这项任务在每个时间步都不会改变。该函数的输入在每个时间步长都是变化的,因为对于较长的句子,该函数需要跟踪较大的单词集。
换句话说,我们需要定义一个具有以下特征的函数:
- 确保输出 Yt 取决于先前的输入
- 确保函数可以处理可变数量的输入
- 确保在每个时间步执行的功能是相同的。
递归神经网络
递归神经网络(RNN) 是一种神经网络,前一步的输出作为当前步骤的输入。
在 RNN,你可以看到第一个时间步的输出和原始输入一起被输入到下一个时间步。
该功能的输入以橙色表示,并表示为 xᵢ 。使用向量 U 来表示与输入相关联的权重,并且将单词的隐藏表示( sᵢ) 计算为先前时间步长的输出和当前输入以及偏差的函数。隐藏表示的输出( sᵢ) 由下面的等式给出,
一旦我们计算了输入的隐藏表示,来自网络的最终输出( yᵢ )是隐藏表示和与其关联的权重以及偏差的 softmax 函数。我们能够提出一个*似函数,它能够满足我们为解决序列学习问题而设定的所有三个条件。
继续学习
如果你想用 Keras & Tensorflow 2.0 (Python 或者 R)学习更多关于人工神经网络的知识。查看来自 Starttechacademy 的 Abhishek 和 Pukhraj 的人工神经网络。他们以一种简单化的方式解释了深度学习的基础。
结论
在本文中,我们简要地看了前馈神经网络和卷积神经网络的局限性,以根据它们的特性来处理变化输入的任务。之后,我们继续讨论序列建模的一些实际应用。然后,我们研究了一种新型的神经网络,它可以帮助我们对序列学习问题进行建模。
推荐阅读
[## 用 Pytorch 解释神经网络中的批量归一化和丢失
在本文中,我们将以简单的方式讨论神经网络中的批处理规范化和丢失。
towardsdatascience.com](/batch-normalization-and-dropout-in-neural-networks-explained-with-pytorch-47d7a8459bcd) [## 用 Pytorch 可视化卷积神经网络
可视化 CNN 过滤器并对输入进行遮挡实验
towardsdatascience.com](/visualizing-convolution-neural-networks-using-pytorch-3dfa8443e74e)
在我的下一篇文章中,我们将深入讨论递归神经网络及其学习算法。所以,请务必在 Medium 上跟随我,以便在它下跌时得到通知。
直到那时,和*:)
NK。
作者简介
Niranjan Kumar 是好事达印度公司的高级数据科学顾问。他对深度学习和人工智能充满热情。除了在媒体上写作,他还作为自由数据科学作家为 Marktechpost.com 写作。点击查看他的文章。
你可以在 LinkedIn 上与他联系,或者在 Twitter 上关注他,了解关于深度学习和机器学习的最新文章。
参考文献:
- 了解 LSTM 网络
- 斯坦福大学——语言模型和 rnn
免责声明 —这篇文章中可能有一些相关资源的附属链接。你可以以尽可能低的价格购买捆绑包。如果你购买这门课程,我会收到一小笔佣金。
Spark NLP 简介:基础和基本组件
原文:https://towardsdatascience.com/introduction-to-spark-nlp-foundations-and-basic-components-part-i-c83b7629ed59?source=collection_archive---------1-----------------------
Photo by James Harrison on Unsplash
*这是一系列博客文章中的第一篇,旨在帮助数据科学家和 NLP 从业者从头开始学习 Spark NLP 库的基础知识,并轻松将其集成到他们的工作流中。在本系列中,我们将尽最大努力制作高质量的内容和清晰的说明,并附上 Python 和 Scala 中关于 Spark NLP 最重要特性的代码。通过这些文章,我们旨在通过用代码和指令触及所有的实际问题和痛点,使 Spark NLP 库的底层概念尽可能清晰。最终目的是让观众在短时间内上手这个神奇的库,*滑学习曲线。希望读者至少对 Python 和 Spark 有一个基本的了解。
1.为什么我们需要另一个 NLP 库?
自然语言处理(NLP)是许多数据科学系统中的关键组件,必须理解或推理文本。常见的用例包括问题回答、解释或总结、情感分析、自然语言 BI、语言建模和消歧。
NLP 在越来越多的人工智能应用中是必不可少的。如果你正在建立一个聊天机器人,搜索专利数据库,将病人与临床试验相匹配,给客户服务或销售电话评分,从财务报告中提取事实或解决 17 个行业的 44 个用例中的任何一个,从自由文本中提取准确的信息是必不可少的。
由于*年来 NLP 的流行和对数据科学的大肆宣传,出现了许多优秀的 NLP 库,甚至数据科学新手也开始使用这些开源库尝试各种 NLP 技术。这里是最流行的 NLP 库,它们在社区和不同的开发水*下被大量使用。
- 自然语言工具包(NLTK) :所有 NLP 技术的完整工具包。
- TextBlob :易于使用的 NLP 工具 API,构建在 NLTK 和 Pattern 之上。
- SpaCy :用 Python 和 Cython 的工业级实力 NLP。
- Gensim :人类主题建模
- 斯坦福核心 NLP :斯坦福 NLP 集团的 NLP 服务和套餐。
- Fasttext :由脸书人工智能研究(FAIR)实验室创建的学习单词嵌入和句子分类的 NLP 库
显然,在 NLP 的一般领域中有更多的库——但是我们在这里关注的是通用库,而不是迎合特定用例的库。考虑到所有这些库,你可能会问为什么我们还需要另一个 NLP 库。
我们将尝试在以下主题下回答这个问题:
答:满足您所有 NLP 需求的单一统一解决方案
当您想要交付可扩展、高性能和高精度的 NLP 支持的软件用于实际生产时,这些库中没有一个提供统一的解决方案。
请记住,任何 NLP 管道都只是更大的数据处理管道的一部分:例如,问题回答涉及加载训练数据、转换数据、应用 NLP 注释器、构建功能、训练值提取模型、评估结果(训练/测试分割或交叉验证)以及超参数估计。我们需要一个一体化的解决方案来减轻文本预处理的负担,并在使用 NLP 解决数据科学问题的各个步骤之间建立联系。因此,我们可以说,一个好的 NLP 库应该能够正确地将自由文本转换为结构化特征,并让您训练自己的 NLP 模型,这些模型可以轻松地输入到下游的机器学习(ML)或深度学习(DL)管道中。
b .利用迁移学习,实现 NLP 研究中最新最棒的算法和模型
迁移学习是一种从源设置中提取知识并将其应用于不同目标设置的方法,它是一种非常有效的方法来不断提高 NLP 模型的准确性,并通过利用一些相关任务或领域的已有标记数据,即使在小数据的情况下也能获得可靠的准确性。因此,没有必要为了训练一个最先进的模型而积累数百万个数据点。
在过去的几年中,NLP 领域正在发生巨大的变化,现代工业规模的 NLP 库应该能够实现最新和最伟大的算法和模型——这并不容易,因为 NLP 正在经历其 ImageNet 时刻并且最先进的模型正被超过一个月两次。
词向量作为 NLP 核心表示技术的长期统治已经出现了一系列令人兴奋的新挑战者,如 ELMo 、 BERT 、 RoBERTa 、 ALBERT 、 XLNet 、 Ernie 、 ULMFiT 、 OpenAI transformer ,它们都是开源的,包括预训练的模型,可以在没有这些作品上了 头条,证明了预先训练的语言模型可以用来在广泛的自然语言处理任务上实现最先进的结果,有时甚至超过人类水*的基准。
c .缺少 Spark 完全支持的 NLP 库
作为一个通用的内存分布式数据处理引擎, Apache Spark 获得了业界的广泛关注,并且已经拥有了自己的 ML 库( SparkML )和其他一些用于特定 NLP 任务的模块,但是它并没有涵盖拥有一个成熟解决方案所需的所有 NLP 任务。当您尝试在管道中使用 Spark 时,通常需要使用其他 NLP 库来完成某些任务,然后尝试将中间步骤反馈给 Spark。但是,将您的数据处理框架从 NLP 框架中分离出来意味着您的大部分处理时间都花费在来回序列化和复制字符串上,并且效率非常低。
d .交付任务关键型企业级 NLP 库
今天许多最流行的 NLP 包都有学术渊源——这表现在设计权衡中,它们更倾向于原型化的简易性而不是运行时性能,选择的广度而不是简单的极简 API,以及淡化可伸缩性、错误处理、节省内存消耗和代码重用。
该库已经在企业项目中使用,这意味着第一级的错误、重构、意外瓶颈和序列化问题已经解决。单元测试覆盖率和参考文档的水*让我们可以放心地将代码开源。
Spark NLP is already in use in enterprise projects for various use cases
总之,我们迫切需要一个 NLP 库,它是简单易学的 API,可以用您最喜欢的编程语言编写,支持您需要的人类语言,速度非常快,并且可以扩展到大型数据集,包括流和分布式用例。
考虑到所有这些问题、流行的 NLP 库的局限性和行业的最新趋势, John Snow Labs ,一家帮助医疗保健和生命科学组织更快地将人工智能投入工作的全球人工智能公司,决定率先开发 Spark NLP 库。
约翰·斯诺实验室是一家获奖的数据分析公司,领导并赞助了 Spark NLP 库的开发。该公司为其提供商业支持、赔偿和咨询。这为该库提供了长期的资金支持、有资金支持的活跃开发团队,以及不断增长的推动健壮性和路线图优先级的真实项目流。
John Snow Labs is a recipient of several awards in Data Analytics
2.什么是 Spark NLP?
Spark NLP 是一个开源的自然语言处理库,构建在 Apache Spark 和 Spark ML 之上。它提供了一个简单的 API 来集成 ML 管道,并由 John Snow 实验室提供商业支持。Spark NLP 的注释器利用基于规则的算法、机器学习和一些在引擎盖下运行的 Tensorflow 来支持特定的深度学习实现。
该库涵盖了许多常见的 NLP 任务,包括标记化、词干化、词汇化、词性标注、情感分析、拼写检查、命名实体识别等。注释器、管道和概念的完整列表在在线参考资料中有描述。所有这些工具都是开源的,可以用于数据训练模型。它还提供了预先训练的管道和模型,尽管它们只是作为一种感受库如何工作的方式,而不是用于生产用途。
Spark NLP 库是用 Scala 编写的,它包括 Scala 和 Python APIs,供 Spark 使用。它不依赖于任何其他 NLP 或 ML 库。对于每种类型的注释器,我们都要做一个学术文献回顾,以找到最先进的技术(SOTA),进行团队讨论,并决定实现哪种算法。根据三个标准评估实施情况:
- 准确性——如果一个伟大的框架有不符合标准的算法或模型,那么它就没有任何意义。
- 性能——运行时应该与任何公共基准相当或更好。没有人应该放弃准确性,因为注释器运行速度不够快,无法处理流用例,或者在集群环境中伸缩性不好。
- 可训练性或可配置性——自然语言处理是一个固有的特定领域的问题。社交媒体帖子、学术论文、电子病历和报纸文章使用了不同的语法和词汇。
Spark NLP 面向软件系统中的生产应用,这些软件系统已经超越了 spaCy、NLTK 和 CoreNLP 等旧库。截至 2019 年 2 月,该库被 16%的企业公司使用,是此类公司使用最广泛的NLP 库。
该库原生构建于 Apache Spark 和 TensorFlow 之上,为机器学习管道提供了简单、高效且准确的 NLP 符号,可以在分布式环境中轻松扩展。这个库在集成 NLP 功能的同时重用了 Spark ML 管道。
在 O'Reilly 最*的年度调查中,它确定了企业公司采用人工智能的几个趋势。根据调查结果,Spark NLP 库在所有人工智能框架和工具中排名第七。它也是迄今为止使用最广泛的 NLP 库——是 spaCy 的两倍。它也是继 scikit-learn、TensorFlow、Keras 和 PyTorch 之后最受欢迎的人工智能库。
作为 Spark ML API 的本机扩展,该库提供了训练、定制和保存模型的能力,以便它们可以在集群、其他机器上运行或保存起来供以后使用。扩展和定制模型和管道也很容易,我们将在本系列文章中详细介绍。Spark NLP 是带有 Apache 2.0 许可的开源软件,所以欢迎您查看完整的源代码。
过去几年自然语言处理深度学习的兴起意味着,在热门库中实现的算法,如 spaCy 、斯坦福 CoreNLP 、 NLTK 和 OpenNLP ,不如最新科学论文可能实现的精确。
声称提供最先进的准确性和速度使我们不断追求最新的科学进步。
Spark NLP provides licensed annotators and models that are already trained by SOTA algorithms for Healthcare Analytics
在单机和集群上,Apache Spark 的性能更接*裸机,这意味着普通的 NLP 管道可以比传统库的固有设计限制快几个数量级。
迄今为止最全面的基准,比较生产级 NLP 库,一年前发表在 O'Reilly Radar 上。左侧是在单个英特尔 i5、4 核、16 GB 内存机器上训练简单流水线(句子边界检测、标记化和词性标注)的运行时比较
Spark NLP training performance on single machine vs cluster
能够利用 GPU 进行训练和推理已经成为赌注。使用 TensorFlow 进行深度学习使 Spark NLP 能够充分利用现代计算机*台——从英伟达的 DGX-1 到英特尔的 Cascade Lake 处理器。旧的库,无论它们是否使用一些深度学习技术,都需要重写以利用这些新的硬件创新,这些创新可以将 NLP 管道的速度和规模提高另一个数量级。
能够在很少或没有代码更改的情况下,将模型训练、推理和完整的人工智能管道从本地机器扩展到集群,也已经成为赌注。Spark NLP 原生构建于 Apache Spark ML 之上,支持 Spark NLP 在任何 Spark 集群、内部或任何云提供商上扩展。由于 Spark 的分布式执行规划和缓存,加速得到了优化,这已经在几乎任何当前的存储和计算*台上进行了测试。
最流行的 NLP 库的功能比较如下:
Spark NLP 还附带了一个 OCR 包,可以读取 PDF 文件和扫描图像(需要Tesseract 4.x+
)。这是第一个包含 OCR 功能的 NLP 库。( **自 2.2.2 起,OCR 功能移至授权版本。*)
3.基本组件和底层技术
既然 Spark NLP 是坐在 Apache Spark 的肩膀上,那么最好用 Spark 本身的参考来解释 Spark NLP 组件。
Apache Spark ,曾经是 Hadoop 生态系统的一个组成部分,现在正成为企业首选的大数据*台,主要是因为它能够处理流数据。它是一个强大的开源引擎,提供实时流处理、交互式处理、图形处理、内存处理以及批处理,速度非常快,易于使用,接口标准。
An overview of Spark NLP components
在该行业中,对能够实现上述所有功能的强大引擎有很大的需求。你的公司或客户迟早会使用 Spark 开发复杂的模型,让你发现新的机会或规避风险。Spark 并不难学,如果你已经懂 Python 和 SQL,入门是非常容易的。为了熟悉 Spark 和它的 Python 包装器 Pyspark ,你可以在本文底部找到额外的资源。
(我强烈建议用我的简介笔记本 )学习 PySpark 的 基础知识
Spark 有一个名为 Spark ML 的模块,它引入了几个 ML 组件。估计器,它们是可训练的算法,以及变换器,它们或者是训练估计器的结果,或者是根本不需要训练的算法。估值器和变压器都可以是流水线的一部分,这不多不少于一系列按顺序执行的步骤,并且可能依赖于彼此的结果。
Spark-NLP 引入了 NLP 标注器,它们合并在这个框架中,其算法旨在并行预测。现在,让我们从详细解释每个组件开始。
a.注释者
在 Spark NLP 中,所有的注释器要么是评估器,要么是转换器,就像我们在 Spark ML 中看到的那样。Spark ML 中的估计器是一种算法,它可以适用于数据帧以产生一个变换器。例如,学习算法是在数据帧上训练并产生模型的估计器。转换器是一种能将一个数据帧转换成另一个数据帧的算法。例如,ML 模型是将具有特征的数据帧转换成具有预测的数据帧的转换器。
在 Spark NLP 中,有两种类型的标注器:标注器方法和标注器模型
AnnotatorApproach 从 Spark ML 扩展了估计器,这意味着通过 fit() 来训练,而 AnnotatorModel 扩展了变换器,这意味着通过 transform()来变换数据帧。
有些 Spark NLP 注释器有一个模型后缀,有些没有。当注释器是训练过程的结果时,模型后缀被明确地声明。一些标注器,比如标记器是转换器,但是不包含后缀模型,因为它们没有经过训练,标注器。模型注释器在其静态对象上有一个 pre-trained() ,用于检索模型的公共预训练版本。
长话短说,如果它在一个数据帧上训练并产生一个模型,它就是一种注释方法;如果它通过一些模型将一个数据帧转换为另一个数据帧,它就是注释器模型(例如wordedbedingsmodel),并且如果它在转换数据帧时不依赖于预先训练的注释器(例如标记器,它就不使用模型后缀。
下面是 Spark NLP v2.2.2 提供的注释器列表
- These marked annotators do not take “Approach” suffix at the end while all the others take this suffix. All the AnnotatorModels take “Model” suffix at the end.
按照惯例,有三种可能的名称:
接*——可训练的注释者
型号 —经过培训的注释者
无——要么是带有预处理步骤的不可训练的注释器,要么是模型的简写
所以比如斯特梅尔没有说接*也没有说型号,但是,它是一个型号。另一方面, Tokenizer 没有说接*也没有说模型,但是它有一个 TokenizerModel()。因为它不是“训练”什么,而是在转换成模型之前做一些预处理。
如有疑问,请参考官方文件和 API 参考。
尽管我们将在下面的文章中进行许多实际操作,但是让我们给你一点提示,让你理解注释者方法和注释者模型之间的区别。
如上所述,标记器是一个注释器模型。所以我们需要调用 fit() 然后 transform() 。
tokenizer = Tokenizer() \
.setInputCols([“document”]) \
.setOutputCol(“token”)tokenizer.fit(df).transform(df)
另一方面,斯特梅尔是一个注释者模型。所以我们只需要调用 transform() 。
stemmer = Stemmer() \
.setInputCols([“token”]) \
.setOutputCol(“stem”)stemmer.transform(df)
稍后您将学习所有这些参数和语法。因此,在我们进入这一部分之前,不要试图复制这些代码片段。
另一个要点是,每个注释器接受某些类型的列,并输出另一种类型的新列(我们称之为注释器类型)。在 Spark NLP 中,我们有以下类型: Document,token,chunk,pos,word_embeddings,date,entity,perspective,named_entity,dependency,labeled_dependency。也就是说,如果要将一个列输入到注释器中,那么您拥有的数据帧需要有一个来自这些类型之一的列;否则,你需要使用一个 Spark NLP 变压器。我们将在后面详细讨论这个概念。
b.预训练模型
我们提到过经过训练的标注器被称为标注器模型,这里的目标是通过指定的模型(经过训练的标注器)将一个数据帧转换成另一个数据帧。Spark NLP 提供以下四种语言的预训练模型(英语、法语、德语、意大利语),您只需指定模型名称,然后根据您的用例和数据集配置模型参数,将预训练模型加载到您的磁盘中。然后,您将无需担心从零开始训练一个新模型,并将能够享受通过 transform() 直接应用于您自己的数据的预训练 SOTA 算法。在官方文档中,你可以找到关于如何通过使用哪些算法和数据集来训练这些模型的详细信息。
以下是 Spark NLP v2.2.2 提供的预训练模型列表
# load NER model trained by deep learning approach and GloVe word embeddingsner_dl = NerDLModel.pretrained(‘ner_dl’)# load NER model trained by deep learning approach and BERT word embeddingsner_bert = NerDLModel.pretrained(‘ner_dl_bert’)ner_bert.transform(df)
c.变形金刚(电影名)
还记得我们讨论过每个注释器接受或输出的特定类型的列。那么,如果我们的数据帧没有这种类型的列,我们该怎么办呢?变形金刚来了。在 Spark NLP 中,我们有五个不同的转换器,主要用于获取数据或将数据从一个注释者类型转换到另一个。以下是变形金刚的列表:
文档汇编员 :为了通过 NLP 过程,我们需要得到带注释的原始数据。这是一个特殊的变压器,为我们做到这一点;它创建了 Document 类型的第一个注释,将来注释者可能会用到它。
token assembler:这个转换器从标记中重建一个文档类型注释,通常是在这些标记被规范化、词汇化、规范化、拼写检查等之后,以便在进一步的注释器中使用这个文档注释。
Doc2Chunk :用 chunkCol 的内容将文档类型注释转换成 Chunk 类型。
Chunk2Doc :将块类型列转换回文档。在尝试对块结果进行重新标记或进一步分析时非常有用。
Finisher :一旦我们的 NLP 管道准备就绪,我们可能想要在其他容易使用的地方使用我们的注释结果。修整器将注释值输出到字符串中。
# get the dataframe with text column, and transform into another dataframe with a new document type column appendeddocumentAssembler = DocumentAssembler()\
.setInputCol(“text”)\
.setOutputCol(“document”)documentAssembler.transform(df)
d.管道
我们之前提到过,Spark NLP 提供了一个简单的 API 来与 Spark ML 管道集成,所有的 Spark NLP 注释器和转换器都可以在 Spark ML 管道中使用。所以,还是通过 Spark ML 官方文档来解释管道概念比较好。
什么是管道呢?在机器学习中,运行一系列算法来处理和学习数据是很常见的。例如,简单的文本文档处理工作流可能包括几个阶段:
- 将每个文档的文本分成句子和标记(单词)。
- 通过应用一些文本预处理技术(清理、词汇化、词干化等)来规范化标记。)
- 将每个标记转换成数字特征向量(例如,单词嵌入、tfidf 等。).
- 使用特征向量和标签学习预测模型。
这就是如何使用 sklearn(一个流行的 Python ML 库)将这样的流编写为管道。
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformerfrom sklearn.linear_model import LogisticRegressiondef text_processing ():
# your text preprocessing steps ..
return processed_textmypipeline = Pipeline ([
(“preprocess”, text_processing()),
(“vect”, CountVectorizer()),
(“tfidf”, TfidfTransformer()),
(“model”, LogisticRegression()),
])mypipeline.fit(X_train, y_train)
Apache Spark ML 将这样的工作流表示为管道,它由一系列按特定顺序运行的 PipelineStages (转换器和估算器)组成。
简而言之,管道将多个转换器和估算器链接在一起,以指定 ML 工作流。我们使用管道将多个转换器和估计器链接在一起,以指定我们的机器学习工作流程。
下图是管道的培训时间使用情况。
流水线被指定为一系列阶段,每个阶段或者是转换器或者是估计器。这些阶段按顺序运行,输入数据帧在通过每个阶段时会发生转换。也就是说,数据按顺序通过拟合的管道。每个阶段的 transform() 方法更新数据集并将其传递给下一个阶段。在管道的帮助下,我们可以确保训练和测试数据经过相同的特征处理步骤。
现在让我们看看如何在 Spark NLP 中使用标注器和转换器来完成这个任务。假设我们有以下需要在数据帧上逐一应用的步骤。
- 将文本拆分成句子
- 标记化
- 使标准化
- 获取单词嵌入
这是我们如何在 Spark NLP 中编写管道代码。
from pyspark.ml import Pipelinedocument_assembler = DocumentAssembler()\
.setInputCol(“text”)\
.setOutputCol(“document”)sentenceDetector = SentenceDetector()\
.setInputCols([“document”])\
.setOutputCol(“sentences”)tokenizer = Tokenizer() \
.setInputCols([“sentences”]) \
.setOutputCol(“token”)normalizer = Normalizer()\
.setInputCols([“token”])\
.setOutputCol(“normal”)word_embeddings=WordEmbeddingsModel.pretrained()\
.setInputCols([“document”,”normal”])\
.setOutputCol(“embeddings”)nlpPipeline = Pipeline(stages=[
document_assembler,
sentenceDetector,
tokenizer,
normalizer,
word_embeddings,
])pipelineModel = nlpPipeline.fit(df)
让我们看看这是怎么回事。从下面的流程图中可以看到,根据输入列的规范,每个生成的(输出)列都作为输入指向下一个注释器。这就像积木和乐高积木一样,你可以通过一点点创意来设计出令人惊叹的管道。
引擎盖下到底发生了什么?
当我们用 Spark 数据帧(df)在管道上拟合()时,它的文本列首先被送入 DocumentAssembler()转换器,然后在文档类型(注释者类型)中创建一个新列“文档”。正如我们之前提到的,这个转换器基本上是任何 Spark 数据帧的 Spark NLP 的初始入口点。然后它的文档列被输入到SentenceDetector()(annotator approach)中,文本被分割成一个句子数组,并在文档 type 中创建新列“ sentences”。然后将“sentences”列输入到Tokenizer()(annotator model)中,对每个句子进行分词,并在 Token type 中创建新列“ token”。诸如此类。您将在下面的文章中详细了解所有这些规则和步骤,因此我们在此不做过多阐述。
除了定制的管道之外,Spark NLP 还有一个预先训练好的管道,已经根据不同的用例使用了特定的注释器和转换器。
以下是预训练管道的列表。
我们将在下面的文章中解释所有这些管道,但是让我们给你一个使用其中一个管道的例子。
下面是我们在“explain _ document _ dl”管道中的 NLP 注释器:
- 文件汇编
- sentenced detector
- 记号赋予器
- LemmatizerModel
- 斯特梅尔
- 感知器模型
- 上下文拼写检查器模型
- 单词嵌入(手套 6B 100)
- NerDLModel
- NerConverter(分块)
所有这些注释器都已经用 SOTA 算法进行了训练和调优,随时可以为您服务。因此,当您调用这个管道时,这些注释器将在幕后运行,您将获得通过这些注释器生成的一批新列。要使用预先训练好的管道,你需要做的就是指定管道名称,然后 transform() 。您还可以设计和训练这种管道,然后保存到您的磁盘上以供以后使用。
print (df.columns)>> [‘text’]from sparknlp.pretrained import PretrainedPipelinepipeline = PretrainedPipeline(“explain_document_dl”, lang=”en”)transformed_df = pipeline.transform(df)print (transformed_df.columns)>> [‘text’,
‘document’,
‘sentence’,
‘token’,
‘checked’,
‘lemma’,
‘stem’,
‘pos’,
‘embeddings’,
‘ner’,
‘entities’]
当说到 SOTA 算法时,我们是认真的。例如, NERDLModel 由 NerDLApproach 标注器在 WikiNER 语料库上使用 Char CNNs — BiLSTM — CRF 和 GloVe 嵌入进行训练,并支持对 PER、LOC、ORG 和 MISC 实体的识别。根据最*的一份调查报告,这种 DL 架构在 NER 获得了最高分。因此,只需一行代码,您就可以获得 SOTA 结果!
4.结论
在第一篇文章中,我们试图让您熟悉 Spark NLP 的基础知识及其构建模块。Spark NLP 库在企业项目中使用,原生构建于 Apache Spark 和 TensorFlow 之上,提供一体化的最新 NLP 解决方案,为机器学习管道提供简单、高性能和准确的 NLP 符号,可在分布式环境中轻松扩展。尽管它有陡峭的学习曲线和复杂的框架,但这个惊人的库背后的虚拟开发人员团队推动了实现和覆盖 NLP 研究中最*突破的极限,并努力使其易于实现到您的日常工作流中。
在接下来的文章中,我们计划用 Python 和 Scala 中清晰的代码样本涵盖所有细节。在此之前,请随时访问Spark NLP workshop repository或查看以下资源。欢迎来到 Spark NLP 的神奇世界,敬请期待!
下一篇文章:
Spark NLP 简介:安装和入门
Spark NLP 101:文档汇编器
Spark NLP 101:光管道
使用 Bert 和通用语句编码器在 Spark NLP 中进行文本分类
命名实体识别(NER)Spark NLP 中的 BERT
5.资源
PySpark Essentials:https://github . com/vkocaman/PySpark _ Essentials _ March _ 2019/blob/master/PySpark %20-% 20 from % 20 zero % 20 to % 20 hero % 20(2019 年 9 月% 20 日)。ipynb
py spark——快速游览:【https://github.com/skamalj/spark/blob/master/spark.ipynb
https://towards data science . com/spark-data bricks-important-lessons from-my-first-six-months-d9b 26847 f45d
https://towards data science . com/the-most-complete-guide-to-py spark-data frames-2702 c 343 B2 E8
https://www . oreilly . com/radar/one-simple-chart-who-is-interest-in-spark-NLP/
https://blog . dominodatalab . com/comparisng-the-functionality-of-open-source-natural language-processing-libraries/
https://databricks . com/blog/2017/10/19/introducing-natural-language-processing-library-Apache-spark . html
https://databricks . com/fr/session/Apache-spark-NLP-extending-spark-ml-to-deliver-fast-scalable-unified-natural-language-processing
https://medium . com/@ Saif 1988/spark-NLP-walk through-powered-by-tensor flow-9965538663 FD
https://www . kdnugges . com/2019/06/spark-NLP-getting-started-with-worlds-most-wide-used-NLP-library-enterprise . html
https://www . Forbes . com/sites/forbestechcouncil/2019/09/17/winning-in-health-care-ai-with-small-data/# 1 b2fc 2555664
https://medium . com/hacker noon/mueller-report-for-nerds-spark-meets-NLP-with-tensor flow-and-Bert-part-1-32490 a8f8f 12
https://www . analyticsindiamag . com/5-reasons-why-spark-NLP-is-the-most-wide-use-library-in-enterprises/
https://www . oreilly . com/ideas/comparing-production-grade-NLP-libraries-training-spark-NLP-and-spacy-pipelines
https://www . oreilly . com/ideas/comparing-production-grade-NLP-libraries-accuracy-performance-and-scalability
[## 为什么应该使用 Spark 进行机器学习
随着组织创建更加多样化和更加以用户为中心的数据产品和服务,对以下方面的需求日益增长…
www.infoworld.com](https://www.infoworld.com/article/3031690/analytics/why-you-should-use-spark-for-machine-learning.html)
https://under rated . sigma ratings . com/post/187988777561/a-practical-intro-to-using-spark-NLP-Bert-word
https://nlpprogress.com/
http://ruder.io/state-of-transfer-learning-in-nlp/
人工智能中的统计方法导论
原文:https://towardsdatascience.com/introduction-to-statistical-methods-in-ai-23f89df72cdb?source=collection_archive---------8-----------------------
文章力求提供关于人工智能中不同统计方法的简明信息
Photo by Daniele Levis Pelusi on Unsplash
统计学习是一套理解数据的工具。这些工具大致分为两类:监督学习和非监督学习。一般来说,监督学习指的是基于一个或多个输入来预测或估计输出。另一方面,无监督学习在没有监督输出的情况下,在给定数据中提供关系或找到模式。
什么是统计学习?
让,假设我们观察到一个反应 y 和 p 不同的预测因子 X = (X₁,X₂,….,Xp)。一般来说,我们可以说:
Y =f(X) + ε
这里 f 为未知函数, ε 为随机误差项。
本质上,统计学习指的是一套估计 f 的方法。
在这种情况下,我们有现成的 X 组,但输出 Y,没有这么多,误差*均为零,我们可以说:
¥ = ƒ(X)
其中表示我们对 f 的估计,表示结果预测。
因此,对于一组预测值 X,我们可以说:
E(Y — ¥)² = E[f(X) + ε — ƒ(X)]²=> E(Y — ¥)² = [f(X) - ƒ(X)]² + Var(ε)
在哪里,
- E(Y — ) 表示实际结果与预期结果的*方差的期望值。
- 【f(X)—ф(X)】代表 可约误差 。它是可简化的,因为我们可以通过更好的建模来潜在地提高的精度。
- Var(ε) 代表不可约误差。它是不可约的,因为无论我们估计得多好,我们都无法减少ε中由方差引入的误差。
回归 Vs 分类问题
变量 Y 可以广义地描述为定量或定性(也称为分类)。量化变量采用数字值,例如年龄、身高、收入、价格等等。估计定性响应通常被称为回归问题 。定性变量采用分类值,例如性别、品牌、词性等等。估计定性反应通常被称为分类问题 。**
统计学中没有免费的午餐:在所有可能的数据集上,没有一种方法能支配所有其他方法。
方差和偏差
方差是指如果我们用不同的训练数据集进行估计时,会发生变化的量。一般来说,当我们在给定的训练数据集上过度拟合模型时(训练集中的可约误差非常低,但测试集中的可约误差非常高),我们得到的模型具有较高的方差,因为数据点的任何变化都会导致显著不同的模型。
偏差指的是通过逼*现实生活中的问题而引入的误差,这可能会因为一个简单得多的模型而变得极其复杂——例如,用线性模型来建模非线性问题。一般来说,当我们过度拟合给定数据集上的模型时,它会导致非常小的偏差。
这导致方差偏差的权衡。
当我们在给定的数据集上拟合模型时,偏差下降的速度往往比方差最初增加的速度快。因此,预期测试误差(可减少的)下降。然而,在某些时候,当过度拟合开始时,对偏差有一点影响,但是方差开始快速增加,当这种情况发生时,测试误差增加。
线性回归
线性回归是一种属于监督学习的统计方法,用于预测定量反应。
简单线性回归 方法基于假设线性关系的单个变量 X 预测定量反应。我们可以说:
**¥ ≈ β₀ + β₁X**
我们现在的工作是基于训练数据集估计 β₀和β₁,我们的模型的参数/系数,使得超*面(在这种情况下是一条线)与训练数据集接*。许多标准可以估计接*程度,最常见的是最小二乘法。
所有观察响应和预测响应之间的差的*方和表示为残差*方和(RSS)。
线性回归中的问题
- 反应-预测值关系的非线性。
- 误差项的相关性。
- 误差项的非恒定方差。
- 异常值:当实际预测值与估计值相差很大时,可能会由于数据记录不准确而出现异常值。**
- 高杠杆点:预测值的异常值会影响称为高杠杆点的回归线。
- 共线性:当两个或两个以上的预测变量彼此密切相关时,剔除单个预测变量的个体效应可能具有挑战性。****
KNN 回归
KNN 回归是一种估计或预测值的非参数方法,它不采用(X)的形式。它通过*均最接* x₀.的所有 N₀响应来估计/预测ƒ(x₀),其中 x₀是预测点我们可以说:
Image by Author
注意:如果 K 很小,拟合将是灵活的,数据的任何变化将导致不同的拟合,因此对于小 K,方差将很高,偏差很低;相反,如果 K 很大,它可能会掩盖数据中的一些结构,因此偏差会很大。
分类问题
我们到目前为止所讨论的反应,可能不总是定量的,也可能是定性的,预测这些定性的反应被称为分类。
我们将讨论分类的各种统计方法,包括:
- SVM
- 逻辑回归
- KNN 分类器
- GAM
- 树木
- 随机森林
- 增压
支持向量机(SVM)
SVM 或支持向量机是最大限度地提高利润率的分类器。在下面的例子中,分类器的目标是找到一条线或(n-1)维超*面,它将 n 维空间中的两个类分开。我已经写了一篇详细的文章解释 SVM 的推导和提法。在我看来,它是我们人工智能统计方法工具箱中最强大的技术之一。
逻辑回归
逻辑模型模拟属于特定类别的输出响应的概率。
我们可以说:
Image by Author
应用componendo dividend to我们得到:
Image by Author
这无非是赔率。
Image by Author
为了估计β系数,我们可以使用最大似然。基本思想是估计β,使得结果的估计值和观察值尽可能接*。在二元分类中,观察到的类为 1 和 0 ,我们可以说似然函数看起来像:
Image by Author
KNN 分类器
KNN(K 最*邻)分类器是一种惰性学习技术,其中训练数据集表示在欧几里德超*面上,测试数据基于 K 欧几里德距离度量被分配标签。
实用方面
- k 应该根据经验选择,最好是奇数,以避免*局。
- KNN 应该有离散的和连续的目标函数。
- 来自不同邻居的加权贡献(例如,基于距离的)可以用于计算最终标签。
注意:当数据是高维时,KNN 的性能会降低。这可以通过向特征本身提供权重来避免。
K 对决策边界的影响
Chapter 8, Pattern Classification by Richard O. Duda, Peter E. Hart, David G. Stork
KNN 的优势
- 我们可以学习复杂的目标函数。
- 任何信息都不会丢失。
KNN 的劣势
- 新实例的分类成本非常高。
- 大量的计算发生在分类的时候。
广义可加模型
GAM 提供了一个广义的框架,用每个变量的非线性函数扩展了标准的多变量线性回归,同时保持了它的可加性。因此,所有非线性函数都可以独立计算并在以后相加。
注:GAM like 线性回归可用于定量和定性响应。
树木、随机森林、助推和装袋
对于涉及将预测空间分割成简单区域的回归和分类,树或决策树都是有用和直接的方法。
典型的决策树是上下颠倒的表示树叶在树的底部。预测器空间被分割的点被称为内部节点,并且叶节点或终端节点是给出预测的节点。连接节点的线段称为分支。
对于预测,我们采取一种自上而下的(在第一个点上所有的观察值都属于一个区域)、贪婪的(在特定步骤中进行最佳分割)的方法,称为递归二元拟合。
有像树修剪这样的策略,通过砍掉一些树枝得到一个小的子树来解决树的过度拟合问题。
对于分类问题,我们或者使用基尼指数,
Image by Author
或者熵
Image by Author
来表示节点的纯度,其中 Pmk 是来自第 k 类的第 m 个区域中的样本的比例。
决策树仍然受到高方差的影响,与其他监督方法相比没有竞争力。因此,我们引入随机森林助推和装袋。
装袋
Bagging 是统计学习方法中减少方差的通用方法。核心思想是对一组观察值进行*均会减少方差。因此,我们对数据进行了多次随机采样,对于每个样本,我们构建了一个树,并对所有预测进行*均,以给出一个低方差的结果。
随机森林
当在袋装树的集合中,从具有总共 m 个预测因子(k < m)的每棵树中随机选择固定的 k 个预测因子,则袋装成为随机森林。
这样做是因为大多数装袋的树看起来差不多一样。因此,单个包树的预测将是高度相关的。因此,我们推论的方差不会有太大的减少。随机森林可以被认为是去相关袋装树的过程。
增压
Boosting 方法是一种缓慢学习的统计方法,其中分类器是在修改的数据集上顺序学习的。在决策树的上下文中,每棵树都是使用来自先前树的信息来生长的。这样,我们就不需要一棵大树了。
无监督学习
以上所有方法都有某种形式的带注释的数据集。但是,当我们想要在没有任何注释的情况下学习数据中的模式时,无监督学习就出现了。
无监督学习最广泛使用的统计方法是 K-Means 聚类。我们在数据集中随机选取 K 个点,并根据它们与 K 个随机点的接*程度,将所有其他点映射到 K 个区域中的一个。然后,我们将 K 个随机点改变为这样形成的簇的质心。我们这样做,直到我们观察到每次迭代后形成的集群中的变化可以忽略不计。
还有其他像无监督学习中的 PCA 这样的技术被大量使用,但是现在,我们就到此为止。
接下来: 人工神经网络简介
流挖掘简介
原文:https://towardsdatascience.com/introduction-to-stream-mining-8b79dd64e460?source=collection_archive---------9-----------------------
流挖掘的简单介绍,支持实时数据分析
想象一下,一个拥有 500 个传感器的工厂每秒钟捕获 10 KB 的信息,一小时内大约捕获 36 GB 的信息,每天 432 GB。需要实时(或在尽可能短的时间内)分析这些海量信息,以检测系统中的异常或偏差,并快速做出反应。流挖掘能够实时分析大量数据。在本文中,介绍了流挖掘,解释了几种技术和有用的资源。
流挖掘支持使用有限资源实时分析大量数据
Figure 1: Industrial sensors can capture high quantities of data Source: commons.wikimedia.org
数据流挖掘是从连续快速的数据记录中提取知识的过程,这些数据以流的形式进入系统。数据流是时间[1,2,4]中实例的有序序列。数据流挖掘满足以下特征:
- 源源不断的数据流。无限流中的大量数据。我们不知道整个数据集
- 概念漂移。数据会随着时间的推移而变化或发展
- 数据的波动。系统不存储接收到的数据(资源有限)。当数据被分析时,它会被丢弃或汇总
Data stream management system. Adapted from de.wikipedia.org
接下来,讨论如何分析数据流。基于数据的技术依赖于对代表性数据子集的分析【3,9】。这种技术也被用作数据流算法的预处理。另一方面,挖掘技术是传统数据挖掘算法的增强版本。
基于数据的技术
采样基于选择均匀分布的数据子集。
- 油藏采样 【固定大小样本】该算法从 stream 中采样一个子集 m 的数据。在以概率 1/i 选择了第 I 个项目之后,如果已经采样了第 I 个元素,则随机替换一个采样的项目
- 最小采样基于将 0 到 1 范围内的随机γ分配给样本 m 的子集。当系统检索 m 个元素时,我们选择γ最小的样本。
素描是基于降低数据集的维度。Sketch 基于执行数据的线性变换,提供流的摘要。请参见最小计数草图。[1]
*似技术基于仅保留数据的子集并丢弃先前的数据(滑动窗口 )[2]:
基于序列的:窗口的大小取决于观察的数量。该窗口存储γ个元素,并且当新元素到达时,如果该窗口已满,则最后一个元素被移除。
- 基于时间戳的:窗口的大小取决于时间。该窗口以时刻 Tn 和 Tn+1 为界,并保存在此期间接收的元素。
采矿技术
存在大量的算法(分类、回归、离群点检测、推荐系统……)用于流挖掘。这些算法需要处理概念漂移、海量数据和有限资源。一些算法需要使用先前的基于数据的技术进行预处理。例如,分类算法的例子有朴素贝叶斯、决策树桩、Hoeffding 树或 ADWIN [8]。
工具
MOA 是一个流行的开源框架,允许处理数据流。MOA 开发了前面提到的一些技术和算法。去年出现了能够分析更多数据的分布式解决方案:Spark Streaming【7】或Apache Storm&Apache Samoa
参考
[1] Mohamed Medhat Gaber、Arkady Zaslavsky 和 Shonali Krishnaswamy。“挖掘数据流:综述”https://sigmodRecord . org/publications/sigmodRecord/0506/p18-survey-gaber . pdf
[2]数据流挖掘https://en.wikipedia.org/wiki/Data_stream_mining
[3] V. Sidda Reddy,T.V Rao 和 Govardhan A .“数据流挖掘的数据挖掘技术”IIETA。链接:http://iieta . org/sites/default/files/Journals/RCES/04.1 _ 06 . pdf
[4] Jure Leskovec,Anand Rajaraman,Jeff Ullman。"挖掘数据流"
[5] Brian Babcock 等人,“数据流系统中的模型和问题
[6]若昂·伽马。从数据流中发现知识。2011
[7] Holden Karau 等人《学习火花:快如闪电的大数据分析》。由…编辑作者是奥莱利。2015
[8]菲利普·克拉宁。流挖掘的任意时间算法。由…编辑《信息与自然科学》。2011
[9] V. Sidda Reddy 和 T.V Rao 和 Govardhan A . .《数据串挖掘的数据挖掘技术》http://iieta . org/sites/default/files/Journals/RCES/04.1 _ 06 . pdf
流处理简介
原文:https://towardsdatascience.com/introduction-to-stream-processing-5a6db310f1b4?source=collection_archive---------9-----------------------
连同机器学习和无服务器流处理似乎是当今最热门的话题之一。公司正在采用现代流处理工具,服务提供商正在发布更好、更强大的流处理产品,对专家的需求很大。
本文介绍了流处理的基础知识。它从为什么我们需要流处理以及它如何在幕后工作的基本原理开始。然后讨论如何编写简单的、可伸缩的分布式流处理应用程序。全部用不到 40 行代码完成!
由于流处理是一个庞大的主题,本文主要关注数据管理部分,而复杂的处理留给另一篇文章。为了使文章更加实用,它讨论了亚马逊的流处理解决方案 AWS Kinesis,但它也参考了其他流行的开源技术,以呈现更广阔的前景。
本文原本为 共同导师网站 撰写。
为什么是流处理
为了理解为什么流处理会出现,让我们看看以前数据处理是如何完成的。以前的方法称为批处理,所有数据都存储在数据库或分布式文件系统中,不同的应用程序将使用这些数据执行计算。由于批处理工具是为处理有限大小的数据集而构建的,为了连续处理新数据,应用程序会定期处理最*一段时间(如一小时或一天)的数据。
虽然这种架构已经工作了很多年,并且仍然有很多应用程序,但是它有一些根本性的缺点。由于新数据不会在到达后立即得到处理,这将导致几个问题:
- 高延迟—新结果仅在显著延迟后计算,但由于数据的值随着时间减少,这是不希望的
- 会话数据—由于批处理系统将数据分割成多个时间间隔,因此很难分析在一个时间间隔内开始但在另一个时间间隔内结束的事件
- 非均匀负载—批处理系统应该等到积累了足够的数据后,才能处理下一个数据块
流处理,也就是数据处理,就是处理一系列的事件。典型的流应用程序由许多生成新事件的生产者和一组处理这些事件的消费者组成。系统中的事件可以是任何数量的事情,例如金融交易、网站上的用户活动或应用程序指标。消费者可以聚合传入的数据,实时发送自动警报,或者生成可由其他消费者处理的新数据流。
这种架构有许多优点:
- 低延迟—系统可以处理新事件并实时做出反应
- 非常适合许多应用程序—流处理系统非常适合处理永无止境的事件流的应用程序
- 统一处理——流处理系统不会等待数据累积后再处理下一批数据,而是在新数据到达时立即执行计算
毫不奇怪,流处理首先被需要实时处理新信息(如交易或价格)的金融公司采用,但现在被用于许多领域,如欺诈检测、在线推荐、监控等。
然而,这个架构提出了一个问题:生产者和消费者应该如何连接?生产者应该向每个消费者开放 TCP 会话并直接发送事件吗?虽然这可能是一个选项,但如果生产者正在编写消费者可以处理的数据,这将是一个严重的问题。此外,如果我们有大量的消费者和生产者,网络连接可能会变成一团乱麻。
这正是 LinkedIn 在 2008 年面临的问题,当时他们最终在多个系统之间建立了多个点对点管道。为了组织它,他们开始着手一个内部项目,最终成为阿帕奇卡夫卡。简而言之,Kafka 是一个缓冲器,允许制作者存储新的流媒体事件,让消费者以自己的速度实时阅读它们。
Apache Kafka 通过为分离的事件驱动应用程序提供数据集成层,迅速成为现代流处理应用程序的骨干。它允许轻松地添加新的消费者和生产者,以及构建更复杂的应用程序。Apache Kafka 变得如此成功,以至于其他公司也建立了类似设计的服务,如 Azure Event Hubs 和 AWS Kinesis 。本文将更详细地讨论后者。
仅附加日志
乍一看,Kafka 和 Kinesis 似乎不是什么大事,因为 RabbitMQ 等替代产品已经存在多年了。然而,如果我们深入了解这些系统,我们会发现它们的设计有所不同,并且支持新用例的实现。
现代流处理软件的基础是一种称为只附加日志的数据结构。日志只是一系列二进制记录。Kinesis 对这些记录的内容没有限制——它们可以是任何格式,比如:JSON、Avro、Protobuf 等。
仅附加日志只允许在日志末尾添加新元素。我们不能在日志的任意位置插入新元素,也不能随意删除元素。日志中的每个元素都有一个序列号,新的元素比旧的元素有更高的序列号。
当一个消费者读取一条记录时,它不会被删除,并且也可以被其他消费者读取。Kinesis 不会跟踪不同的消费者将要阅读哪些记录。相反,这一责任在于消费者。这与 RabbitMQ 等系统不同。它的行为就像一个队列,跟踪每个消费者的状态。
这种架构允许 Kinesis 和 Kafka 这样的系统以低延迟处理数量惊人的事务,远远超过传统消息传递系统的能力。它还允许使用者在启动之前处理写入缓冲区的数据。
请记住,Kinesis 和 Kafka 并没有让 RabbitMQ 过时,仍然有许多 RabbitMQ 更适合的用例。
保存期
此时,您可能想知道,“数据曾经从流中移除过吗?”如果我们迟早不能从流中删除记录,我们将没有足够的空间来存储所有的新记录。
在 AWS Kinesis 和 Apache Kafka 中,记录都有一个保留期,并在该期限结束时自动删除。在 Kinesis 中,记录会在 24 小时后自动删除,但保留期可延长至 7 天。
如果由于某种原因,您的系统无法正确处理传入的数据,并且您需要再次重新处理这些数据,那么延长保留期尤其有益。保留期越长,修复生产系统和重新处理日志的时间就越长。缺点是你必须为额外的存储空间支付更多的费用。
Kafka 允许指定所有记录的最大保留期或最大保留大小。默认的保留期是七天,但是如果启用了日志压缩特性,它甚至可以是无限的。
按比例放大
像 Apache Kafka 和 AWS Kinesis 这样的系统是为了处理数 Pb 的数据而构建的。由于单台机器永远无法处理这种负载,他们需要横向扩展。为了处理巨大的负载,这两个系统都应用了两个众所周知的技巧来允许处理更多的读取和写入:分片和复制。
分片
在流处理的情况下,分片意味着我们有不止一个日志。单个流被分割成多个日志,每个日志都足够小,因此单台机器可以处理它。
为了确定使用哪个碎片,我们需要为每个记录提供一个键。对于每个传入的记录,Kinesis 计算一个键的散列码,散列码的值用于确定哪个碎片将处理它。每个碎片负责散列码值范围的一部分,如果一个键的散列码在一个碎片的范围内,这个碎片将存储一个与之相关的记录。
但是,我们如何为记录找到一个关键字呢?我们可以选择一个随机的键,然后我们的记录将均匀地分布在流的碎片中。我们还可以使用问题领域中的一个密钥,比如一个主机名(如果我们处理指标的话),或者付款人 ID(如果我们处理金融交易的话)。这将允许在具有相同键的记录之间实现排序,因为它们将被定向到相同的碎片。
需要注意的一件重要事情是,因为一个日志被分割成多个片段,所以元素的全局顺序没有被保留。但是,最终出现在同一个碎片上的元素的顺序会被保留。
但是我们应该有多少碎片呢?这取决于我们每秒需要读写多少条记录。我们需要处理的数据越多,我们需要处理的数据流就越多。因此,我们需要能够增加和减少流中的碎片数量。
Kinesis 允许将一个碎片分成两个碎片来处理更多的记录。如果我们需要处理的记录数量减少了,我们可以合并两个具有相邻散列键范围的碎片,并将它们合并到单个碎片中。这反过来会降低吞吐量和我们每月的账单。
[## 用 AWS Kinesis 开发流处理应用程序
AWS Kinesis 是一个强大、实时、灵活、可靠的流处理服务。本课程将教你如何使用 AWS Kinesis、流处理服务和大数据框架构建流处理应用。
bit.ly](http://bit.ly/pluralsight-kinesis)
分身术
与数据库一样,全局复制意味着我们维护数据的多个副本,消费者可以从任何副本中读取数据。在 Kinesis 的情况下,每个记录在三个不同的数据中心有三个副本。
这有两个好处。首先,它使流处理系统对故障更有弹性,因为我们可能会丢失数据的两个副本。其次,它允许向消费者传输更多的数据。这反映在 Kinesis 的限制中,它只允许将最多 1MB 的数据写入单个碎片,并从一个碎片中读取最多 2MB 的数据。
使用 Kinesis
在这个阶段,您应该了解流处理系统是如何工作的,以及它如何处理几乎无限量的传入数据。现在是时候看一些实际的代码示例了。
来源:https://bit.ly/2IQCFjM
在这一节中,我们将看到如何使用低级 API 来读写流数据。我们将实现一个将度量数据写入流的生成器和一个将读取和处理该流的生成器。我们的应用程序应该做到以下几点:
- 创建一个流
- 当我们有新数据时向流发送新记录的生产者
- 在无限循环中读取和处理新记录的消费者
正如许多其他 AWS 服务一样,当我们使用 Kinesis 时,我们不需要提供主机或安装软件。我们所需要做的就是执行几个 API 调用,剩下的工作会替我们完成。这就是 Kinesis 不同于卡夫卡的地方。卡夫卡需要一个复杂的设置,这是很难做到的。
要使用 Kinesis 执行任何操作,我们首先创建一个 Kinesis 客户端:
// **Create** an AWS Kinesis **client**
// You may want **to** **set** **parameters** such **as** AWS region, credentials, etc.
AmazonKinesis kinesis = AmazonKinesisClientBuilder
.standard()
.build();
创建流
首先,让我们创建一个连接生产者和消费者的流。我们所需要做的就是提供我们的流的名称,一个初始的分片数,并调用createStream
方法。
CreateStreamRequest createStreamRequest = new CreateStreamRequest();
// **Set** the **name** **of** a **new** stream
createStreamRequest.setStreamName("metrics-stream");
// **Set** **initial** number **of** shards
createStreamRequest.setShardCount(4);client.createStream(createStreamRequest);
在我们调用了createStream method
之后,我们需要等待一个新的流被激活。为了简洁起见,我省略了这个逻辑,但是您可以在 AWS 文档中阅读完整的代码示例。
实现生成器
现在,当我们有一个流时,我们可以向其中写入一些数据!写入新的数据并不难。首先,对于每个新记录,我们需要创建一个PutRecordRequest
实例,设置一个流名、一个键和我们想要存储在流中的数据。然后我们需要调用putRecord
方法,并将我们的新记录传递给它:
*// A metric data that we need to send*
Metric metric = ...;PutRecordRequest putRecordRequest = **new** PutRecordRequest();
*// Set a stream name. The same as we created in the previous example*
putRecordRequest.setStreamName("metrics-stream");
*// Set metric name as a key of the new record*
putRecordRequest.setPartitionKey(metric.getMetricName());
*// Finally we specify data that we want to store*
putRecordRequest.setData(metric.toBytes());**try** {
kinesis.putRecord(putRecordRequest);
} **catch** (AmazonClientException ex) {
*// Don't forget to process an exception!*
}
这段代码片段向名为metrics-stream
的流发送一条记录。
请记住,无论是 Kinesis 还是 Kafka 都不能保证 100%的正常运行时间!两者都是复杂的系统,许多事情都可能出错,从网络故障到在生产系统上执行无效命令。最重要的是,如果你试图在短时间内写太多数据,AWS Kinesis 甚至可以抑制你的请求。因此,您需要做好准备—实现重试逻辑,并在短时间内在本地缓冲新记录,以防流处理系统不可用。
实现消费者
这都是为了写数据。从流中读取数据有点复杂。在 AWS Kinesis 的情况下,过程如下所示:
- 获取一个迭代器从一个特定的碎片中读取数据
- 发送一个读请求,并提供在上一步中接收到的迭代器
- 一个读请求从一个流和一个新的迭代器返回记录,我们可以用它来发送另一个读请求以读取下一批记录
下面是我们如何让一个迭代器从一个名为shard-0001
的分片中读取记录,从流的开始:
*// Create a request to get an iterator*
**GetShardIteratorRequest** getShardIteratorRequest = **new** **GetShardIteratorRequest**();
*// Specify a name of the stream to read records from*
**getShardIteratorRequest**.**setStreamName**("metrics-stream");
*// Specify what shard to read from*
**getShardIteratorRequest**.**setShardId**("shard-0001");
*// Start reading from the oldest record*
**getShardIteratorRequest**.**setShardIteratorType**("**TRIM_HORIZON**");*// Get an iterator to read data from a stream from a specific shard*
**GetShardIteratorResult** **getShardIteratorResult** = **client**.**getShardIterator**(getShardIteratorRequest);
*// Iterator that we can use to read records from the specified shard*
**String** **shardIterator** = **getShardIteratorResult**.**getShardIterator**();
在这个例子中,我们从流中最老的记录开始读取,但是 Kinesis 支持其他迭代器类型:
- AT_SEQUENCE_NUMBER —从具有指定序列号的记录开始读取
- AFTER_SEQUENCE_NUMBER —从具有指定序列号的记录后开始读取
- AT_TIMESTAMP —从指定的时间戳开始读取记录
- LATEST —从流中最*的记录后开始读取
请注意,我们只能让一个迭代器从单个碎片中读取数据。但是我们怎样才能得到一个碎片的 ID 来读取呢?我们可以通过使用 AWS Kinesis 的ListShards
方法获得特定流的碎片列表,该方法返回关于碎片的信息,包括它们的标识符:
**ListShardsRequest** listShardsRequest = **new** **ListShardsRequest**();
**listShardsRequest**.**setStreamName**("metrics-stream");**ListShardsResult** **result** = **kinesis**.**listShards**(listShardsRequest);**for** (**Shard** shard : result.getShards()) {
*// Get hash key range a shard is responsible for*
**HashKeyRange** **hashKeyRange** = **shard**.**getHashKeyRange**();
*// Returns first a range of records' sequence numbers in a stream*
**SequenceNumberRange** **sequenceNumberRange** = **shard**.**getSequenceNumberRange**();
*// Get a shard id that we can use to read data from it*
**String** **shardId** = **shard**.**getShardId**();
*// Get parent's shard id*
**String** **parentShardId** = **shard**.**getParentShardId**();
}
现在,当我们有一个迭代器时,我们可以从单个碎片中读取数据。由于我们不期望记录流永远不会结束,所以我们在无限循环中读取记录。每当我们从一个流中读取一批新的记录时,我们都会得到一个迭代器,可以用它来执行下一次读取。
**String** shardIterator = ...;**while** (true) {
**GetRecordsRequest** getRecordsRequest = **new** **GetRecordsRequest**();
**getRecordsRequest**.**setShardIterator**(shardIterator);
**getRecordsRequest**.**setLimit**(20);
**GetRecordsResult** **result** = **client**.**getRecords**(getRecordsRequest);
*// Put the result into record list. The result can be empty.*
**List**<**Record**> **records** = **result**.**getRecords**();
**for** (**Record** record: records) {
*// Process each record*
}
**Thread**.**sleep**(200);
**shardIterator** = **result**.**getNextShardIterator**();
}
为什么我们需要睡眠 200 毫秒?这是因为 Kinesis 中的每个碎片每秒允许多达五个读取事务,因此我们最多每 200 毫秒可以读取新记录。我们从碎片中读取的消费者越多,每个消费者应该等待的时间就越长。
因为我们在前面的例子中使用了一个指标名作为键,所以所有同名的指标都将出现在同一个片上。这允许一个碎片的读者处理相同度量的所有数据。在某种程度上,这类似于 MapReduce ,当单个 Reduce 执行使用相同的键处理记录。
高级 API
到目前为止,我们已经知道如何从单个碎片中读取数据,但是通常,我们希望处理一个流中的所有记录。当然,我们可以在一个流中的每个分片上启动一个线程,但是这带来了几个问题:
- 如果在一个流中创建了新的碎片,我们该怎么办?
- 我们如何在多台机器之间分配从流中读取记录的工作?
- 如果我们的一台机器从流中读取失败,我们如何确保我们继续正确地处理记录?
有多个流处理系统可以处理来自 Kinesis 或 Kafka 流的记录,如 Apache Spark、Apache Flink、Google Cloud Dataflow 等。,但是这些都是复杂的工具,超出了本文的范围。在这里,我们将看看如何使用一个叫做 Kinesis 客户端库 (KCL)的更简单的框架。
要使用它,我们需要做两件事:
- 实现一个处理器来处理来自单个分片的记录
- 在一台或多台机器上运行 KCL 工作进程
这就是了。KCL 将确保来自所有碎片的所有记录都得到处理,并且工作在多台机器之间*均分配。
然而,在我们开始之前,让我们简单地谈谈 KCL 是如何分配工作的。KCL 在多个工作者之间分配碎片,每个工作者控制几个处理器,每个处理器处理一个瓦片碎片。这个系统没有“主”节点,每一个 KCL 工作者都是独立于其他工作者的。系统的状态存储在 DynamoDB 表中,并由每个工人不断更新。DynamoDB 表中的每条记录都指定了 Kinesis 流中的一个分片 ID,哪个处理器正在处理它,以及这个分片中最后一条被处理记录的序列号是多少。
每个 KCL 工作者定期从 KCL 流中获取一个碎片列表,并检查是否有没有分配处理器的碎片。如果它发现了任何未分配的碎片,一个 worker 会在 DynamoDB 表中创建一个记录来“获取”一个碎片,并创建一个处理器实例来处理它。如果我们缩小一个流,并且一些碎片被关闭,KCL 也会检测到这一点,并减少处理器的数量,以保持流中处理器和碎片之间的 1:1 关系。
实现处理器
要用 KCL 实现处理器,我们需要实现以下接口:
// Called once before processor starts processing incoming records
public void initialize(InitializationInput initializationInput) {}// Called to process a batch of records read from a Kinesis stream
public void processRecords(ProcessRecordsInput processRecordsInput) {}// Called once before the processor is terminated
public void shutdown(ShutdownInput shutdownInput) {}
}
让我们逐一实现这些方法。
我们需要实现的主要方法是processRecords
。每当 KCL 库读取一组记录时都会调用它,并将它们发送给处理器。在这个方法中,我们需要遍历一个记录列表,处理每个记录(这里我们只是将它的内容打印到控制台),并检查我们的进度。
**@Override**
**public** **void** **processRecords**(ProcessRecordsInput processRecordsInput) {
*// Iterate through a list of new records to process*
**for** (Record record : processRecordsInput.getRecords()) {
*// First we need to deserialize a metric object*
Metric metric = parseMetric(record);
*// Now we can process a single record. Here we just print*
*// record to a console, but we could also send a notification*
*// to a third-party system, write data to a database, calculate*
*// statistics, etc.*
System.out.println(metric);
*// At last, we need to signal that this record is processed*
*// Once a record is processed it won't be sent to our processor again*
checkpoint(processRecordsInput.getCheckpointer(), record);
}
}**private** Metric **parseMetric**(Record record) {
ByteBuffer data = record.getData();
*// Parse binary data that was recorded to a stream*
}**private** **void** **checkpoint**(IRecordProcessorCheckpointer checkpointer, Record record) {
**try** {
checkpointer.checkpoint(record);
} **catch** (InvalidStateException e) {
*// DynamoDB Table does not exists*
*// We need recreate the table*
} **catch** (ShutdownException e) {
*// Two processors are processing the same shard*
*// We need stop processing records in this processor*
}
}
有多种方法来检查进度,我们不一定要在处理完所有记录后才这样做。根据我们的应用程序,它可以每 N 条记录执行一次,或者在我们处理完一批记录后执行一次。
注意,如果 DynamoDB 表不存在,或者如果我们有两个 KCL 记录处理同一个碎片,那么checkpoint
方法会抛出一个异常。
我们需要实现的最后一个方法是shutdown
。这个方法是处理器检查其进程的最后机会,这正是我们在这里要做的:
**public** **void** shutdown(ShutdownInput shutdownInput) {
ShutdownReason reason = shutdownInput.getShutdownReason();
**switch** (reason) {
*// Re-sharding, no more records in current shard*
**case** TERMINATE:
*// Application shutdown*
**case** REQUESTED:
checkpoint(shutdownInput.getCheckpointer(), lastProcessedRecord);
**break**;
*// Processing will be moved to a different record processor*
**case** ZOMBIE:
*// No need to checkpoint*
**break**;
}
}
大部分工作已经完成,但是我们还需要为 KCL 提供一个工厂对象来创建处理器的实例:
**public** **class** **MetricsProcessorFactory** **implements IRecordProcessorFactory** {**public** IRecordProcessor createProcessor() {
**return** **new** **MetricRecordsProcessor**();
}
}
运行 KCL
现在,当我们有了所有的部分,我们需要做的就是启动一个 KCL 工人。我们将在尽可能多的机器上运行这段代码来处理我们的 Kinesis 流。
// Configuration for a worker instance
final KinesisClientLibConfiguration config = new KinesisClientLibConfiguration(
// Name of our application
"metrics-processor",
// Name of stream to process
"metrics-stream",
new DefaultAWSCredentialsProviderChain(),
// Name of this KCL worker instance. Should be different for different processes/machines
"worker-1"
);// Create a factory that knows how to create an instance of our records processor **final** IRecordProcessorFactory recordProcessorFactory = new MetricsProcessorFactory();
// Create a KCL worker. We only need one per machine **final** Worker worker = new Worker.Builder()
**.config**(config)
**.recordProcessorFactory**(recordProcessorFactory)
**.build**();// Start KCL worker
worker.run();
这就是我们实现分布式流处理所需要做的全部工作。KCL 将为每个 Kinesis 碎片启动一个处理器,并将自动在多台机器之间分配负载。
注意,KCL 可以启动额外的线程。但是,如果您需要更多的机器来处理传入的记录,您需要自己处理。如果您使用 AWS,您可以使用自动扩展组在 CPU 利用率过高时自动添加更多机器。
代码示例
为了让这些概念更加实用,我实现了一个小型的 GitHub 项目,展示如何使用 AWS Kinesis。您可以浏览代码并运行工作示例。它由几个小应用程序组成,这些应用程序创建 AWS 资源,产生流数据,并从流中读取数据。
结论
这是对流处理领域的简要介绍。现代流处理系统基于仅附加的日志数据结构,该结构允许构建数据摄取基础设施。流处理系统允许生产者向日志中写入新记录,多个消费者可以并行地从日志中读取记录。我们还介绍了如何使用 AWS Kinesis 创建简单的流处理应用程序
这篇文章只是触及了这个话题的表面。它没有涵盖流中的窗口、流处理框架、流数据中的时间概念、流 SQL(我知道这听起来有点矛盾!),等等。,我希望在接下来的文章中涵盖这些和许多其他主题。
嗨!我叫 Ivan Mushketyk,是一名狂热的软件工程师、开源贡献者、博客作者,也是 Pluralsight 、 Udacity 和 Coursera 的课程作者。
如果你喜欢这篇文章,你可以观看我的深潜 Pluralsight 课程 使用 AWS Kinesis 开发流处理应用 ,它涵盖了 AWS Kinesis 的内部和外部。
带权重和偏差的张量流简介
原文:https://towardsdatascience.com/introduction-to-tensorflow-with-weights-and-biases-cd97636e820f?source=collection_archive---------22-----------------------
在本教程中,我将带您通过一个简单的卷积神经网络,使用 TensorFlow 对 FashionMNIST 中的图像进行分类。我将首先设置权重&偏差来记录模型度量,然后检查模型性能,最后,分享用于该图像分类问题的卷积神经网络的最佳架构的发现。
为了给你一些背景,Weights & Biases 帮助你跟踪你的机器学习实验。您可以使用该工具记录您跑步的超参数和输出指标,然后可视化和比较结果,并快速与您的同事分享发现。
您可以将它视为 Tensorboard 的一个很好的替代方案,tensor board 是 TensorFlow 的一个扩展,允许在浏览器中轻松监控模型。Tensorboard 的问题是,当它在本地运行时,很难保存信息或在团队中共享结果。此外,您可以为所有配有砝码和偏差的跑步提供 Tensorboard。
在这个例子中,我将使用 Google Colab 作为一个方便的托管环境,但是您可以从任何地方运行自己的培训脚本,并使用 W&B 的实验跟踪工具可视化指标。
入门
- 打开这个 Colab 笔记本。
- 单击“在操场上打开”为自己创建此笔记本的副本。
- 在 Google Drive 中为自己保存一份副本。
- 浏览下面的每个部分,按代码块上的 play 运行单元。
结果将被记录到 a 共享 W & B 项目页面。
训练模型
让我们回顾一下我在上面的 Colab 笔记本中使用的关键 wandb 命令。
设置
- pip 安装 wandb —安装 W & B 库
- 导入 wandb —导入 wandb 库
- wandb 登录 —登录您的 W & B 账户,这样您就可以在一个地方记录您的所有指标
- wandb.init() —初始化一个新的 W & B 运行。每次运行都是训练脚本的一次执行。
初始化超参数
- wandb.config —将所有的超参数保存在一个配置对象中。您可以使用我们的应用程序,通过超参数值对您的跑步进行排序和比较。
追踪结果
- wandb.log() —记录您的指标,以便您可以可视化您的神经网络随时间推移的性能。
可视化结果
一旦你训练了你的模型,你可以可视化你的模型所做的预测,它的训练和损失,梯度,最佳超参数,并审查相关的代码。
要查看此打开项目中的人员创建的跑步记录:
- 查看项目页面。
- 展开 runs 表,比较每个尝试过该脚本的人的所有结果。
- 单击一次跑步的名称,在其跑步页面上深入了解该次跑步。
可视化渐变
单击单次运行,查看有关该运行的更多详细信息。例如,在这个运行页面上,您可以看到我运行这个脚本时记录的梯度。
审查代码
overview 选项卡选择代码的链接。在这种情况下,这是一个链接到我工作的 Google Colab。如果您正在运行 git repo 中的脚本,我们将获取最新 git 提交的 SHA,并在您自己的 GitHub repo 中为您提供该版本代码的链接。
接下来的步骤
你应该尝试分叉这个 colab 笔记本,调整一些超参数,看看你是否能最大化验证准确性。祝你好运!
TF-Agents 简介:TensorFlow 中的强化学习库
原文:https://towardsdatascience.com/introduction-to-tf-agents-a-library-for-reinforcement-learning-in-tensorflow-68ab9add6ad6?source=collection_archive---------18-----------------------
通过 Tensorflow 中灵活而强大的强化学习库来训练您自己的 AI 机器人
Example of an untrained agent playing the CartPole game
今天的主题是 Tensorflow 最新的强化学习库,名为 TF-Agents。这个库相当新,大约一年前才对外开放。因此,与其他流行的强化学习库相比,它严重缺乏适当的文档和教程。在本教程中,我们将学习设置和运行官方文档提供的教程的正确方法。内容分为以下几类:
- 装置
- 例子
- 结论
事不宜迟,我们开始吧!
1.装置
我在这个项目中使用的是 Ubuntu 18.04.2 LTS,但是下面的步骤应该适用于任何其他操作系统。根据您正在使用的内容相应地修改命令。
虚拟环境
首先,我们需要一个新的虚拟环境来完成这个项目。将项目分离到它自己的虚拟环境中是一个好主意。打开终端,进入你选择的目录。然后,运行以下代码:
python3 -m venv tfagent
将在同一目录中创建一个名为 tfagent 的新文件夹。通过运行以下命令来激活它:
source tfagent/bin/activate
您应该会看到以下输出
Pip 升级(可选)
将 pip 模块更新到最新版本总是一个好主意。如果您不确定是否拥有最新版本,请运行以下命令
python3 -m pip install --upgrade pip
Jupyter 笔记本
接下来,我们将安装 Jupyter Notebook,这是一个基于 web 的交互式开发环境,可以提供更流畅的体验。强烈推荐给那些参与数据科学任务的人。运行以下命令:
python3 -m pip install jupyter
TF-每晚
如果您一直遵循官方网站提供的教程,您会注意到它将具有以下代码:
...
import tensorflow as tf
from tf_agents.agents.reinforce import reinforce_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import actor_distribution_network
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common
...
我们不打算安装 tensorflow,但只为 CPU 的预览版本称为 tf-nightly。这个模块相当不稳定,但是 tf-agent 需要它。官方网站建议我们通过以下代码安装最新版本:
python3 -m pip install --upgrade tf-nightly
它将安装 tf-nightly 和 tf-nightly-estimator。这两个模块可能有不同的版本。
TFP-每晚
除此之外,我们还需要安装 tfp-nightly,这是一个用于 TensorFlow 中概率推理和统计分析的库。运行以下命令:
python3 -m pip install tfp-nightly
TF-代理-每夜
我们现在已经为 tf 代理模块做好了准备。在继续之前,请确保您已经安装了 tf-nightly 和 tfp-nightly。在终端中键入以下命令并运行它:
python3 -m pip install tf-agents-nightly
我使用的模块版本如下:
降级 gast
如果您遇到某些模块的任何问题,例如以下问题,您需要修改模块的版本:
AttributeError: module 'gast' has no attribute 'Ellipsis'
对于 gast,我们需要将其设置为以下版本:
python3 -m pip install gast==0.2.2
其他 python 模块
官方教程需要以下模块才能正常工作。逐一执行以下命令来安装它们:
python3 -m pip install gym==0.10.11
python3 -m install imageio==2.4.0
python3 -m install pyglet==1.3.2
python3 -m install pyvirtualdisplay
python3 -m install matplotlib
2.例子
我们将使用最初的 DQN 教程作为例子。代码和步骤非常简单。您需要通过以下命令启动 jupyter notebook:
jupyter notebook
它将在您的默认浏览器中打开一个选项卡,带有以下 url
[http://localhost:8892/tree](http://localhost:8892/tree/work)
创建一个新的 Python3 文件。然后,前往 DQN 教程,并开始复制和粘贴笔记本内的代码。您可以独立运行每个单元。让我们来看看如果一切正常,你会看到什么。
渲染环境
下面的代码将渲染环境并向您输出一个显示游戏外观的图像。
env.reset()
PIL.Image.fromarray(env.render())
结果如下:
规格
time_step_spec ()方法返回时间步长元组的规范。
print('Observation Spec:')
print(env.time_step_spec().observation)
print('Reward Spec:')
print(env.time_step_spec().reward)
print('Action Spec:')
print(env.action_spec())
您应该得到以下输出
A .观察是 4 个浮点数的数组:
- 手推车的位置和速度
- 极点的角位置和速度
B .奖励是一个标量浮点值
C. Action 是一个标量整数,只有两个可能的值:
- 0 —“向左移动”
- 1 —“向右移动”
培养
在你达到“培训代理”这一步之前,一切都应该很好。尝试运行 Jupyter Notebook 的单元格中的代码会遇到错误。
"UsageError: Line magic function %%time not found."
这只是因为按照惯例,魔法函数应该从第一行开始。只需删除该命令,并将%%time 作为单元格中的第一行。运行之后,您应该能够看到下面的输出。
它需要一些时间来运行。预计时间约为 5 分钟。最终输出如下所示
形象化
您可以使用 matplotlib 模块来可视化训练结果。一次迭代由 200 个时间步组成。玩家每走一步,杆子就会得到 1 点奖励。结果一集最高收益 200。让我们运行下面的代码:
iterations = range(0, num_iterations + 1, eval_interval)
plt.plot(iterations, returns)
plt.ylabel('Average Return')
plt.xlabel('Iterations')
plt.ylim(top=250)
您的图表应该是这样的(可能会有一些小的差异):
录像
最后一部分是渲染一个视频来显示代理在玩游戏。您应该能够看到如下的训练版本:
我注意到它在站立不动的状态下*衡杆子,表现得非常好。未经训练的代理看起来像这样
3.结论
恭喜你!你已经成功地训练了一个能玩翻筋斗的特工。让我们回顾一下今天所学的内容。首先,我们从建立虚拟环境开始。然后,我们安装了必要的 python 模块。同时,我们还需要降级 gast 模块来纠正一些错误。
接下来,我们按照教程提供的渲染图像和设置所需的参数。之后,我们用 DQN 学习算法训练了一个代理。培训大约需要 5 分钟。
最后,我们尝试使用 matplotlib 来可视化它,并呈现两个视频来显示训练有素的代理和未训练的代理之间的差异。
非常感谢,祝你有美好的一天!
参考
- https://github.com/tensorflow/agents
- https://github . com/tensor flow/agents/blob/master/TF _ agents/cola bs/1 _ dqn _ tutorial . ipynb
基于内容推荐系统的两种方法介绍
原文:https://towardsdatascience.com/introduction-to-two-approaches-of-content-based-recommendation-system-fc797460c18c?source=collection_archive---------5-----------------------
解决困惑的完整指南
基于内容的过滤是构建推荐系统的常用方法之一。当我试图做一些研究来理解细节时,有趣的是看到有 2 种方法声称是“基于内容的”。下面我将分享我的发现,如果你曾经对这个定义感到困惑,希望它能节省你的研究时间。
本文将涵盖:
- 方法 1 —仅分析内容描述
- 方法 2——从用户评价的内容建立用户简档和项目简档
- 两种方法的利弊
本文将重点解释这两种方法的主要区别,可能不会详细讨论编码。请访问这里的库获取各自的 Jupyter 笔记本,你会发现这两种方法的 Python 实现!
Content-based recommendation system (approach 2) simply analyses what you love — Photo Credit: Jason Leung
方法 1:只分析内容的描述
根据我的理解,方法 1 类似于 基于项目的协同过滤 。简而言之,系统会推荐任何与你之前喜欢的某个物品相似的东西。
在建模阶段,系统首先找到所有项目对之间的相似性,然后在推荐阶段使用与用户已评分项目最相似的项目来生成推荐列表。
例如,如果有人观看《明日边缘》,系统可能会基于相似性推荐 Looper。
H 如何找到物品之间的相似性?
通常相似性将从项目的描述中导出,并且将引入 TF-IDF 的概念。那么每个项目将由一个 TF-IDF 向量来表示。
词频-逆文档频率(TF-IDF)
TF-IDF 属于自然语言处理(NLP)的子领域。它在信息检索中用于特征提取目的。简而言之,你以某种方式计算每个单词在文档中的出现次数,衡量每个单词的重要性,并计算该文档的分数。
词频
当前文档中单词占文档总字数的频率。它表示该单词在文档中出现的次数,当出现的次数越多,权重就越高,所以用它除以文档长度进行归一化。
逆文档频率
文档总数与包含该单词的文档的出现频率之比。它表示单词的稀有性,因为文档中出现的单词越少,IDF 就越大。这有助于给文档中的罕见术语更高的分数。
最后,TF-IDF 是用于评估一个单词对文档语料库中的文档有多重要的度量。单词的重要性与单词在文档中出现的次数成比例地增加,但是被单词在语料库中的频率抵消。
由于方法严重依赖描述来区分每个项目,描述应深入到产品细节,即标题、摘要、标语、流派,以便提供更多关于项目的信息。
TF-IDF 载体
在为标签定义了 TF-IDF 值之后,我们就可以为每个项目创建关键字向量了。下面每一行代表一个项目的关键字向量。关于 TF-IDF 的详细计算,你可以参考这里的一篇文章。
比较项目 TF-IDF 向量的相似性
为了计算项目向量的相似程度,我们可以使用各种方法,例如:
- 余弦相似性
- 欧几里得距离
- 皮森相关
那么推荐器将基于最相似的项目给出推荐。
我试着实现了这三种方法,我发现在推荐的项目上没有明显的区别。你可以从这个 Jupyter 笔记本中找到我的全部代码。范例数据集——图书穿越数据集可点击此处下载。
方法 2:从用户评价的内容建立用户简档和项目简档
这种方法类似于维基百科中的定义。
方法 2 利用来自用户已经交互的项目的描述或属性来推荐相似的项目。它仅依赖于用户先前的选择,使得该方法对于避免冷启动问题具有鲁棒性。对于文本项目,如文章、新闻和书籍,很容易使用文章类别或原始文本来构建项目简档和用户简档。
假设我观看一部特定类型的电影,我将被推荐该特定类型的电影。片名、上映年份、导演、演员也有助于识别类似的电影内容。
在这种方法中,产品的内容已经基于用户偏好(用户简档)被分级,而项目的类型是一个隐含特征,它将用于建立项目简档。然后通过使用两个简档来预测项目分数,并且可以进行推荐。与方法 1 相似,TF-IDF 技术也将用于该方法。
如何建立用户档案和物品档案?
通常rating table
(用户评分)item profile
(书籍类型)是我们仅有的资料。
rating table
:用户与图书的关系item profile
:属性与账簿的关系
然后我们将创建user profile
,这样我们就可以了解用户实际上更喜欢什么属性。
user profile
:用户-属性关系
因此,使用user profile
,我们可以根据他/她的user profile
和item profile
预测特定用户的所有项目得分。
你可以从这本 Jupyter 笔记本中找到我的方法 2 的完整代码。虽然这种方法需要像书籍流派这样的信息,并且它不在图书交叉数据集中,但报废是使用谷歌图书 API 来检索附加信息。报废信息可以在这里找到。
两种方法的利弊
方法 1
优点:
- 与协同过滤不同,如果项目有足够的描述,我们就避免了“新项目问题”。
- 内容表示是多种多样的,它们提供了使用不同方法的选择,如:文本处理技术、语义信息的使用、推理等
- 很容易建立一个更透明的系统:我们使用相同的内容来解释推荐。
缺点:
- 基于内容的 RecSys 趋向于过度专业化:他们会推荐与已经消费过的商品相似的商品,并倾向于创建一个“过滤气泡”。
方法 2
赞成的意见
- 用户独立性:协同过滤需要其他用户的评分来发现用户之间的相似性,然后给出建议。相反,基于内容的方法只需要分析项目和用户简档来进行推荐。
- 透明:协作式方法给你推荐是因为一些未知的用户和你有相同的品味,但是基于内容的方法可以告诉你他们是基于什么特征给你推荐的。
- 无冷启动:与协同过滤相反,新项目可以在被大量用户评级之前被建议。
骗局
- 有限内容分析:如果内容没有包含足够的信息来精确区分项目,推荐将不会精确到最后。
- 过度专门化:基于内容的方法提供了有限程度的新颖性,因为它必须匹配简档和项目的特征。一个完全完美的基于内容的过滤可能没有什么“惊喜”
- 新用户:当没有足够的信息为用户建立可靠的档案时,无法正确提供推荐。
P.S. 以上发现来自我在数据科学训练营的合作项目。如果你有兴趣了解更多关于其他推荐系统(协同过滤、潜在因素分析)的信息,请访问这个知识库。
参考
https://www . analyticsvidhya . com/blog/2015/08/beginners-guide-learn-content-based-recommenders-systems/https://towardsdatascience . com/learning-to-make-recommenders-745d 13883951
优步《路德维希》简介
原文:https://towardsdatascience.com/introduction-to-ubers-ludwig-cdaa67245cfa?source=collection_archive---------9-----------------------
无需编写代码即可创建深度学习模型
Figure 1: Ludwig Logo (Source)
优步的人工智能实验室继续开源深度学习框架,并发布了最新版本 Ludwig,这是一个基于 TensorFlow 的工具箱,允许用户在不编写代码的情况下创建和训练模型。
为您的模型找到正确的模型架构和超参数是深度学习管道的一个困难方面。作为一名数据科学家,您可以花几个小时试验不同的超参数和架构,以找到最适合您的特定问题的方法。这个过程不仅耗时、代码密集,而且需要了解所有使用的算法和最先进的技术,这些都是用来挤出最后的性能百分比的。
Ludwig 试图为你提供一个工具箱,让你不用写代码就可以训练和测试你的深度学习模型。这有助于没有很多深度学习知识的领域专家建立他们自己的高性能模型。
路德维希
过去两年,优步在内部开发了 Ludwig,以精简和简化深度学习模型的使用。他们已经在自己的几个项目中见证了它的价值,例如从驾照中提取信息、在驾驶员-合作伙伴和乘客之间的对话中识别兴趣点等等。出于这个原因,他们决定将其作为开源软件发布,这样每个人都可以获得 Ludwig 提供的灵活性和易用性。
路德维希遵循以下核心原则:
- 不需要编码:不需要编码技能来训练一个模型并使用它来获得预测。
- 通用性:一种新的基于数据类型的深度学习模型设计方法,使该工具可以跨许多不同的用例使用。
- 灵活性:有经验的用户对模型的建立和训练有广泛的控制,而新手会发现很容易上手。
- 扩展性:易于添加新的模型架构和新的特征数据类型。
- 可理解性:理解模型性能并比较其预测的标准可视化。
Ludwig 允许我们通过只提供一个包含数据的文件来训练深度学习模型,如 csv 和 YAML 配置文件,其中我们需要指定关于我们的数据文件中包含的特征的一些信息,如它们是因变量还是自变量。如果指定了一个以上的相关/输出变量,Ludwig 将学会同时预测所有的输出。
Ludwig 背后的主要新思想是特定于数据类型的编码器和解码器的概念。这些特定类型的编码器和解码器可以在配置文件中设置,并为我们提供一个高度模块化和可扩展的架构,该架构对每种类型的数据都有特定的预处理步骤。
Figure 2: Different input and output features (Source)
这种设计为用户提供了许多不同的功能和选项,允许他们在不需要大量深度学习知识的情况下为特定领域构建尖端模型。
使用路德维希
要使用 Ludwig,我们需要安装它,这可以通过以下命令完成:
pip install git+[https://github.com/uber/ludwig](https://github.com/uber/ludwig)
python -m spacy download en
下一步是创建我们的模型定义 YAML 文件,它指定了我们的输入和输出特性,以及一些关于我们想要采取的特定预处理步骤的附加信息。
但是在我们创建这个文件之前,我们需要决定我们想要使用什么数据集。对于这篇文章,我决定使用 Twitter 美国航空公司情绪数据集,它可以免费下载。
现在我们有了数据集,我们可以开始编写模型定义了。
input_features:
-
name: text
type: textoutput_features:
-
name: airline_sentiment
type: category
准备好 YAML 配置文件后,我们可以使用以下命令开始训练我们的模型:
ludwig train –data_csv Tweets.csv –model_definition_file model_definition.yaml
Ludwig 现在将随机数据分为训练集、验证集和测试集,对它们进行预处理,然后用指定的编码器和解码器建立一个模型。
它还在控制台内显示训练过程,并提供张量板功能。
训练之后,Ludwig 创建了一个结果目录,其中包含了经过训练的模型及其超参数,以及一些可用于可视化训练过程的汇总统计数据。可以使用以下命令执行这些可视化之一:
ludwig visualize –visualization learning_curves –training_stats results/training_stats.json
这将显示一个图形,该图形显示了作为历元数的函数的损失和精度。
Figure 3: Loss and accuracy plots (Source)
训练之后,我们可以通过键入以下内容来使用该模型进行预测:
ludwig predict –data_csv path/to/data.csv –model_path /path/to/model
Ludwig 的编程 API
Ludwig 还提供了 Python 编程 API,允许我们使用 Python 训练或加载模型。上面的问题可以使用如下所示的编程 API 来实现。
推荐读物
[## Keras 深度学习简介
如何使用 Keras 深度学习库
towardsdatascience.com](/introduction-to-deep-learning-with-keras-17c09e4f0eb2)
结论
Ludwig 是一个构建在 TensorFlow 之上的工具箱,允许用户在不编写代码的情况下创建和训练模型。
它为我们提供了许多不同的功能和选项,如数据类型特定的编码器和解码器,允许我们建立尖端的深度学习模型。
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道,在社交媒体上关注我。
本文涵盖的代码可以从 Github 资源库获得。
如果你有任何问题、建议或批评,可以通过 Twitter 或评论区联系我。
视频分类介绍
原文:https://towardsdatascience.com/introduction-to-video-classification-6c6acbc57356?source=collection_archive---------8-----------------------
许多深度学习文章和教程主要关注三个数据领域:图像、语音和文本。这些数据域因其在图像分类、语音识别和文本情感分类中的应用而广受欢迎。另一个非常有趣的数据形式是视频。从维度和大小的角度来看,视频是与社交网络或遗传密码等数据集一起最有趣的数据类型之一。YouTube 等视频上传*台正在收集庞大的数据集,为深度学习研究提供支持。
视频实际上只是一堆图像。本文将回顾一篇关于视频分类研究的论文[1],该研究由现任特斯拉人工智能总监 Andrej Karpathy 领导。
https://static . Google user content . com/media/research . Google . com/en//pubs/archive/42455 . pdf
本文使用卷积网络对视频进行建模,其方式与 CNN 对图像建模的方式非常相似。这篇论文是卷积网络强大表示能力的一个好例子。在这项工作之前,视频分类研究主要由一系列视觉词袋特征组成,这些特征被量化到 k-means 字典中,并用 SVM 等机器学习模型进行分类。这项工作突出了细胞神经网络的力量,抽象出所有这些以前的特征工程算法。该论文也为将视频的时间成分集成到 CNN 模型中的想法提供了良好的基础。
本文探讨了视频分类的三个不同组成部分,设计了考虑视频中时间连通性的细胞神经网络,可以加速计算的多分辨率细胞神经网络,以及视频分类的迁移学习的有效性。
讨论的数据集
任何深度学习项目最重要的组成部分之一是对正在使用的数据集的理解。本文使用了由 487 个类别的100 万个 YouTube 视频组成的数据集。本文还对从这个大规模数据集学习到的特征到更小的 UCF-101 数据集的迁移学习进行了实验,该数据集由属于 101 个类别的 13320 个视频组成。
有两个与所使用的视频数据集相关的直接问题。首先是数据集的巨大规模,因此将整个数据集加载到本地内存的前景是不切实际的。一种解决方法是使用 url 解析库从视频的 youtube 链接动态下载视频,并覆盖当前在内存中的视频,这些视频是在以前的批量中使用的。为了加快速度,使用了并行计算系统,使得这些批次可以在与训练模型的机器不同的单独机器上加载和预处理。Karpathy 等人使用计算集群来实现这些实验,这非常适合这种数据处理流水线。
这个数据集的第二个问题是文本挖掘应用程序经常遇到的问题,即每个实例的可变长度。例如,一个视频可能是 30 秒,而另一个是 2 分钟。在文本中,这可以通过用 0 填充文本的末尾来解决,这样所有的输入都是相同的长度。本文通过对视频中的作物进行预测并汇总所有作物的预测来解决这一问题。我认为这是需要记住的一个非常重要的细节。整个视频并没有被传送到网络上,而是使用了半秒钟的剪辑。视频通常以每秒 30 帧的速度录制。因此,这些剪辑由 15 帧组成。
聚合半秒剪辑的预测与图像分类中的测试时间增强是一个类似的概念。图像的类别预测与旋转、剪切、裁剪或增强颜色空间后的同一图像的预测相结合。这些视频分类实验还测试了半秒剪辑的翻转和裁剪增强。
时间信息融合
CNN 架构中的哪种时间连接模式最能利用视频中的局部运动信息?
额外的运动信息如何影响 CNN 的预测,它对整体性能的改善有多大?
也许本文最有趣的主题是如何修改经典卷积网络以解释视频中的时间依赖性。在本文中,一堆帧一个接一个地连接起来,输入到 CNN。传统上,CNN 采用一个(高×宽×颜色通道)矩阵作为输入。例如,这可能是一个 224 x 224 x 3 的输入张量。在这些实验中,先前的帧堆叠在颜色通道轴的顶部,使得由视频中的两个图像帧组成的输入具有 224 x 224 x 6 的形状。Karpathy 等人提出了 3 种不同的策略来组合作为 CNN 输入的帧,并将这些方法与一次分类一个帧的基线模型进行对比。
单帧模型是通过简单地聚合单帧/图像的预测来对视频进行分类的一个例子。后期融合模型通过连接剪辑中的第一帧和最后一帧来组合帧。早期的融合模型从剪辑中取出较大的连续片段。最后,慢融合模型具有更复杂的方案,其中 4 个部分重叠的连续段在卷积层中被渐进地组合。实验发现慢融合策略获得了最大的个体成功,尽管并没有显著大于单帧模型。通过对所有模型的结果进行*均,找到了最佳的总体结果,(单一+早期+晚期+缓慢)。
多分辨率 CNN
本文讨论的另一个非常有趣的概念是一个引人注目的图像处理策略。多分辨率 CNN 工作如下:两个独立的输入被馈送到独立的卷积层,在两个独立的 conv-最大池-批处理序列之后融合在一起。这些多分辨率输入由下采样为 89 x 89 的 178 x 178 帧和原始 178 x 178 帧的中心 89 x 89 裁剪组成。
这种策略为卷积层节省了大量的计算时间。作者报告说,由于这种降维方案,速度提高了 2-4 倍。具体来说,他们引用了全帧网络每秒 5 个剪辑的速度和多分辨率网络每秒 20 个剪辑的速度。他们还强调,如果使用高端 GPU,而不是在拥有 10–50 个模型副本的计算集群中进行并行化,这可以进一步加快速度。除了加速之外,它还报告了比单帧模型小的改进,单帧模型采用原始的 178 x 178 帧。
视频分类中的迁移学习
图像分类中的迁移学习已经被大量研究,并且是一个非常直观的概念。在 ImageNet 这样的海量数据集上训练,1.2M 的图片,把这些权重转移到一个数据较少的问题上,然后在新的数据集上微调权重。在本文中,Karpathy 等人将 Youtube-1M 数据集的特征转移到流行的视频分类数据集 UCF-101。他们实验了三个层次的迁移学习,并在 UCF-101 数据集上与从头开始的训练进行了比较。
所研究的迁移学习水*包括微调顶层、微调前 3 层和微调所有层。例如,当微调顶层时,网络中的其余权重在训练期间被“冻结”,这意味着它们只参与网络的正向传递,而不通过反向传播进行更新。
从本文来看,时间融合和多分辨率策略带来的性能提升并不显著。然而,迁移学习的结果令人大开眼界。如果这份报告也显示了单框架网络的结果,以对比慢速融合方案是否对迁移学习更有效,这将是很有趣的。
结论
我对报告的结果印象深刻,慢融合方案始终优于单帧模型。在这篇论文中,我期望时间融合算法由 CNN 特征组成,并输入到一个递归模型中,如 LSTM。我认为慢速融合的设计可以通过简单地加倍相邻块的大小来改进,也许可以通过一些参数数量的帧来连接相邻块,并添加剩余连接。
我认为多分辨率处理图像和视频是一个非常有趣的想法,可以扩展到语音和音频。这种机制主要设计用于在输入尺寸减小的情况下提高计算速度,但是,我认为在使用超分辨率技术(如 SR-GANs)对图像进行上采样后,反转这一点并测试分类精度会很有意思。
令人鼓舞的是,图像迁移学习的成功扩展到了视频。在 YouTube-1M 数据集上训练后,UCF-101 的准确率提高了* 25%,高得令人震惊!
本文为探索视频分类奠定了良好的基础。它写得非常好,讨论了在视频数据上建立深度学习模型的许多重要特征。感谢阅读,请在纸上或这篇文章上留下你的想法!
参考
[1]安德烈·卡帕西、乔治·托代里奇、桑克思·谢蒂、托马斯·梁、拉胡尔·苏坦卡尔、李菲菲。基于卷积神经网络的大规模视频分类。2014.
Selenium 和 Python 网页抓取简介
原文:https://towardsdatascience.com/introduction-to-web-scraping-with-selenium-and-python-85920d41722d?source=collection_archive---------28-----------------------
关于如何开始使用 Selenium 的实用教程
当你需要数据时,网络抓取是一种快速、经济、可靠的获取方式。更好的是,数据通常是最新的。现在,请记住,当抓取一个网站时,你可能会违反其使用政策,并可能被踢出网站。虽然抓取大部分是合法的,但根据您打算如何使用数据,可能会有一些例外。所以在开始之前,一定要做好调查。然而,对于一个简单的个人或开源项目,你应该没问题。
抓取数据的方法有很多,但我最喜欢的一种是使用 Selenium 。它主要用于测试,因为它主要做的是浏览器自动化。用简单的语言来说,它创建了一个机器人浏览器,为你做事情:它可以获得 HTML 数据,滚动,点击按钮等。最大的好处是我们可以明确地说出我们想要什么样的 HTML 数据,这样我们就可以适当地组织和存储它。
Selenium 与许多编程语言兼容,但是本教程将重点介绍 Python。检查此链接以阅读 Selenium(使用 Python)文档。
第一步
要下载 Selenium,请在命令行中使用这个简单的命令:
pip install selenium
如果你在 Jupyter 笔记本上工作,你可以直接在那里而不是命令行上完成。开头加个感叹号就行了:
!pip install selenium
之后,您需要做的就是导入必要的模块:
from selenium.webdriver import Chrome, Firefox
也支持其他浏览器,但这两种是最常用的。
开始时需要两个简单的命令:
browser = Firefox()
(或browser = Chrome()
取决于你的喜好)
这创建了一个 Firefox WebDriver 的实例,允许我们访问它所有有用的方法和属性。我们把它赋给了变量browser
,但是你可以自由选择你自己的名字。Firefox 浏览器将自动打开一个新的空白窗口。
接下来获取您想要抓取的 URL:
browser.get('https://en.wikipedia.org/wiki/Main_Page')
get()
方法将在浏览器中打开 URL,并等待它完全加载。
现在你可以从这个 URL 获得所有你想要的 HTML 信息。
定位元件
用硒定位元素有不同的方法。哪一个是最好的,取决于你抓取的页面的 HTML 结构。找出访问您想要的元素的最有效的方法可能很棘手。所以请慢慢来,仔细检查 HTML。
您可以使用选择的搜索参数访问单个元素(您将获得与您的搜索参数对应的第一个元素),也可以访问与搜索参数匹配的所有元素。要获得单个,请使用以下方法:
find_element_by_id()
find_element_by_name()
find_element_by_xpath()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_tag_name()
find_element_by_class_name()
要定位多个元素,只需在上述方法中将element
替换为elements
。您将获得通过该方法定位的 WebDriver 对象的列表。
抓取维基百科
所以让我们看看它是如何与已经提到的维基百科页面https://en.wikipedia.org/wiki/Main_Page一起工作的
我们已经创建了包含 WebDriver 实例的browser
变量,并加载了 Wikipedia 主页面。
假设我们想要访问该页面可以翻译成的语言列表,并存储所有指向这些语言的链接。
经过一些检查,我们可以看到所有元素都有相似的结构:它们是类'interlanguage-link'
的<li>
元素,包含带有 URL 和文本的<a>
;
<li class="interlanguage-link interwiki-bg"> <a href="https://bg.wikipedia.org/wiki/" title="Bulgarian"
lang="bg" hreflang="bg" class="interlanguage-link-target">
Български </a> </li>
所以让我们首先访问所有的<li>
元素。我们可以使用类名来隔离它们:
languages = browser.find_elements_by_class_name('interlanguage-link')
languages
是 WebDriver 对象的列表。如果我们打印它的第一个元素:
print(languages[0])
它会打印出这样的内容:
<selenium . web driver . Firefox . web element . Firefox web element(session = " 73e 70 f 48–851 a-764d-8533–66f 738 D2 BCF 6 ",element = " 2a 579 b 98–1a 03-b04f-AFE 3–5d 3 da 8 aa 9 EC 1 ")>
所以要真正看到里面有什么,我们需要写一个 for 循环来访问列表中的每个元素,然后访问它的<a>
子元素,并获得<a>
的文本和'href'
属性。
要获取文本,我们可以使用text
属性。使用get_attribute('attribute_name')
方法获得'href'
。因此,代码将如下所示:
language_names = [language.find_element_by_css_selector('a').text
for language in languages] links =[language.find_element_by_css_selector('a') \
.get_attribute('href') for language in languages]
你可以打印出language_names
和links
来看看它工作了。
卷动
有时并不是从一开始就加载整个页面。在这种情况下,我们可以让浏览器向下滚动,从页面的其余部分获取 HTML。使用将 JavaScript 代码作为参数的execute_script()
方法非常简单:
scroll_down = "window.scrollTo(0, document.body.scrollHeight);" browser.execute_script(scroll_down)
scrollTo(x-coord, y-coord)
是一个滚动到给定坐标的 JavaScript 方法。在我们的例子中,我们使用返回元素高度的document.body.scrollHeight
(在这个例子中是body
)。
正如你可能已经猜到的,你可以用execute_script()
方法让浏览器执行所有类型的脚本。所以如果你有 JavaScript 的经验,你有很大的试验空间。
微小静电干扰声
点击就像选择一个元素并对其应用click()
方法一样简单。在某些情况下,如果您知道需要访问的 URL,您可以让浏览器加载带有 URL 的页面。还是那句话,看什么效率更高。
为了举例说明click()
方法,让我们点击左侧菜单中的“内容”链接。
该链接的 HTML 如下:
<li id="n-contents">
<a href="/wiki/Portal:Contents" title="Guides to browsing Wikipedia">
Contents
</a>
</li>
我们必须首先找到具有唯一 id 'n-contents'
的<li>
元素,然后访问它的<a>
子元素
content_element = browser.find_element_by_id('n-contents') \
.find_element_by_css_selector('a')content_element.click()
您现在可以看到浏览器加载了“目录”页面。
下载图像
现在,如果我们决定从页面下载图片。为此,我们将使用urllib
库和一个 uuid 生成器。我们将首先用 CSS 选择器'img'
定位所有图像,然后访问它的'src'
属性,然后用urlretrieve('url', 'folder/name.jpg')
方法为每个图像创建一个唯一的 id 下载图像。这个方法有两个参数:一个图片的 URL 和一个我们想给它的名字,以及我们想下载到的文件夹(如果适用的话)。
from urllib.request import urlretrieve
from uuid import uuid4 # get the main page again browser.get('https://en.wikipedia.org/wiki/Main_Page') # locate image elements
images = browser.find_elements_by_css_selector('img') # access src attribute of the images
src_list = [img.get_attribute('src') for img in images] for src in src_list:
# create a unique name for each image by using UUID generator
uuid = uuid4() # retrieve umages using the URLs
urlretrieve(src, f"wiki_images/{uuid}.jpg")
增加动作之间的等待时间
最后,有时有必要在浏览器中的操作之间引入一些等待时间。比如一个接一个加载很多页面的时候。可以用time
模块完成。
让我们从我们的links
列表中加载 3 个 URL,并让浏览器在使用time.sleep()
方法加载每个页面之前等待 3 秒钟。
import time urls = links[0:3] for url in urls:
browser.get(url) # stop for 3 seconds before going for the next page
time.sleep(3)
关闭 web 驱动程序
最后,我们可以关闭机器人浏览器的窗口
browser.close()
不要忘记browser
是一个包含Firefox()
方法实例的变量(见教程开头)。
GitHub 中的代码
这篇文章中的代码可以在 GitHub 中找到:
https://github.com/AnnaLara/scraping_with_selenium_basics
原发布于 2019 年 9 月 12 日https://dev . to。
反思自己的虚拟足迹
原文:https://towardsdatascience.com/introspection-on-ones-virtual-footprint-79590857afb5?source=collection_archive---------24-----------------------
谷歌和脸书对你了解多少?可以下载自己找。
或者,一点心理分析数据
你担心网上收集的关于你的数据吗?
如果你正在读这篇文章,我想你以前听说过这个:你已经意识到网上已经有很多关于你的数据,反乌托邦 奥威尔 卡夫卡 雅哒雅哒雅哒你无力控制它。
GDPR 是欧洲保护消费者数据的一大进步;而美国有多重保护措施( COPPA 、隐私保护等)。)没有什么东西像 GDPR 一样既独特又包罗万象。
你至少可以追踪一些关于你自己的已知信息,并限制它们的使用来针对你。
按照我的习惯(bespoke data science 4ever),我想简要地检查一下我自己的数据。我们将快速浏览一下谷歌、Instagram 和脸书提供的内容,看看我们能轻松梳理出什么。
在我的 GitHub 上可以找到 Jupyter 笔记本来复制这里提出的问题和绘制的图表。
谷歌
谷歌提供通过外卖下载你的数据的能力。
takeout.google.com
按照给出的指示,几个小时后,谷歌将通过电子邮件向你发送链接,下载可能是几千兆字节的个人信息,这取决于你已经告诉谷歌为你保留的隐私级别。我的全部存档超过 20 GB(考虑到其中大部分是谷歌照片和邮件,我认为这是合理的)。
如果您只对浏览数据感兴趣,那么您选择的格式可能对您并不重要。HTML 可能是最容易用肉眼阅读的,但是如果您对检查数据感兴趣,您可能希望深入每个服务并更改格式,并尽可能选择 JSON,以使数据操作最容易。这个选择对于 My Activity 是最重要的,它是一个元产品,存储了跨产品的活动记录。
You’ll want to check My Activity out.
有一些显而易见的产品,比如搜索和位置历史,你想挖掘它们的记录,但是也有一些你可能不知道的“产品”。我在这里要研究的是购买和交易。
I was not aware that Google was scraping my Gmail for purchase info and collecting it in JSON format.
“购买和交易”包含从其他谷歌服务中抓取的信息。如果 Google 检测到一条信息(通常是电子邮件)涉及购买、预订、订阅、交付或其他类型的金融交易(似乎不包括银行交易),该内容就会被提取出来并放在 JSON 文件中。每个事务都有自己的文件(与我的活动文件相反,我的活动文件包含特定产品的所有操作)。
例如,我很惊讶(但我应该惊讶吗?)来查看谷歌已经解析了我在 2017 年 11 月下的订单的一封 GrubHub 回执邮件的内容。
part of the email receipt from GrubHub…
… and part of the JSON extracted from this email.
我很好奇谷歌从我收到的电子邮件中提取了多少此类内容,以及从我可能不知道的其他金融服务中提取了多少与谷歌相关的内容。
事实证明相当多。
我还想知道这个 JSON 文件是如何创建的。谷歌真的提取了这些内容,还是 GrubHub 卖给了谷歌?我不知道。
在没有输入其他单个交易的细节的情况下,在我使用各种谷歌产品的过程中,谷歌似乎已经从至少追溯到 2008 年 5 月的 521 笔交易中提取/获取了数据(截至我的外卖存档时间)。(有 42 个没有日期。)
在这 521 笔交易中,有 390 笔交易有"小计"栏。将这些值相加(忽略任何行项目)表明,在过去 11 年中,Google 已经索引了我价值超过 11,000 美元的交易数据。
真正令人惊讶的是,这实际上并不多。如果我的数据具有代表性的话,看起来他们在 2013 年真正开始加快交易抓取的步伐。(也就是从那时起,我开始使用这个特殊的 gmail 地址进行更多的在线消费。或者两者都有。)
要收集你的 Instagram 数据,请遵循标题为“在 Instagram 上下载你的数据副本”下的这些指示。
这些数据仅以 JSON 格式提供。
我们将在这里运行一个简单的查询:每个月我给其他个人资料的赞是什么样的?
我在 2012 年年中开始使用 Instagram。在几个月的小活动后,有趣的是看到幂定律似乎是从我点击小心形图标的简单任务中产生的——至少可以说,这是一场无意的受欢迎程度竞赛。(当然,配置文件名是隐藏的。)
还要注意,分级简档的数量增加了;随着我关注的账户数量的增加,喜欢的照片的差异也在增加,但粗略的幂律结构仍然保持着,即使喜欢的人自己变得越来越分散(T2)。
a sample of my Instagram likes distributions: 12/2012, 6/2014, 6/2016, 6/2018
脸书
像以前一样,按照这些指示,在问题“我如何下载我的脸书信息的副本?“你会注意到,就像谷歌的“我的活动”一样,脸书的数据有 JSON 和 HTML 两种格式。
我们将着眼于脸书数据的两个方面:反应和帖子的情绪。
反应
一旦从句子结构的帖子中提取出反应的接收者,反应(喜欢和其他类型)就可以像 Instagram 喜欢一样进行计数。
sample Facebook reaction post — if we wish to tabulate who received what reactions, we need to extract the objects of these “title” sentences.
从我自己的脸书 feed 收集 11+年的反应数据开车回家有多少人已经离开了*台;不想在没有对象的情况下丢弃这些反应),我发现,在排列我的前 25 个回复接收者时,第 5 名是所有离开脸书的占位符“NO_NAME”的总和。
power laws emerging here make sense here too, although a power law appears cleaner with “likes” alone.
与 Instagram 的数据一样,喜欢和反应的“人气”效应表现为一种“财富分配”,受幂律支配。
帖子情感
对我在脸书的帖子进行情感分析更有趣一些。 VADER ,已经被整合到 NLTK (“自然语言工具包”)中,提供了文档级情感的分类,分为“正面的”、“负面的”、“中性的”和“复合的”。
首先,我们将检查每年有多少帖子。
this says a lot just by itself.
接下来,我们将生成每年这些帖子的情绪的箱线图。我是一个相对中立的演讲者(嗨,数学家),所以我们可以看到中间值非常坚定中立,几乎所有 2010 年以前的负面情绪(那时脸书的帖子变得更像句子,而不是 2000 年代后期的“人是 _____”格式)都被认为是离群值。
这仅仅触及了你能从这些数据中了解到的一些皮毛。上面给出的例子并没有真正涉及单个交易和帖子中的细节,在这里可以进行更细致的分析。
如果你能通过这些数据了解自己,那么掌握这些数据的公司也能从中学习。并用它向你推销。并可能卖给其他人来推销给你。
你同意吗?
模型拟合背后的直觉:过度拟合 v/s 欠拟合
原文:https://towardsdatascience.com/intuition-behind-model-fitting-overfitting-v-s-underfitting-d308c21655c7?source=collection_archive---------36-----------------------
在我们深入了解过度拟合和欠拟合背后的概念之前,让我们尝试理解机器学习模型的幕后工作。
你觉得把数据给机器学习模型会怎么样?想象一个充满白点的黑色房间。因为一个房间意味着 3 个维度(高度、宽度和长度),所以基本上我们是在 3 个维度上可视化数据。现在,让我们假设黑色房间里的白点形状像一条蛇。你认为你的模型如何在黑房间(3D 空间)中学习白点的这种性质?实际上,让模型学习数据性质的过程称为模型拟合。
模型拟合是让模型学习给定训练数据的性质的过程。
模型拟合的质量取决于三个主要因素,例如你的问题范式是什么,N 维空间(这里,N=3)中存在哪种数据,以及你选择的模型的固有性质是什么。
模型拟合取决于: 问题范式、数据种类和所选模型性质
让我试着解释一下。当我说你的问题范式是什么的时候,我指的是不管是 有监督的 还是 无监督的 学习任务。监督学习简单地说就是一种机器学习的范例,其中给你的数据包含目标的值。所谓目标,我指的是模型试图预测的值。另一方面,无监督学习顾名思义,暗示了一种我们有数据但没有目标值的范式。在查看模型对 N 维数据模式的掌握程度时,理解问题范式的概念是一个需要考虑的重要方面。
在监督学习任务的情况下(例如分类或回归),我们知道数据的实际模式只是因为我们有目标标签。换句话说,作为读者,你知道数据的性质(暗室中白点的蛇形结构),只是因为我明确告诉你,你已经得到了数据的目标值或真实值。另一方面,如果你观察无监督的学习任务,例如聚类,其中你只有数据,但你没有办法检测实际的结构或模式或目标标签。你唯一能做的就是进行有根据的猜测,并尝试使用不同的类内和类间相似性标准来评估你的模型。
因此,只有在监督学习任务中,我们才有足够的能力相对容易地检测模型拟合的质量,即,我们的模型对我们的数据的底层结构的理解程度,因为我们有真实的数据与之进行比较。请注意,我并不是想说无监督学习范式不关心模型拟合。我只是想指出,在缺乏真实目标值的情况下,在无监督学习范式中,确定模型与数据的拟合程度是一项多么困难的任务。
监督学习:给定目标标签
无监督学习:没有给定目标标签
在讨论模型拟合时,第二个需要了解的最重要的事情是我们得到了什么样的数据。我的意思是,无论数据是否线性可分。 线性可分性 的思想来源于这样一个事实:与非线性数据相比,在线性可分数据上训练和学习模型更容易。例如,再次想象一个黑暗的房间,想象红色发光点在房间的一端看起来像一朵云,蓝色发光点在房间的另一端看起来像另一朵云。在这种情况下,模型可以仅仅是线性模型(如线 y=mx+c ),并且它将能够基于任何未来点在房间中的位置来预测该点是红色还是蓝色。相比之下,想象一个房间,里面充满了随机排列的红色和蓝色发光点。现在,你能想出任何简单的(线性)模型,能够分离这些点群,同时很好地概括未来的预测吗?可能是的,但是这个模型会比线性模型复杂得多。
可线性分离:数据可以通过线性模型分离
非线性可分离:线性模型无法分离数据
这里有一张以不同形式呈现的更多数据点的图片,可以帮助您更好地理解线性可分性的概念。
Source of Image: http://www.robots.ox.ac.uk/~az/lectures/ml/lect2.pdf
最后但同样重要的是,当我提到模型的固有性质时,我基本上是指您选择了什么类型的模型来拟合您的数据。像直线或超*面一样是线性的吗?是像曲线一样的二次型吗?还是更复杂?选择一个能够识别给我们的数据的细微差别的模型是非常重要的。所以,选择你的模型要非常小心。
现在我们更好地理解了模型拟合,让我们看看任何机器学习模型的两个最重要的特征。即,。顾名思义,专一性仅仅意味着对给定的数据或任务的专一和专注。而可推广性意味着以可接受的性能水*推广任何未知(测试)数据的结果或模型的能力。
****特异性:对训练数据进行 f 集中学习的能力,以便模型学习数据的微小细节。
****可推广性:通过已知数据训练,对未知测试数据推广模型的能力。
当我们说模型适合数据时,我们的意思是它确定了数据中的一般趋势或模式,即,它是可概括的,而不是太具体的。把模型做得太具体会让它抓住每一个微小的细节。从而增加了它在看不见的测试数据上表现不佳的脆弱性。发生这种情况是因为模型在识别给定(训练)数据的细微差别方面变得过于精通,因此当向其提供可能显示略有不同的模式的看不见的测试数据时,它往往无法以任何可接受的效率水*对测试数据使用相同的明显特定的模型,因此表现不佳。上述场景中,模型往往过于特定于训练数据而无法进行概括,这被称为 过拟合 !
现在你一定在想什么是不合适的?欠拟合** 是与过拟合相反的一种方式。想象一下,一个模型如此笼统,以至于无法从给定的训练数据中捕捉到任何有意义的东西。在这种情况下,有很高的普遍性,但很低的特异性。这也不好!**
下图展示了红点所示给定数据的欠拟合、过拟合和完美拟合之间的差异。
您可以看到最左边的图包含一个模型(用黄线表示),该模型无法从数据中捕获任何有意义的信息(高概化),因为它无法通过 1 个以上的数据点(红点)(低特异性)。与之形成直接对比的是,我们看到最右边的模型穿过了所有的红点(高特异性)。这表明它试图捕捉所有数据点的复杂性,但如果我们使用这条黄色曲线并试图根据看不见的数据拟合它,它将表现不佳(低概化)。现在看中间的图片。这是一条最佳拟合或完美拟合模型线,因为它了解数据的整体结构,但在训练过程中不会太具体,从而产生一条穿过大多数数据点(红点)而遗漏一些数据点的线。换句话说,它假设可能有很少的点是异常值,并在训练时保持一定的误差幅度。
因此,为了使模型表现良好,总是需要在特异性和可推广性之间取得*衡。
简而言之,这是记住两者区别的经验法则。
**过拟合:高特异性,低概化
**欠拟合:低特异性,高概化
请注意,我在本文中使用的模型大多是线性的,因为它们最容易被我们所有人理解。然而,同样的经验法则也适用于更复杂的模型。
我希望这篇文章能帮助你理解模型拟合背后的基本原理,以及过度拟合和欠拟合有什么不同!
感谢您的阅读!
继续学习!
直觉:探索与开发
原文:https://towardsdatascience.com/intuition-exploration-vs-exploitation-c645a1d37c7a?source=collection_archive---------6-----------------------
权衡和常见解决方案背后的直觉。
Berries by William Felker on Unsplash
探索-开发权衡是一个众所周知的问题,它发生在学习系统不得不重复做出不确定回报的选择的场景中。从本质上来说,对于一个对世界只有不完整认识的决策系统来说,困境在于是重复迄今为止行之有效的决策(exploit)还是做出新颖的决策,希望获得更大的回报(explore)。
这与强化学习高度相关,但对于许多其他应用也是如此,例如推荐系统和在线广告。
在这篇文章中,我给出了三个简单且行之有效的策略的概述,以解决多武装匪徒的探索-开发权衡。
术语一个武装强盗来自老丨虎丨机,它有一只“胳膊”可以拉,可以有效地“抢劫”玩家的钱。
如果问题包括在多个离散选项(武器)中反复选择,每个选项产生一个概率奖励(金钱),我们称之为“多武器强盗问题”。在这种情况下,就像吃角子老丨虎丨机一样,每个选择的奖励与之前选择的选项无关。随着时间的推移,决策者对每个选项的回报分配建立了理解。目标是最大化期望回报,这需要找出哪个选项给出最高的*均回报,并尽可能地利用这个选项。
例如,想象你正遭受下午疲劳的折磨,你想知道如何仍然是最有效率的。每天,你可以尝试几种策略中的一种:喝杯咖啡,小睡一会儿,试着放松一下,等等。对于每一种策略,回报看起来都是概率性的,因为许多其他因素也在影响你的生产力。你开始每天选择一个选项,有时尝试新的东西,有时重复过去行之有效的东西。当你观察你每天的工作效率时,你会对你的策略的有效性有更好的理解,使你最终能够始终如一地选择最可靠的策略。
解决方案策略
正如你所想象的,有许多方法可以解决多臂土匪问题。我将试着给你一个直观的概述,介绍一些简单但有效的(也就是它们实际上正在被使用的)方法。
ϵ-greedy
这个非常简单,如果你学过强化学习 101 课程,我保证你听说过。纯粹贪婪的方法背后的想法是每一个决定都尝试一次,然后一直选择能带来最高回报的那个。
为了增加一些探索的成分, ϵ-greedy 让你决定你的决定中有多少部分要花在探索(ϵ)上,有多少部分要花在探索(1-ϵ)到目前为止的最佳选择上。如果你将ϵ设为 0.4,那么你会在过去 60%的时间里选择给你最好*均回报的选项,而在 40%的时间里选择任何其他选项。通常,你希望ϵ很小,这样你可以充分利用你的经验,但也可以不时地去探索。虽然有时候,从一个更大的ϵ开始是一个好主意,以鼓励最初的探索,并在你收集关于回报的知识时减少它。
对于许多应用程序,ϵ-greedy 工作得非常好。在其他场景中,由于不加选择地探索,它失去了一些效率。这意味着当你探索时,选择两个看似次优的选项的概率是相等的。即使有些选项总是比其他选项差,它们有时还是会被选中,浪费宝贵的资源。
置信上限(UCB)
现在我们在贝叶斯水域中行走。想象一下,对于每一个选项,我们都维护着一个我们在选择这个选项时收集到的奖励的分布。如果我们还没有收集到任何奖励,我们可以从一个假设开始:每个选项的先前奖励分布通常非常广泛(例如均匀分布)。当我们收集奖励时,我们会不断更新这个分布。
UCB: Three options with different densities. The orange lines are one standard deviation higher than the mean. As we explore the option with the highest μ + βσ, we would go for option 3 this time (if we chose β=1).
在每一步,我们不会像贪婪方法那样,只选择估计*均回报μ最高的选项,而是选择μ 加标准差σ最高的选项。这样做的效果是,在开始时,当我们不确定任何选项的回报并且方差很大时,我们倾向于探索具有高不确定性的选项,因为σ占优势。随着我们对每个选项的*均回报越来越确定,标准差会缩小,我们倾向于选择估计*均回报μ最高的选项,而忽略回报很少的选项。
我们称 μ + βσ 为置信上限,其中β是一个权衡参数,用于引导更多或更少的探索。随着β趋于零,我们更接*于纯粹利用迄今为止提供最高*均回报的期权。另一方面,高β值有利于探索,直到我们几乎没有不确定性。
请注意,与ϵ-greedy 方法不同,我们的经验会影响我们要探索的选项。如果我们很早就发现其中一个选项几乎肯定比其他选项差,那么我们就不会投资去进一步探索它。
汤普森取样
请记住,我们不断地重新估计我们的奖励分布。当遵循 1933 年引入的汤普森采样方案时,我们利用了那些分布所提供的不确定性。在每个时间步,我们从每个分布中抽取一个样本。然后,我们根据这些样本的回报值对选项进行排序,就像我们之前根据*均值加上β乘以标准差对分布进行排序一样。最后,我们选择排名最高的选项。
Thompson sampling: Three options with different densities. The black dots represent one sample drawn from each distribution. For this set of samples, we would explore option 3, although it has a lower mean reward than option 2.
这样,估计*均回报高的选项就有可能被选中。尽管如此,我们不确定的期权也有机会被选中,因为它们的样本分布在一个很大的可能回报值区域。
采用这种策略,我们通常不会完全放弃任何选择,不像我们对 UCB 那样。相反,它越来越不可能选择一个看似糟糕的选项。
凭直觉,我们可以说 UCB 和汤姆森抽样都是“乐观的”,因为他们给了期权一个机会,即使这些期权到目前为止还没有带来最好的*均回报。在理论层面上,可以证明 UCB 和汤普逊抽样之间有着密切的联系。
感谢您的阅读。我希望你喜欢这篇文章,也学到了一些有用的东西!
直观深度学习第 1a 部分:神经网络简介
原文:https://towardsdatascience.com/intuitive-deep-learning-part-1a-introduction-to-neural-networks-aaeb3a1500df?source=collection_archive---------8-----------------------
什么是深度学习?一个非常温和和直观的神经网络及其工作原理的介绍!
*年来,eep Learning 因其在许多应用程序上令人印象深刻的表现而受到了广泛关注,包括语言翻译、x 光医疗诊断、识别图像以帮助无人驾驶汽车、击败顶级围棋选手以及高级 DotA 选手、仅从像素数据学习如何玩 Atari 游戏……所有这些都是 Deep Learning 最*取得的成就!在这篇文章中,我们将在直观的层面上(温和地)向你介绍深度学习背后的内部工作。
深度学习实际上只是机器学习的一个子集,由于它在我们上面列出的许多任务中的出色表现,最*获得了极大的关注。
这就引出了一个问题——什么是机器学习?机器学习与“传统算法”有何不同?
如果你上过算法课,那么算法的标准隐喻就是一个配方。算法是一系列步骤,当按特定顺序执行时,会产生您想要的输出。机器人制作面包的“烹饪算法”可能是这样的:
- 向一个大碗中加入 3 杯面粉、1 汤匙盐和 3 汤匙糖。
- 在另一个碗里,将一包酵母溶解在温水中。
- 把两个碗放在一起,揉 10 分钟。
诸如此类……(我不是面包专家,所以我不会在这里写面包的食谱)
在机器学习中,我们不会像上面那样指定算法。相反,我们指定了烹饪方法可能采用的模板(或“架构”):
- 向一个大碗中加入 __ 杯面粉、__ 汤匙盐和 __ 汤匙糖。
- 在另一个碗里,将 __ 包酵母溶解在温水中。
- 把两个碗放在一起,揉 __ 分钟。
空格是在开始时没有指定的数字,但是我们必须找出答案。然后,我们编写一个算法(另一系列指令),依靠我们可以访问的数据,根据什么是“最佳”(我们将在后面定义)来计算这些数字。
在很高的层面上,机器学习的任务是双重的:
- 找到最适合该任务的最佳模板。深度学习只是我们从中选择的模板的子集,这些模板已经被证明在许多任务中是有效的。
- 使用数据找出填充模板的最佳数字。这就是“机器学习”的“学习”部分。
一个成功的机器学习模型需要这两个步骤——如果没有第一步,没有面包粉,无论你尝试多少次,都不可能代表正确的“食谱”;如果没有第二步,你的面包“配方”的比例可能会完全错误,即使配料是正确的。
举一个更具体的例子,考虑根据房屋大小(*方米)、层数、到最*学校的距离(米)等特征预测房价的任务。
一个标准的算法可能是这样的:房价大约是(100 *房子大小)+ (1000 *楼层数)——(30 *到最*学校的距离。(参数化)机器学习方法看起来像这样:
第一步:我已经指定了模板:房价 __ *房屋面积+ __ *层数+ __ *到最*学校的距离。
第二步:看我列出的所有房子的数据,似乎最好的填空数字分别是(90.3,1006.2,-40.5)。
我们将更深入地探究我们具体指定了什么样的模板,以及我们如何使用这些数据来填补这些空白。但是在高层次上,许多机器学习任务采取与上面的例子类似的形式:给定一些输入,学习一些将输入转换成期望输出的函数。
这种输入-输出对的其他例子有:
- 输入:来自照片的图像(一系列像素);输出:判断图像中是否有汽车
- 输入:来自胸部 x 光的图像(一系列像素);输出:患者胸部感染可能性的概率
- 输入:客户服务电话的录音;输出:预测客户对此次通话的感受,得分从 1 到 10
- 输入:英文单词序列;输出:相应的法语翻译
机器学习算法的强大之处在于,我们可以解决以前不知道答案的问题。假设我们不知道如何将语音转换为文本的公式,因为这个公式非常复杂(如果它存在的话)。通过机器学习,我们可以仅从转录服务(例如字幕)的数据中找出复杂的公式,解决(至少*似地)一个我们之前无法用算法编码的问题。
总结:机器学习包括两步:指定一个模板,并为该模板找到最佳参数。
如上所述,深度学习只是采用“神经网络”的架构(或模板)的一个子集,我们可以在步骤 1 中指定。“神经网络”(更具体地说,人工神经网络)松散地基于我们人类大脑的工作方式,神经网络的基本单元是神经元。
在基本水*上,神经元做两件事:
- 接收来自其他神经元的输入并将它们组合在一起
- 执行某种转换来给出神经元的输出
在(1)中,我们经常取一些输入的线性组合。通俗地说,如果神经元有三个输入(让我们称它们为 x1、x2 和 x3),那么我们可以这样组合它们:
This is a linear combination of inputs to our neurons
其中,各个空白是将被优化以用于以后的参数(即,从数据中学习什么数字最好地填充那些空白)。在数学术语中,连接到输入(x1、x2 和 x3)的空白称为权重,不连接到任何输入的空白称为偏差。
对于线性组合,我们应用一些函数(称为激活函数)来实现我们的最终输出。这些功能的常见示例有:
- Sigmoid 函数(将所有初始输出“挤压”在 0 和 1 之间的函数)
- 双曲正切函数(将所有初始输出“挤压”到-1 和 1 之间的函数)
- ReLU 函数(如果初始输出为负,则输出 0。否则,不对初始输出做任何事情)
这就是一个神经元的全部!
Image taken from CS231N notes (http://cs231n.github.io/neural-networks-1/). This shows the parallels between the artificial neuron we’ve described and a biological neuron.
现在我们已经描述了一个神经元,一个“神经网络”简单地由层神经元组成,以一种方式连接,一个层神经元的输入是前一层神经元的输出(激活后):
Image taken from CS231N Notes (http://cs231n.github.io/neural-networks-1/). A layer in the neural network consists of one or more neurons. These layers are connected such that the input of one layer of neuron is the output of the previous layer of neurons (after activation).
现在,激活函数的意义是什么?神经元的第一步有道理,但第二步真的有必要吗?激活函数为函数提供了一些非线性,我们需要用它来表示复杂的函数。请参见脚注 1 了解原因。
让我们通过一个简单的神经网络示例来巩固我们的理解。假设我们已经完成了培训(稍后会详细介绍),并在模板中填入了数字,这样我们就有了一个完整的模型。假设我们希望预测某人是否会通过驾驶考试。我们有三个输入特征:年龄、性别、课程数量。我们的中间层有两个神经元。假设每个神经元分别描述了它们在停车和道路驾驶中的表现。
Our simple neural network to predict whether someone has passed his/her driving
现在我们已经填写了最佳数字,因此我们知道根据年龄、性别和课程数量来描述某人停车表现的最佳方式。假设函数是这样的:
A function to compute how well someone would park based on their age, sex and number of lessons
我们考虑两个人:
个人 A:20 岁,男性,已经上了 10 节课。他的“停车”神经元将输出 0(因为 ReLU 将所有负输出转换为 0)。
人 B:50 岁,女性,已经上了 20 节课。她的“停车”神经元将输出 150.5(因为 ReLU 只留下正输出)。
类似地,对于道路驾驶神经元,我们可以有这样一个函数:
A function to compute how well someone would drive on the road based on their age, sex and number of lessons
对于上述两个人,我们知道 A 的“道路驾驶分数”为 0,B 的“道路驾驶分数”为 179.5。
现在,这两个分数有助于这个公式中某人是否通过的最终输出:
A function to compute the probability of someone passing based on the output of the two intermediate neurons
在最后一层,我们已经计算出,人 A 通过的概率将是 Sigmoid(-3) = 4.74%,人 B 通过的概率将是 Sigmoid(2.9925) = 95.22%。请记住,sigmoid 是一个将我们的值压缩在 0 和 1 之间的函数,一个对获取概率有用的函数!你可以在这里找到一个 sigmoid 计算器:https://keisan.casio.com/exec/system/15157249643325
然而,在一天结束时,当数字被填入这个模板时,神经网络只是复杂的功能,其中的神经元建立在其他神经元的基础上。神经网络的强大之处在于,在实践中,它们能够灵活地(*似地)很好地表示任务的输入和输出之间的潜在关系。
附带说明:虽然术语神经网络可以指模板(模型架构),但它也经常用于指完整的模型(参数填充到模板中)。
在我们的例子中有一个错误,我想强调一下。在我们的例子中,我们确切地知道中间神经元在做什么——计算停车和道路驾驶时的表现。然而,在神经网络中,我们不知道神经元在做什么;它自己计算出什么是要计算的最佳中间特征,这将导致最终输出的准确预测。可能是‘停车’和‘道路驾驶’,也可能是其他我们并不真正理解的东西。这就是为什么人们说神经网络是不可解释的——我们不知道这些中间表示在人类可理解的层面上意味着什么。
我们再举一个例子。在最终层识别图像是否包含猫时,我们可能希望中间层识别中间特征(例如,某些类似猫的特征的存在,如胡须)。我们没有对这些中间特征进行硬编码,而是让机器来确定哪些中间特征最适合识别猫。这是否意味着中间层的神经元正在准确地识别胡须,我们不知道,但我们相信机器知道如何以最佳形式安排参数。我们没有指定那些参数,但是我们指定了为我们的模型设置边界的架构(容器)。当我们来到关于计算机视觉的第二部分时,我们将对此进行更多的讨论。
这是一个神经网络!但是现在你可能已经注意到了,我们可以有很多不同的组合来安排这个神经网络架构。我们应该有多少隐藏层?每个隐藏层应该有多少个神经元?所有这些与架构相对应的设置被称为“超参数”,我们最终也需要找到最佳的“超参数”集。我们将在第 1b 部分中回来讨论这个问题。
总结:神经网络只是我们指定的一个复杂的‘模板’,它具有建模输入和输出之间许多复杂关系的灵活性。
到目前为止,我们只触及了机器学习的“第一步”:为我们的模型设置一个好的模板或架构。我们现在进入“第二步”:假设我们已经找到了一个好的模板,我们如何从数据中学习?哪组数字最适合我们的任务?我们称之为优化:寻找符合我们模板的最优(最佳)数字。
要做到这一点,我们首先必须定义“最佳”的含义,用某种度量标准来衡量模型的表现。在我们预测一些产出(房价、某人是否患有癌症等)的情况下。),我们希望预测尽可能接*实际值。如果我对数据集的预测与实际值相差甚远,那就真的很糟糕,我可能想在我的性能指标中对此进行惩罚。
我们使用的指标被称为损失函数,它根据我们的预测与数据集中的实际值之间的差距来描述模型的表现有多差。我们的任务是提出一种算法来寻找使这个损失函数最小化的最佳参数。
分类问题的一个常见损失函数(见脚注 2)是 softmax 损失函数(见脚注 3)。
在没有给出数学的全部细节的情况下,对该损失函数的一种常见解释是:
Loss Function Interpretation
其中,Prob_model (CorrectLabel)是指模型分配给我们所知的正确标签的概率。让我们通过一个例子来获得更好的直觉:
假设我的问题是识别一个图像是否是热狗:
无论如何,我给我的模型一个热狗的训练例子(所以我们知道“热狗”是正确的标签)。根据图像,我的模型可能会给我这样的概率:
Model Probabilities of Hot Dog vs Not Hot Dog
在这个训练例子的损失函数中,我们有
Loss for Hot Dog Training Example
现在拿另一个有不同参数的模型来说,他们试图从同一张图像中进行预测。相反,该模型在识别哪个是正确图像方面表现不佳:
Probabilities and loss for a poorer model which gives a lower probability to the correct class (Hot Dog)
显然,模型预测更差,因此我们得到更高的损失。因此,损失函数确实对应于模型在预测特定示例的正确类别方面的表现。对正确答案的预测越高,损失越低。总损失可视为每个单独训练示例的*均损失。
现在我们有了一个损失函数,我们必须找到合适的参数来最小化它。为此,我们求助于一种叫做梯度下降的算法。梯度下降背后的想法很简单——在损耗减少的方向上缓慢移动参数。方向由损耗相对于这些参数的梯度给出。一个“更新步骤”是这样的:
An update step: The new parameters is one step away from the old parameters. The step is in the direction of the gradient, and how big a step we take in that direction is determined by the step size.
在我们迈出第一步后,我们继续移动并迭代这些参数,直到我们到达“最低点”,在那里没有方向会给我们带来任何明显更低的损失:
Image taken from https://ml-cheatsheet.readthedocs.io/en/latest/gradient_descent.html
你可能经常听到术语反向传播。反向传播仅仅是一种在神经网络中寻找梯度的方法。这里我们不讨论数学,因为寻找梯度需要对微积分有所了解,但是我们的想法是,神经网络是一个非常复杂的函数,用“传统”方法求导可能会很困难。然而,数学显示的是,我们在早期层中需要的梯度可以表示为在它之后的层中的梯度的更简单的函数:
How the gradient we needs depend on the layer after it
那我们该怎么办?一个好的策略是从最后一层开始,然后反向工作。假设有 5 层:我们找到最后一层的梯度,第 5 层(这很简单)。然后,我们找到第 4 层的梯度,因为我们已经找到了第 5 层的梯度。然后,我们找到第 3 层的梯度,因为我们已经找到了第 4 层的梯度,等等,直到我们到达第 1 层。这就是为什么它被称为反向传播:我们的计算从第 5 层一直反向传播到第 1 层。反向传播真的只是帮助我们找到更简单的表示和公式来计算梯度下降所需的梯度。
万一我们丢失了大图,让我们回顾一下为什么我们需要使用梯度下降:梯度下降帮助我们找到最小化损失的参数。通过最小化训练损失,我们得到了一个更好的模型,为我们的训练集提供了最准确的预测。
总结:指定损失函数和执行梯度下降有助于我们找到为我们的训练集提供最准确预测的参数。
合并总结:机器学习包括两步:指定一个模板,为该模板寻找最佳参数。神经网络只是我们指定的一个复杂的“模板”,它具有建模输入和输出之间许多复杂关系的灵活性。指定损失函数并执行梯度下降有助于我们找到为我们的训练集提供最准确预测的参数。
下一步 : 到目前为止,我们已经在很高的层面上涵盖了深度学习的基本概念。
这篇帖子最初是作为直观深度学习入门系列的第一篇帖子出现的。我的使命是用纯粹直观的方式解释深度学习概念!如果你是一个非技术初学者,我想为你提供深度学习内部工作原理背后的直觉,让你使用相同的语言和行话与技术工程师交流,即使你不知道背后的数学或代码。如果你是一名深度学习的学生,我相信在直觉方面获得坚实的基础将有助于你更好地理解你正在学习的课程中的所有数学和代码,为你提供一种更少痛苦的方式来学习这些概念。
如果你希望阅读更多,下一篇文章第 1b 部分将通过直觉告诉你一些我们必须注意的细微差别。我们将深入探讨如何让深度学习模型工作背后的一些本质细节,回答诸如“我们如何找到最佳的模型架构(模板)”之类的问题
如果你对编写你的第一个神经网络感兴趣,这篇文章附带了一个编码伴侣:
[## 用 Keras 建立你的第一个预测房价的神经网络
一步一步完整的初学者指南,建立你的第一个神经网络在几行代码像一个深…
medium.com](https://medium.com/intuitive-deep-learning/build-your-first-neural-network-to-predict-house-prices-with-keras-eb5db60232c)
脚注:
- 为什么我们的神经元中需要激活功能
如果每个神经元的输出只是其输入的线性组合,那么层输出中神经元的输出仍将是输入的线性组合,无论神经网络有多少隐藏层或有多复杂。假设相反,我们没有激活函数;那么隐藏层 2 中的神经元只是隐藏层 1 中神经元输出的线性函数。
因此,隐藏层 2 中神经元的公式可能如下所示:
Formulation of a neuron in hidden layer 2
其中 h1、h2 和 h3 是隐藏层 1 中的神经元。但是 h1 的公式应该是
Formulation of a neuron in hidden layer 1
其中 x1 和 x2 是输入特征。h2 和 h3 的公式是相似的,尽管填空的数字可能不同。尝试将 h1、h2 和 h3 的公式代入中,您会发现隐藏层 2 中神经元的公式可以简化为输入特征的线性组合,如下所示:
Substituting in the formulation for neurons in earlier layers and rearranging it reveals that we merely get a linear function in the end
如果你继续这种逻辑,你会意识到,即使在最后一层,它们也只是输入的线性组合——对于建模复杂的关系来说,这真的不是一个非常复杂的函数。增加一个非线性意味着你不能重新排列它来得到一个线性函数,你最终会得到一个非常复杂的公式(来表达复杂的关系):
Substituting in the formulation for neurons in earlier layers, we see that this representation does not reduce to a simple linear combination of the inputs
- 回归与分类的区别
监督学习的输出通常分为两类:回归和分类。分类是这篇文章的重点:输入可以映射到几个不同的输出(称为类),并且每个输入都有一个正确的标签。另一方面,回归预测的是一个实数值而不是一个类。假设我们希望从他们的评论中预测 Yelp 的星级(1 星到 5 星)。分类方法预测评论属于哪个不同的类别(1 星、2 星、3 星、4 星或 5 星);回归方法预测一些实数值(例如 3.71)。对于本系列的大多数帖子,我们将重点讨论分类问题。
3.soft max
Softmax 是最后的一个常见步骤,它将最终输出转换为一组概率。概率必须满足以下条件:每个概率介于 0 和 1 之间(包括 0 和 1),所有概率的总和为 1。
如果我们没有 softmax 层,则无法保证我们的最终输出满足上述条件,因为最终输出可以是任何没有概率意义的数字(例如-4、5.2 等)。因此,Softmax 将我们所有的最终输出标准化为一组概率,以满足上述条件。
弄脏你的手:
一个玩神经网络的好网站是 tensor flow Playground:https://playground.tensorflow.org
关于作者:
你好,我是约瑟夫!我最*从斯坦福大学毕业,在那里我和吴恩达一起在斯坦福机器学习小组工作。我想让深度学习概念尽可能直观,尽可能容易被每个人理解,这激励了我的出版:直观的深度学习。
直观深度学习第 2 部分:用于计算机视觉的 CNN
原文:https://towardsdatascience.com/intuitive-deep-learning-part-2-cnns-for-computer-vision-472bbb2c8060?source=collection_archive---------16-----------------------
什么是卷积神经网络?我们如何应用神经网络来识别图像?
从无人驾驶汽车到面部识别技术,我们的机器似乎能够理解它们看到的东西。这是一个令人印象深刻的壮举:毕竟,机器只能将图像作为一系列数字来处理。机器如何将这一系列数字翻译成识别图像中的对象?
在这篇文章中,我们将揭示深度学习如何推动我们尖端的图像识别技术的秘密。
这是直觉深度学习介绍系列的第 2 部分。以下是到目前为止发生的事情的简要总结:
在第 1 部分中,我们介绍了神经网络以及如何让它们工作。我们从第 1a 部分开始,高度概括了机器学习的目标:
机器学习指定一个模板,并为该模板找到最佳参数,而不是我们自己对参数进行硬编码。神经网络只是我们指定的一个复杂的“模板”,它具有建模输入和输出之间许多复杂关系的灵活性。指定损失函数并执行梯度下降有助于找到为我们的训练集提供最佳预测的参数。
然后,我们在第 1b 部分中深入探讨了如何让神经网络在实践中发挥作用的一些基本细节。
在这篇文章中,我们将看到神经网络如何应用于图像识别。特别是,我们将介绍一种新的模型架构,称为卷积神经网络(也称为CNN或 ConvNets )。这是一种新型的体系结构,它将利用图像数据的特殊属性,所以让我们开始吧!
首先,我们需要讨论图像的属性,然后才能讨论如何在我们的神经网络中利用它们。在计算机中,图像存储为空间排列的二维像素阵列,每个像素对应于图像的一小部分。事实上,“像素”一词来自短语“pi(x)ctureElelement”,因为它构成了图像中的一个小元素:
Images are made out of pixels arranged within a 2-D array. Image taken from https://www.photoshopessentials.com/basics/pixels-image-size-resolution-photoshop/
现在每个像素存储一种颜色;一种颜色在计算机中用三个数字表示,分别对应该颜色中红、绿、蓝的数量,范围从 0 到 255(包括 0 和 255)。所以实际上,如果您将颜色通道视为另一个维度,图像可以表示为一个三维数组(前两个维度存储图像中出现的像素,最后一个维度有三个通道——红色、绿色和蓝色)。
这对我们的深度学习算法意味着什么?当我们把一幅图像作为输入时,我们实际上是在接受一个三维数组。每个数字都是我们通过神经网络传递的图像的一个特征。假设我们的图像尺寸是 256 * 256;然后,我们将总共 256 * 256 * 3 = 196,608 个特征输入到我们的神经网络中。(功能真多啊!)从这 196,608 个特征中,我们需要找到一些复杂的函数,将它转换成对图像代表什么对象的预测。一个简单的例子是——照片里有猫吗?
回想一下,拥有 196,908 个特征意味着我们在一个神经元中需要 196,908 + 1 = 196,909 个参数。请记住,在应用激活函数之前,我们的神经元输出首先采用输入特征的一些线性组合:
A formulation of the neuron output in terms of its input features x1, x2 and x3
在三个输入特征(x1、x2 和 x3)的情况下,我们有四个需要填充数字的空白,一个对应于每个特征和一个偏差项(不附属于任何特征)。如果我们有 196,908 个特征,我们还剩下 196,909 个空白,我们需要找到最好的数字。所有这些都发生在一个神经元上!现在,如果我们有一个神经网络,那就需要学习很多参数!
让事情变得更复杂的是,猫可以在照片中的任何地方。猫可以在图片的右上角,也可以在左下角——它们对应着一组非常不同的 196,608 个特征,但它们代表着同一个东西:一只猫。
摘要:图像是一个三维特征阵列:二维空间中的每个像素包含三个数字,从 0 到 255(包括 0 和 255 ),分别对应红、绿、蓝通道。通常,图像数据包含大量输入特征。
回想一下,图像的本质是这样的:
- 有许多“输入特征”,每个特征对应于每个像素的 R、G 和 B 值,因此需要许多参数。
- 图像左上角的一只猫或右下角的一只猫应该给出相似的输出。
此时,或许可以考虑以下方法。假设我们有一个想要测试的图像:
An image of size 256x256 we wish to test whether there is a cat or not
这是我们的算法:
步骤 1:将图像分成四个相等的象限。让我们把图像尺寸设为 256 * 256 * 3(通道)。然后,图像的每个象限将具有 128 * 128 * 3 个特征。
We cut our image into four equal quadrants of size 128x128 pixels. Remember that each pixel has 3 channels (R, G and B)
步骤 2:对左上角象限应用一个神经元,将 128 * 128 * 3 的特征转换成一个单一的数字。出于直觉(尽管这并不完全准确),假设这个神经元负责识别 128 * 128 * 3 特征范围内的猫:
We apply the neuron which takes in the 128 * 128 * 3 features in the top-left quadrant
步骤 3:对右上象限、左下象限和右下象限应用完全相同的神经元。这被称为参数共享,因为我们对所有四个象限使用完全相同的神经元。
We apply the exact same neuron with the exact same parameters to all four quadrants of the image
第四步:对所有四个象限应用该神经元后,我们有四个不同的数字(直观地说,这些数字代表每个象限中是否有猫)。
We get four different output numbers even though we apply the same neuron since the inputs are different (although the parameters are the same)
记住,我们得到四个不同的数字,因为我们输入了不同的输入特征,即使函数(和参数保持不变)。
A formulation of the neuron output in terms of its input features x1, x2 and x3
根据上面的公式,输入特征(x1、x2 和 x3)已经改变,即使填充空白的数字没有改变;因此,这些输入特性会产生不同的输出。
第五步:我们需要一个数字来告诉我们整张照片中是否有一只猫。所以我们只取这四个数字中的最大值来得到一个数字。
We take the maximum of the four numbers to get one number in the end
这个算法在解决我们之前的问题方面做了什么?
- 我们最初的担心是有太多的特性,因此有太多的参数。回想一下,即使我们只有一个神经元具有所有这些特征,我们也需要 256 * 256 * 3 + 1 = 196,609 个参数用于每个神经元。如果我们将其分成四个不同的象限,并对所有四个象限使用完全相同的参数,我们只需要 128 * 128 * 3 + 1 = 49,153 个参数,几乎减少了四倍!
- 猫在图像中的什么位置并不重要,重要的是图像中有一只猫。通过在所有四个象限中使用相同的神经元来识别猫,我们解决了这个问题,因为“识别猫的神经元”应该告诉我们哪个象限有猫!
恭喜你!你已经看到了你的第一个卷积神经网络!现在,这些不是我们在实践中建立的 CNN 的类型,但是概念只是我们已经覆盖的内容的一般扩展。
在接下来的几节中,我们将了解一个典型的 CNN 是由什么组成的。
CNN 拥有的第一个重要的层被称为卷积(Conv)层,它对应于上面算法中的步骤 1 到 4。Conv 层是一种特殊类型的神经网络层,它使用参数共享,并在图像中应用相同的较小的参数集,就像我们在步骤 1 到 4 中对猫识别神经元所做的那样。这不同于标准的神经网络层,其具有用于整个图像的参数。
卷积层有几个我们可以指定的超参数:
- 滤镜大小。 这对应于一个神经元在宽度和高度维度上接受多少输入特征。在我们之前的例子中,过滤器的大小是 128 * 128,因为每个神经元在空间上看起来是 128 * 128 像素(宽度和高度)。我们总是假设我们不按深度(或通道)分割图像,只按宽度和高度。所以如果我们指定滤波器大小,我们神经元中的参数个数就是 filter _ width * filter _ height * input _ depth+1。在我们的例子中,参数的数量是 128 * 128 * 3 + 1 = 49,153。不过,通常情况下,合理的过滤器尺寸可能更接* 3 * 3 或 5 * 5 的数量级。
- 泰然处之。有时一只猫并不出现在象限中,而是可能出现在两个(或更多)象限的中间。在这种情况下,也许我们不应该只在四个象限中应用我们的神经元,但我们也希望在重叠区域中应用神经元。Stride 就是当我们再次应用神经元时,我们想要移动(向右/向下)多少像素。在我们之前的例子中,我们以步幅 128 移动,因此我们立即进入下一个象限,而没有访问任何重叠区域。更常见的是,我们通常以步幅 1 或 2 移动。
A convolution layer with filter width, filter height and stride. Note that while the red and blue boxes look at different areas, they use the same parameters.
- 深度。 在我们之前的例子中,我们只应用了一个神经元来识别是否有猫,并通过在每个象限中应用相同的神经元来共享参数。假设我们希望另一个神经元也能识别是否有狗。这种神经元的应用方式与识别猫的神经元相同,但具有不同的参数,因此每个象限的输出也不同。这将如何改变我们的参数和输出大小?嗯,如果我们有两个这样的神经元,我们就会有(128 * 128 * 3+1)* 2 = 98306 个参数。在第 4 步结束时,我们将得到 2 * 2 * 2 = 8 个输出数字。前两项 2 * 2 指的是(我们四个象限区域的)高度和宽度,最后一项 2 指的是每个象限应用了两个不同的神经元。这最后一项就是我们所说的深度。
我不想一口气介绍太多概念,所以我们来做一个小测验来巩固这些概念。
假设我们有一个输入尺寸为 256 * 256 * 3 的图像。我应用了一个过滤器大小为 3 * 3,跨度为 1,深度为 64 的 conv 层。
- 在我们的 conv 层中有多少参数?
- 这个 conv 层的输出尺寸是多少?
我鼓励你自己解决这个问题,不要向下滚动来看答案!
— —
好了,下面是答案!(希望你没出轨,反正我也没办法知道):
- 参数数量:我们计算出深度= 1 的情况,因为从头到尾只应用了一个神经元。这个神经元接受 3 * 3 * 3(滤波器大小*输入通道)个特征,因此这个神经元的参数数量是 3 * 3 * 3 + 1 = 28。我们知道深度= 64,意味着有 64 个这样的神经元。这为我们提供了总共 28 * 64 = 1,792 个参数。
- 输出尺寸:先从宽度的尺寸上来想。我们在原始输入图像中有一行 256 像素。开始时,我们的过滤器的中心(神经元的输入)将在像素 2,因为我们有一个 3 * 3 的过滤器。因此,由于过滤器的最左侧将在像素 1 处,所以过滤器的中心将在像素 2 处。此过滤器每次向右移动 1 个像素,以应用神经元。在所有步骤结束时,我们的滤镜的中心将位于像素 255,这也是因为我们有一个 3 * 3 的滤镜(因此像素 256 将被滤镜的最右侧占据)。因此,假设我们的过滤器的中心从像素 2 开始,在每一步移动 1 个像素时结束于 255,数学表明我们已经在宽度上应用了神经元 254 次。类似地,我们在高度上应用了神经元 254 次。由于我们有 64 个神经元在做这件事(深度= 64),我们的输出尺寸是 254 * 254 * 64。
此时,您可能会想:那么,如果我希望输出尺寸为 256 * 256 * 64,那么输出的高度和宽度与输入尺寸保持不变呢?在这里,我将引入一个新的概念来处理这个问题:
- 垫料。回想一下,3×3 滤波器的中心开始于像素 2(而不是像素 1),结束于像素 255(而不是像素 256)。为了使过滤器的中心从像素 1 开始,我们可以用“0”的边界填充图像,如下所示:
This is an example of padding a 3x3 image with a padding border of size 1. This ensures that the center of a 3x3 filter will begin at pixel 1 of the original image.
至此,我们已经确切了解了许多尖端系统中使用的卷积层是什么!我们将介绍另一层,然后我们将所有层放在一个大的架构中,并讨论其背后的直觉!
概要:conv 层中 CNN 常见的一层,由滤波器大小、步距、深度和填充定义。Conv 层使用相同的参数,并在图像的不同区域应用相同的神经元,从而减少所需参数的数量。
我们将经历的下一层被称为池层,它大致对应于开始时布置的算法中的步骤 4 和 5。如果你还记得,我们有四个数字在我们的基本算法后,应用 conv 层,我们希望它减少到一个数字。我们简单地取四个输入数,输出最大值作为输出数。这是 max-pooling 的一个例子,顾名思义,取它所看到的数字的最大值。
更一般地说,池层具有过滤器大小和跨度,类似于卷积层。让我们以深度为 1 的输入为例(即它只有一个深度片)。如果我们应用一个最大池,过滤器大小为 2x2,跨距为 2,因此没有重叠区域,我们得到:
Max-pooling with filter 2 and stride 2. Note that a max-pool layer of filter 2 and stride 2 is commonly seen in many models today. Image taken from CS231N notes: http://cs231n.github.io/convolutional-networks/
这个最大池似乎非常类似于 conv 层,除了没有参数(因为它只是取过滤器中看到的四个数字的最大值)。然而,当我们引入深度时,我们会看到池层和 conv 层之间的更多差异。
汇集层分别应用于每个单独的深度通道。也就是说,最大池化操作不在不同深度取最大值;它只在单一深度通道中取最大值。这与 conv 层不同,后者合并了来自所有深度通道的输入。这也意味着我们的输出图层的深度大小不会也不能改变,这与输出深度可能不同于输入深度的 conv 图层不同。
最终,汇集层的目的是减少层的空间尺寸(宽度和高度),并且它根本不触及深度。这减少了该池层之后的未来层中所需的参数数量(从而减少了计算)。
举个简单的例子,假设在我们的第一个 conv 层(有池)之后,我们有一个 256 * 256 * 64 的输出维度。我们现在对此应用最大池(过滤器大小为 2x2,步长为 2)操作,最大池层之后的输出尺寸是多少?
— —
答案:128 * 128 * 64,因为 max-pool 操作符将宽度和高度的维度减少了一半,而深度维度保持不变。
总结:CNN 中的另一个常见层是最大池层,由过滤器大小和步幅定义,通过取其过滤器内数字的最大值来减小空间大小。
CNN 中常见的最后一层是我们在前面的部分中见过的层,即全连接(FC)层。FC 层与我们的标准神经网络相同——下一层中的每个神经元都将前一层输出中的每个神经元作为输入。因此,命名为完全连接,因为下一层中的所有神经元总是连接到上一层中的所有神经元。展示一个我们在第 1a 部分中见过的熟悉的图表:
Image taken from CS231N Notes (http://cs231n.github.io/neural-networks-1/)
我们通常在 CNN 的最末端使用 FC 层。所以当我们到达这个阶段时,我们可以将神经元展*成一维的特征阵列。如果前一个图层的输出是 7 * 7 * 5,我们可以将它们展*为一行 775 = 245 个要素,作为上图中的输入图层。然后,我们像往常一样应用隐藏层。
总结:我们通常还会在 CNN 的末端使用传统的全连接层。
现在让我们把它们放在一起。计算机视觉研究人员通常使用的一个重要基准是称为 ImageNet 大规模视觉识别挑战(ILSVRC)的挑战。ImageNet 指的是一个巨大的图像数据库,ILSVRC 的挑战是将一幅输入图像准确地分类到 1000 个独立的对象类别中。
在使用深度学习的转折点上受到欢呼的模型之一是 AlexNet,它在 2012 年赢得了 ILSVRC。在一篇题为“历史始于 AlexNet:深度学习方法综合调查”的论文中,我引用:
与所有传统的机器学习和计算机视觉方法相比,AlexNet 实现了最先进的识别准确性。这是机器学习和计算机视觉领域在视觉识别和分类任务方面的重大突破,也是历史上对深度学习兴趣迅速增加的一点。
AlexNet 表明,当我们深入时,精确度可以实现惊人的提高——即像我们看到的那样,将越来越多的层堆叠在一起。事实上,AlexNet 之后的架构决定继续深入,超过一百层!
AlexNet 的架构可以总结如下:
A simplistic view of the AlexNet Architecture, where some details have been omitted
如您所见,AlexNet 只是由以下构件组成:
- Conv 层(有相关活动)
- 最大池层数
- FC 层
- Softmax 层
到目前为止,我们都以这样或那样的方式看到了这些层!正如你所看到的,我们已经涵盖了强大的深度学习模型的构建模块,我们需要做的就是将这些层堆叠在一起。为什么把这么多层堆在一起会起作用,每一层到底在做什么?
我们可以想象一些中间层。这是 AlexNet 的第一个 conv 层的可视化:
A visualization of the first conv layer in AlexNet. Image taken from CS231N notes: http://cs231n.github.io/understanding-cnn/
我们可以看到,在前几层,神经网络试图提取出一些底层特征。这些最初的几层然后在随后的几层中结合,形成越来越复杂的特征,最后,找出代表像猫、狗等物体的东西。
为什么神经网络会在第一层中特别挑出那些特征?它只是发现这些是表征前几层的最佳参数;他们只是制造了最小的损失。
总结 : AlexNet 是一个革命性的深度学习领域的 CNN,由 conv 层、最大池层和 FC 层构建而成。当许多层放在一起时,前面的层学习低级特征,并在后面的层中组合它们用于更复杂的表示。
综合摘要:图像是一个三维的特征数组:二维空间中的每个像素包含 0-255(包括 0-255)三个数字,分别对应红、绿、蓝三个通道。通常,图像数据包含大量输入特征。Conv 层是 CNN 中常见的一层,由滤镜尺寸、步距、深度和填充定义。Conv 层使用相同的参数,并在图像的不同区域应用相同的神经元,从而减少所需参数的数量。CNN 中的另一个常见层是 max-pooling 层,由过滤器大小和步幅定义,它通过取其过滤器中数字的最大值来减小空间大小。我们还通常在 CNN 的末尾使用传统的全连接层。AlexNet 是一个革命性的深度学习领域的 CNN,由 conv 层、最大池层和 FC 层构建而成。当许多层放在一起时,前面的层学习低级特征,并在后面的层中组合它们用于更复杂的表示。
下一步是什么:深度学习不仅改变了我们看待图像识别的方式,还彻底改变了我们处理语言的方式。但是处理语言本身也有一系列的挑战。我们如何将单词表示为数字?此外,一个句子有不同的长度。在输入可能具有不同长度的情况下,我们如何使用神经网络来处理序列?如果你很好奇,直觉深度学习第 3 部分将神经网络应用于自然语言,解决了学习如何将英语句子翻译成法语句子的问题。
如果您对编写您的第一个图像识别模型感兴趣,这篇文章附带了一个编码伴侣:
[## 建立你的第一个卷积神经网络来识别图像
一步一步的指南,建立自己的图像识别软件与卷积神经网络使用 Keras 上…
medium.com](https://medium.com/intuitive-deep-learning/build-your-first-convolutional-neural-network-to-recognize-images-84b9c78fe0ce)
这篇帖子最初是作为直觉深度学习入门系列的第三篇帖子出现的。我的使命是用纯粹直观的方式解释深度学习概念!如果你是一个非技术初学者,我想为你提供深度学习内部工作原理背后的直觉,让你使用相同的语言和行话与技术工程师交流,即使你不知道背后的数学或代码。如果你是一名深度学习的学生,我相信获得坚实的直觉基础将有助于你更好地理解你正在学习的课程中的所有数学和代码,为你提供一种更少痛苦的方式来学习这些概念。
关于作者:
你好,我是约瑟夫!我最*从斯坦福大学毕业,在那里我和吴恩达一起在斯坦福机器学习小组工作。我想让深度学习的概念尽可能直观,尽可能容易被每个人理解,这激励了我的出版:直观的深度学习。
交叉熵的直观解释
原文:https://towardsdatascience.com/intuitive-explanation-of-cross-entropy-5d45fc9fd240?source=collection_archive---------7-----------------------
首先,我们需要理解熵的概念(很大程度上借用了可汗学院优秀的解释)。
让我们玩游戏。
游戏 1:
我将从一袋硬币中抽出一枚硬币:一枚蓝色硬币、一枚红色硬币、一枚绿色硬币和一枚橙色硬币。你的目标是用最少的问题猜出它是什么颜色。
最好的策略之一是:
每枚硬币有 1/4 的概率被选中,猜对两个问题。所以猜硬币的预期问题数是 2。
游戏 2:
现在,我将从一袋硬币中抽出一枚硬币:1/2 是蓝色的,1/4 是红色的,1/8 是绿色的,1/8 是橙色的。以前的策略不再是最好的;因为抽到蓝色硬币的机会很大,所以我们应该优先猜测最有可能的结果。你的最优策略现在看起来像这样:
1/2 的时候是蓝色的,要猜 1 题。1/4 的时候是红色的,要猜 2 题才能猜出来。按这个逻辑,猜一个硬币的期望题数是 1/2 × 1(蓝色)+ 1/4 × 2 题(红色)+1/8 × 3 题(绿色)+ 1/8 × 3 题(橙色)= 1.75。
游戏 3:
为了对比一个极端的例子,我从一袋蓝色硬币中抽取。很简单,猜我的硬币的颜色需要 0 个问题。或者… log(1) = 0 问题如果我们用搞笑的方式写的话。注意,只有当你知道这是一袋蓝色时,才需要 0 个问题。
有趣的是,出现了一种模式:一个概率为 p 的硬币需要 log (1/p)个问题才能答对。比如 p = 1/4 时,log(4) = 2 题(本帖所有对数均以 2 为基数)。所以总的来说,这个游戏的预期问题数是
。这就是熵的表达式。直观来看,就是这个博弈的最优策略下猜色的预期题数。 设定越不确定(游戏 1 >游戏 2 >游戏 3),熵越高。
现在,让我们从转移到交叉熵 。
对于第二场比赛,如果我们仍然使用第一场比赛的策略,
然后,1/8 的时候,硬币是橙色的,要做对 2 道题。1/2 的时间,它是蓝色的,但仍然需要 2 个问题才能答对。*均下来,需要 1/8 × 2 + 1/8 × 2 + 1/4 × 2 + 1/2 × 2 = 2 个问题才能答对,而不是用我们之前讨论的最优策略的 1.75。所以在博弈 2 中使用博弈 1 策略是一个更差的策略,2 是在这个设置中使用这个策略的交叉熵。
因此,给定策略的交叉熵就是在该策略下猜测颜色的预期问题数。对于给定的设置,策略越好,交叉熵越低。交叉熵最低的是最优策略的交叉熵,也就是上面定义的熵。这就是为什么在机器学习的分类问题中,人们试图最小化交叉熵。
更正式地说,交叉熵是
,其中 p_i 是真实概率(例如,橙色和绿色为 1/8,红色为 1/4,蓝色为 1/2),而{p_i}是错误假设的概率(例如,使用策略 1,我们假设所有颜色的 p = 1/4)。可能很容易混淆日志中是 p 还是{p}。在这个解释下,就很好记了:log 是用来计算你策略下的题数的,所以 log 下面的是你的预测概率,\hat{p}。
所以,在决策树中,如果你的树不是以最佳方式构建的,你基本上是错误地假设了结果的概率分布,交叉熵很高。
交叉熵不仅仅是关于决策树;它适用于所有分类问题。在二元分类问题中,标签 y 为 1 的可能性就是你预测的 y,\ hat { y };y 为 0 的可能性是 1 -\hat{y}。所以我们可以用一种巧妙的方式写出我们想要最大化的可能性:
。当 y 为 1 时,乘积中的第二项为 1,我们希望最大化{ y };当 y 为 0 时,乘积中的第一项为 1,我们希望最大化 1 — \hat{y}。这仅在 y 取值为 0 或 1 时有效。
最大化可能性的对数相当于最小化
这只是交叉熵的表达式。这就是交叉熵被称为对数损失的原因。最小化交叉熵最大化对数似然。举个例子,我的分类里有三个数据点,它们的真实标签是 1,1,0,我预测的 y 是 0.8,0.9,0.3。那么*均交叉熵就是
如果我完美预测为 1,1,0,那么交叉熵为 0。(从技术上讲,log 在 0 处没有很好的定义,但是我们可以忽略这个术语。)使用硬币游戏类比,在这里,对于样本 y 的每个预测是具有游戏 3 设置的单独的硬币猜测游戏。第一个样本 y=1 就像从一个只包含“y = 1”的袋子里抽出一枚硬币。现在,如果你是一个忍者猜测者(又名完美算法),那么你也知道它必须是一个全 1 的包。所以你的\hat{p} = 1。第二个和第三个样本也是如此。因此,对于完美的算法,交叉熵是 0。
原载于www.quora.com。
直观的超参数优化:网格搜索,随机搜索和贝叶斯搜索!
原文:https://towardsdatascience.com/intuitive-hyperparameter-optimization-grid-search-random-search-and-bayesian-search-2102dbfaf5b?source=collection_archive---------16-----------------------
机器学习算法中的超参数就像煤气炉中的旋钮。就像我们调整煤气炉上的旋钮,直到我们达到正确的设置,让食物按照我们喜欢的方式烹饪。同样,我们调整机器学习算法的超参数,使其工作在最佳水*,并获得我们想要的性能水*。
在我开始讨论超参数优化的搜索算法之前,让我打破一些人们对超参数的常见误解!
误区一:参数和超参数相同
这种混乱背后的原因是,在机器学习算法中存在两种类型的可学习实体:参数和超参数。参数由模型在学习期间学习,而超参数由用户在学习之前设置。
流言终结者警报
参数: 训练时学习到的机器学习模型的实体。
超参数 :训练开始前设置的机器学习模型的实体。
例如,让我们考虑逻辑回归。逻辑回归是一种分类算法。
上图展示了逻辑回归模型。让我简单解释一下逻辑回归背后的思想。对于任何给定的输入数据 X,我们首先学习 Z=WX+B 形式的线性模型,其中 W 和 B 充当参数。然后我们计算 Z 的 sigmoid,结果是 0 和 1 之间的值。因此,为了决定给定数据点属于哪一类(类 0 或类 1),我们通常设置阈值(例如阈值=0.5),这有助于决定类。如果 sigmoid 输出的值大于阈值,则分类任务的输出为 1,即数据点属于类 1,否则属于类 0。诸如 W 和 B 的实体被认为是在给定数据 x 的训练期间学习的参数。而诸如优化算法的类型、正则化技术、α或学习速率、C(用于保持正则化强度的正则化参数的逆,即 C = 1/λ)的实体是超参数的例子。
让我们看看另一个关于超参数优化的常见误区。
误区 2 : 使用超参数的默认值就足够了。没有必要试着去调它们。
超参数的默认值可以被各种机器学习库如 sklearn、Hyperopt 等选为默认值,因为它们对于学术文献中的某些测试问题是足够好的组合。但是,这样的值对于您的问题陈述可能并不理想。永远记住,运用这些价值观,看看什么最适合你。不相信我?开始在数据集上测试这些超参数的不同组合。你会自动看到不同之处!
流言终结者警报
默认值仅针对选定的少数问题陈述进行测试,可能不是您的问题的最佳超参数选择。所以,总是调整你的超参数!
现在,我们已经打破了一些关于超参数优化的常见神话。让我来讨论一些最常见的超参数优化技术。即 网格搜索 , 随机搜索 和 贝叶斯搜索 。
网格搜索 是一种尝试超参数集所有可能组合的方法。超参数的每个组合代表一个机器学习模型。因此,N 个组合代表 N 个机器学习模型。通过网格搜索,我们确定了表现出最佳性能的模型。这使得网格搜索不仅在时间复杂度上非常昂贵,在空间复杂度上也是如此。
看下图。正则化类型(惩罚)和 C 是逻辑回归的超参数,如下所示。
逻辑回归的超参数
正则化类型(或惩罚)= { l1,l2,None}
= { 0.1,1}
网格搜索在给定数据上测试这些值的所有组合(所有可能的模型),并通过使用用户指定的评估度量(如准确度、精确度、召回率等)来找到最佳可能的模型。
组合 :
{penalty: l1,C=0.1} == > 模型 1
{惩罚:l1,C=1}。== > 型号 2
{惩罚:l2,C=0.1} == > 模型 3
{penalty: l2,C=1} == > 模型 4
{罚:无,C=0.1} == > 模型 5
{惩罚:无,C=1} == > 模型 6
换句话说,网格搜索将一次获取一个惩罚和 C 的组合(一次一个模型),并将其拟合到训练数据(或交叉验证折叠)上,并计算其表现如何。它将对所有可能的(如上所示)组合执行此操作,最终选择表现最佳的模型。请注意,存在更多的逻辑回归超参数,但为了简洁起见,我只选择了其中的两个来演示网格搜索是如何工作的。
网格搜索:测试给定机器学习算法的超参数的所有可能排列组合。
随机搜索 另一方面、* 是一种我们尝试随机选择超参数组合的方法。这通常在计算上非常便宜,并设法给我们提供足够好的超参数组合,从而实现所需的性能水*。*
换句话说,随机搜索可能很快从所有可能性中选择惩罚和 C 的随机组合(如上所示),并且只测试那些选择的组合。
随机搜索:从可搜索空间中随机选择超参数的组合(所有可能的组合)。
随机搜索的唯一问题是,它没有告诉我们如何选择超参数组合。这个过程完全是随机的,没有办法知道是否存在更好的组合。没有办法缩小搜索空间,因为我们实际上不知道在哪里可以找到更好的价值。
贝叶斯搜索 从另一方面解决了上述问题。这是另一种众所周知的超参数优化方法。顾名思义,该技术基于贝叶斯原理。贝叶斯原理基本上说,后验概率分布与赋予它的先验(先验概率分布)和似然函数成正比。
Source of Image: https://luminousmen.com/post/data-science-bayes-theorem
简而言之,先验概率分布可以被视为提供给模型的专家知识,以帮助增加机器学习模型通过查看训练数据掌握的知识。假设事件 A 已经发生,似然函数可以被视为对事件 B 有多可能发生(或为真)的理解。最后但并非最不重要的是,后验概率分布可以被认为是最终的学习模型,它包含专家领域知识并考虑给定输入数据的可能性。
因此,贝叶斯优化或贝叶斯搜索考虑了先前已知的知识(先验知识),并且仅搜索那些它认为将提高模型性能的超参数组合。
贝叶斯搜索 :基于贝叶斯规则并考虑先前已知的知识,帮助缩小良好超参数组合的搜索空间。
贝叶斯搜索通常比随机搜索花费更多时间,但比网格搜索花费更少时间。
按时间复杂度排序
网格搜索>贝叶斯搜索>随机搜索
我希望这篇文章有助于澄清一些关于超参数优化的最常见的疑问。
感谢您的阅读!
继续学习!
资源:
sk learn/Scikit learn:https://scikit-learn.org/stable/
逻辑回归:https://sci kit-learn . org/stable/modules/generated/sk learn . linear _ model。LogisticRegression.html
远视:https://github.com/hyperopt/hyperopt
理解贝叶斯原理的一个很好的来源是:【https://luminousmen.com/post/data-science-bayes-theorem】
对深度学习中注意机制的直观理解
原文:https://towardsdatascience.com/intuitive-understanding-of-attention-mechanism-in-deep-learning-6c9482aecf4f?source=collection_archive---------0-----------------------
注意力神经机器翻译的张量流实现
警告
这是一个稍微高级的教程,需要对使用 RNNs 的序列到序列模型有基本的理解。请参考我早先的 博客这里 ,我在其中详细解释了 Seq2Seq 模型的概念。
目录
- 介绍
- 注意力背后的中心思想
- 为什么叫注意?
- 注意力是如何工作的?
- 代码遍历
- 可视化结果
- 参考
1.介绍
注意力是深度学习社区中最有影响力的思想之一。尽管这种机制现在用于各种问题,如图像字幕等,但它最初是在使用 Seq2Seq 模型的神经机器翻译的上下文中设计的。在这篇博文中,我将考虑与运行示例相同的问题来说明这个概念。我们将利用注意力来设计一个系统,将一个给定的英语句子翻译成马拉地语,这个例子和我在早先的博客中考虑的完全一样。
那么 seq2seq 车型有什么问题呢?
seq2seq 模型通常由编码器-解码器架构组成,其中编码器处理输入序列,并将信息编码/压缩/汇总到固定长度的上下文向量(也称为“思维向量”)中。这种表示应该是对整个输入序列的一个很好的总结。解码器然后用这个上下文向量初始化,使用它开始产生变换的输出。
这种固定长度上下文向量设计的一个关键且明显的缺点是系统不能记住更长的序列。一旦它处理了整个序列,经常会忘记序列的前面部分。注意力机制就是为了解决这个问题而诞生的。
让我们把它分解成更详细的细节。由于我已经在之前的 博客 中解释了理解注意力所需的大部分基本概念,这里我将直接进入问题的实质,不再赘述。
2.注意力背后的中心思想
为了便于说明,我将借用我在之前的 博客 中用来解释 Seq2Seq 模型的同一个例子。
输入(英语)句子:“拉胡尔是个好孩子”
目标(马拉地语)句子:“राहुल चांगला मुलगा आहे”
唯一的变化将是,而不是 LSTM 层,我用在我以前的解释,这里我将使用 GRU 层。原因是 LSTM 有两种内部状态(隐藏状态和单元状态),而 GRU 只有一种内部状态(隐藏状态)。这将有助于简化概念和解释。
回想下图,其中我总结了 Seq2Seq 建模的整个过程。
在传统的 Seq2Seq 模型中,我们丢弃编码器的所有中间状态,仅使用其最终状态(向量)来初始化解码器。这种技术适用于较小的序列,但是随着序列长度的增加,单个向量成为瓶颈,很难将长序列总结成单个向量。这种观察是凭经验得出的,因为注意到随着序列大小的增加,系统的性能急剧下降。
注意力背后的中心思想不是丢弃那些中间编码器状态,而是利用所有的状态来构建解码器生成输出序列所需的上下文向量。
3.为什么叫注意?
让我们将编码器的每个中间状态命名如下:
Encoder GRU
请注意,由于我们使用的是 GRU 而不是 LSTM,因此我们在每个时间步只有一个状态,而不是两个状态,这有助于简化图示。还要注意,注意力尤其在较长序列的情况下是有用的,但是为了简单起见,我们将考虑上述相同的示例进行说明。
回想一下,这些状态(h1 到 h5)只不过是固定长度的向量。为了发展一些直觉,把这些状态想象成在序列中存储局部信息的向量。比如说;
h1 存储出现在序列开头的信息(如“Rahul”和“is”)而 h5 存储出现在序列后面部分的信息(如“good”和“boy”)。
让我们用下面的简图来表示我们的编码器 GRU:
Compact Representation of Encoder GRU
现在的想法是共同利用所有这些局部信息,以便在解码目标句子时决定下一个序列。
想象你正在把“拉胡尔是个好孩子”翻译成“राहुल चांगला मुलगा आहे".”扪心自问,你在脑子里是怎么做到的?
当您预测“राहुल”时,很明显这个名字是单词“Rahul”出现在输入的英语句子中的结果,而不管句子的其余部分。我们说在预测“राहुल”时,我们更关注 输入句子中的单词“Rahul”。
类似地,当预测单词“चांगला”时,我们更关注输入句子中的单词“好”。
类似地,在预测单词“मुलगा”时,我们更关注输入句子中的单词“男孩”。等等..
由此得名“立正”。
作为人类,我们能够很快理解输入序列的不同部分和输出序列的相应部分之间的映射。然而,人工神经网络自动检测这些映射并不是那么简单。
这样注意力机制通过梯度下降和反向传播发展到 【学习】 这些映射。
4.注意力是如何工作的?
让我们从技术角度切入注意力机制的本质。
在时间步长 1 解码
继续上面的例子,假设我们现在想要我们的解码器开始预测目标序列的第一个字,即“राहुल”
在时间步骤 1,我们可以将整个过程分为五个步骤,如下所示:
Decoding at time step 1
在开始解码之前,我们首先需要将输入序列编码成一组内部状态(在我们的例子中是 h1、h2、h3、h4 和 h5)。
现在的假设是,输出序列中的下一个字取决于解码器的当前状态(解码器也是 GRU)以及编码器的隐藏状态。因此,在每个时间步,我们考虑这两件事,并遵循以下步骤:
步骤 1 —计算每个编码器状态的分数
因为我们预测的是第一个字本身,所以解码器没有任何当前的内部状态。为此,我们将编码器的最后状态(即 h5)视为先前的解码器状态。
现在使用这两个组件(所有编码器状态和解码器的当前状态),我们将训练一个简单的前馈神经网络。
为什么?
回想一下,我们试图预测目标序列中的第一个单词,即“राहुल".”按照 attention 背后的思想,我们不需要所有的编码器状态来预测这个单词,但是我们需要那些存储关于输入序列中单词“Rahul”的信息的编码器状态。
如前所述,这些中间编码器状态存储输入序列的本地信息。所以很有可能单词“Rahul”的信息会出现在状态中,比如说 h1 和 h2。
因此,我们希望解码器更多地关注状态 h1 和 h2,而较少关注编码器的其余状态。
为此,我们训练一个前馈神经网络,该网络将学习以通过为需要注意的状态生成高分而为需要忽略的状态生成低分来识别相关的编码器状态。
设 s1、s2、s3、s4 和 s5 是对应于状态 h1、h2、h3、h4 和 h5 生成的分数。因为我们假设我们需要更多地关注状态 h1 和 h2,而忽略 h3、h4 和 h5,以便预测“राहुल”,所以我们期望上述神经生成分数,使得 s1 和 s2 高,而 s3、s4 和 s5 相对低。
第二步——计算注意力权重
一旦生成这些分数,我们就对这些分数应用 softmax,以产生如上所示的注意力权重 e1、e2、e3、e4 和 e5。应用 softmax 的优势如下:
a)所有权重位于 0 和 1 之间,即 0 ≤ e1,e2,e3,e4,e5 ≤ 1
b)所有权重总和为 1,即 e1+e2+3+e4+e5 = 1
因此,我们得到了注意力权重的一个很好的概率解释。
在我们的例子中,我们期望如下的值:(只是出于直觉)
e1 = 0.75,e2 = 0.2,e3 = 0.02,e4 = 0.02,e5 = 0.01
这意味着在预测单词“राहुल”时,解码器需要更多地关注状态 h1 和 h2(因为 e1 和 e2 的值很高),而忽略状态 h3、h4 和 h5(因为 e3、e4 和 e5 的值很小)。
步骤 3——计算上下文向量
一旦我们计算了注意力权重,我们需要计算解码器将使用的上下文向量(思维向量),以便预测序列中的下一个单词。计算如下:
context _ vector = E1 * h1+E2 * H2+E3 * H3+E4 * H4+E5 * H5
显然,如果 e1 和 e2 的值高,而 e3、e4 和 e5 的值低,则上下文向量将包含来自状态 h1 和 h2 的更多信息,以及来自状态 h3、h4 和 h5 的相对较少的信息。
步骤 4——将上下文向量与先前时间步骤的输出连接起来
最后,解码器使用以下两个输入向量来生成序列中的下一个字
a)上下文向量
b)从前一时间步生成的输出字。
我们简单地连接这两个向量,并将合并后的向量提供给解码器。注意,对于第一个时间步,由于没有来自前一个时间步的输出,我们为此使用一个特殊的<开始>标记。这个概念在我之前的 博客 中已经详细讨论过了。
步骤 5—解码器输出
然后,解码器生成序列中的下一个字(在这种情况下,预计会生成“राहुल”),随着输出,解码器还会生成一个内部隐藏状态,我们称之为“d1”。
在时间步长 2 解码
现在,为了生成下一个单词“चांगला”,解码器将重复相同的过程,该过程可在下图中总结:
这些变化在绿色圆圈中突出显示
Decoding at time step 2
在时间步长 3 解码
Decoding at time step 3
在时间步长 4 解码
Decoding at time step 4
在时间步长 5 解码
Decoding at time step 5
一旦解码器输出了
注意,与在传统 Seq2Seq 模型的情况下用于所有解码器时间步骤的固定上下文向量不同,在这里,在注意力的情况下,我们通过每次计算注意力权重来为每个时间步骤计算单独的上下文向量。
因此,使用这种机制,我们的模型能够发现输入序列的不同部分和输出序列的相应部分之间的有趣映射。
注意,在网络的训练期间,我们使用教师强制,以便输入实际单词,而不是来自前一时间步的预测单词。这个概念在我之前的 博客 中也有解释。
5.代码遍历
与任何 NLP 任务一样,在读取输入文件后,我们执行基本的清理和预处理,如下所示:
对于任何给定的词汇表,创建一个类来将每个单词映射到一个索引,反之亦然:
我们使用 tf.data 输入管道来创建数据集,然后以小批量的方式加载它。要阅读更多关于 TensorFlow 中输入管道的信息,请阅读官方文档 此处 和 此处 。
现在使用 TensorFlow 的模型子类 API,我们将模型定义如下。要了解更多关于模型子类化的信息,请点击 阅读官方文档 。
注:请阅读下面代码部分的注释,以便更好地理解我们上面讨论的概念。代码中大多数重要的行都指向上面给出的解释的相应部分。
定义优化器、损失函数和检查点
使用急切执行,我们为 10 个时期训练网络。要阅读更多关于渴望执行的内容,请参考官方文档 这里 。
推理设置和测试:
6.可视化结果
如果你不熟悉热图,你可以这样理解上面的图:
请注意,“父亲”和“बाबांनी”交叉处的单元格非常暗,这意味着当解码器预测单词“बाबांनी”时,它会更多地关注输入单词“父亲”(这正是我们想要的)。
类似地,在预测单词“कॅमेरा”时,解码器非常关注输入单词“照相机”。诸如此类。
结论
首先要注意的是,翻译结果比我之前的 博客 要好很多。其次,该模型能够在输入和输出序列之间找到正确的局部映射,这些映射与我们的直觉相匹配。
给定更多的数据和更多的超参数调整,结果和映射肯定会有很大的改进。
使用 LSTM 层代替 GRU 并在编码器上添加双向包装器也将有助于提高性能。
深度学习模型通常被认为是黑盒,这意味着它们不具备解释其输出的能力。然而,注意力是成功的方法之一,它有助于使我们的模型可解释,并解释为什么它会这样做。
注意机制的唯一缺点是非常耗时,并且难以并行化系统。为了解决这个问题,谷歌大脑提出了“变压器模型”,该模型仅使用注意力,并消除了所有卷积和递归层,从而使其高度并行化和计算高效。
7.参考
- https://arxiv.org/abs/1409.0473(原文如此)
- https://github . com/tensor flow/tensor flow/blob/master/tensor flow/contrib/eager/python/examples/NMT _ with _ attention/NMT _ with _ attention . ipynb(tensor flow 实现可在其官网上作为教程使用)
- https://www . coursera . org/lecture/NLP-sequence-models/Attention-model-lSwVa(吴恩达关于注意力的解释)
- https://jalammar . github . io/visualizing-neural-machine-translation-mechanics-of-seq 2 seq-models-with-attention/
- 【https://www.tensorflow.org/xla/broadcasting (tensor flow 中的广播)
- 数据集:【http://www.manythings.org/anki/ (mar-eng . zip)
PS:完整实现,参考我的 GitHub 库 这里 。
逆投影变换
原文:https://towardsdatascience.com/inverse-projection-transformation-c866ccedef1c?source=collection_archive---------0-----------------------
Fig 1: 3D points back-projected from a RGB and Depth image
深度和反向投影
当相机捕捉到一个场景的图像时,我们会丢失深度信息,因为 3D 空间中的对象和点被映射到 2D 图像*面上。这也称为投影变换,其中世界上的点被转换为 2d *面上的像素。
但是,如果我们想做逆呢?也就是说,我们希望在只给定 2D 图像的情况下恢复和重建场景。为此,我们需要知道每个对应像素的深度或 Z 分量。深度可以表示为如图 2(中间)所示的图像。较亮的强度表示较远的点。
理解深度知觉在许多计算机视觉应用中是必不可少的。例如,能够测量自主车辆的深度可以更好地做出决策,因为代理完全知道其他车辆和行人之间的间距。
Fig 2: (from left) RGB, Depth, 3D back-projected points
透视视角下的推理难度
考虑上面的图 2,仅给出 RGB 图像。很难判断左侧车道上两辆车之间的绝对距离。此外,我很难确定左边的树是离房子很*还是非常远。上述现象是透视投影的结果,透视投影要求我们依靠各种线索来对距离进行良好的估计。在这篇文章中,我讨论了一些你可能感兴趣的问题:)
然而,如果我们在深度图的帮助下将其重新投影回 3d(图 2。右),我们可以准确地定位树木,并认为他们实际上是远离建筑物。是的,当一个物体被另一个物体遮挡时,我们真的不擅长计算相对深度。主要的收获是只看图像,很难辨别深度。
估计深度的问题是一项正在进行的研究,多年来取得了很大进展。已经开发了许多技术,最成功的方法来自使用立体视觉确定深度[1]。并且在最*几年,使用深度学习的深度估计已经显示出令人难以置信的性能[2],[3]。
在本文中,我们将浏览并理解执行从 2D 像素坐标到 3D 点的反投影的数学和概念。然后,我将通过 Python 中的一个简单示例来展示实际的投影。此处有代码。我们将假设提供深度图来执行 3D 重建。我们将经历的概念是相机校准参数、使用内蕴及其逆的投影变换、帧之间的坐标变换。
3D reconstructed point clouds from the scene in Fig 2
针丨孔丨摄像机模型的中心投影
Fig 3: Camera Projective Geometry
首先,理解相机投影的几何模型是核心思想。我们最终感兴趣的是深度,参数 Z. 这里,我们考虑最简单的没有歪斜或失真因子的针丨孔丨相机模型。
3D 点被映射到图像*面(u,v) = f(X,Y,Z)。描述这种转换的完整数学模型可以写成 p = K[R|t] * P.
Fig 4: Camera Projective Model
在哪里
- p 是图像*面上的投影点
- k 是摄像机内部矩阵
- [R|t]是描述世界坐标系中的点相对于摄像机坐标系的变换的外部参数
- p,[X,Y,Z,1]表示在欧几里得空间中预定义的世界坐标系中表示的 3D 点
- 纵横比缩放,s:控制当焦距改变时,像素如何在 x 和 y 方向缩放
内在参数矩阵
矩阵 K 负责将 3D 点投影到图像*面。为此,必须将下列量定义为
- 焦距(fx,fy):测量图像*面 wrt 到相机中心的位置。
- 主点(u0,v0):图像*面的光学中心
- 倾斜因子:如果图像*面轴不垂直,则偏离正方形像素。在我们的例子中,这被设置为零。
求解所有参数的最常见方法是使用棋盘法。其中,借助于 PnP、直接线性变换或 RANSAC,通过匹配和求解未知参数来获得若干 2D-3D 对应,以提高鲁棒性。
确定了所有未知数后,我们可以通过应用逆运算来最终恢复 3D 点(X,Y,Z)。
反投影
考虑图 4 中的等式。假设(X,Y,Z,1)在摄像机坐标系中。即我们不需要考虑外部矩阵[R|t]。扩展该等式将得到
Fig 5: Equation mapping 3D to 2D point
3D 点可以通过深度图给定的 Z 值以及对 X 和 y 的求解来恢复。如果需要,我们可以进一步将这些点转换回世界坐标系。
逆投影示例
让我们通过一个简单的例子来理解这些概念。我们将使用如图 1 所示的 RGB 和深度图像。图片是从模拟器卡拉的汽车上安装的摄像机中获取的。深度图存储为 float32,对于无限远的深度值,编码最大为 1000 米。
视场的固有参数
代替使用棋盘确定内部参数,可以计算针丨孔丨照相机模型的焦距和光学中心。所需信息是以像素为单位的成像传感器高度和宽度以及垂直和水*方向的有效视野。相机制造商通常会提供这些。在我们的例子中,我们将在垂直和水*方向都使用+-45 度。我们将比例因子设置为 1。
参考图 3,焦距(fx,fy)和主点(u0,v0)可以使用简单的三角学来确定。我把它留给你作为一个练习来推导,或者你可以在代码中查找它!
现在,我们可以计算如下的倒数
- 获得摄像机固有参数 K
- 求 K 的倒数
- 应用图 5 中的公式,Z 为深度图中的深度。
# Using Linear Algebra
cam_coords = K_inv @ pixel_coords * depth.flatten()
编写步骤 3 的一种更慢但更直观的方式是
*cam_points = np.zeros((img_h * img_w, 3))
i = 0
# Loop through each pixel in the image
for v in range(height):
for u in range(width):
# Apply equation in fig 5
x = (u - u0) * depth[v, u] / fx
y = (v - v0) * depth[v, u] / fy
z = depth[v, u]
cam_points[i] = (x, y, z)
i += 1*
你会得到同样的结果!
结论
好了,我已经讲了做反投影所需的基本概念。
反投影到 3D 形成了经由结构形式运动的 3D 场景重建的基础,其中从移动的相机捕捉若干图像,以及其已知或计算的深度。此后,匹配和拼接在一起,以获得对场景结构的完整理解。
[## darylclimb/cvml_project
使用计算机视觉和机器学习的项目和应用
github.com](https://github.com/darylclimb/cvml_project/tree/master/projections/inverse_projection)
正投影:俯视图(可选)
使用 3D 表示的点,一个有趣的应用是将其投影到场景的自上而下的视图中。对于移动机器人来说,这通常是一种有用的表示,因为障碍物之间的距离保持不变。此外,它易于解释和利用来执行路径规划和导航任务。为此,我们需要知道这些点参考的坐标系。
我们将使用如下定义的右手坐标系
Fig 6: Camera coordinate and pixel coordinate
对于这个简单的例子,你认为点应该投影到哪个*面?
Fig 7: Top-down view
如果你的猜测是在 y= 0 的*面上,那么你是对的,因为 y 代表相机坐标系定义的高度。我们简单地折叠投影矩阵中的 y 分量。
查看下图,您可以轻松测量所有车辆和物体之间的间距。
Fig 8: Birds Eye View projection
参考
[1]赫希米勒,H. (2005 年)。通过半全局匹配和互信息进行准确有效的立体处理。 CVPR
[2]周廷辉、马修·布朗、诺亚·斯内夫利和大卫·劳。来自视频的深度和自我运动的无监督学习。2017 年在 CVPR
[3]克莱门特·戈达尔、奥辛·麦克·奥德哈和加布里埃尔·J·布罗斯托。具有左右一致性的无监督单目深度估计。2017 年在 CVPR。
倒 U 型和云计算架构:进化也是学生和悬崖的事情!
原文:https://towardsdatascience.com/inverted-u-and-cloud-computing-architectures-evolution-is-also-a-matter-of-students-and-cliffs-b264616fdba8?source=collection_archive---------32-----------------------
source: https://en.wikipedia.org/wiki/White_Cliffs_of_Dover
首先,什么是倒 U 型?
倒 U 形是一种图形,用于探索经济、社会和其他类型的事件,该图形由一条钟形线组成,可用于表示一个值(A)的增加将导致另一个值(B)增加的情况。
然而,在倒 U 型的情况下,当你增加 A 的比例没有增加 B 的时候,它实际上开始减少 A。
在这种情况下,当数量 A 开始降低 B 的值时,可以获得最佳性能。最佳结果是使用较低水*的 A 获得较高水*的 B。
让我们举个例子,马尔科姆·格拉德威尔,在他最*的书[ 大卫和歌利亚 ]中探索了一个有趣的观点。
一个班有很多学生好还是只有几个学生好?
嗯,与常识所说的不同[我的教授会说越少越好],有一点你可以取得更好的结果,这与班级的大小直接相关,如果你只有几个学生,比如说少于 12 个,班级太小,老师不会有在课堂上如此重要的多样化的观点[仅举一个例子],但是, 假设你有超过 50 个,那么,你会有很多不同的意见,但老师会缺乏对具体案例的关注。
在这种情况下,很明显,如果你开始增加一个班级的学生人数,参与度,注意力或其他参数也会增加,至少直到班级过大的某一点,结果是相反的,你开始失去一些东西。格拉德威尔描绘了其他几个场景,这是一本值得一读的书。
这和云计算有什么关系?
我就要到了伙计[冷静!],我们先找一个计算机科学中的倒 U 型场景,好吗?
嗯,你们都听说过线程吧?[如果你不记得了,看看这个视频。
图像有大量数据要处理,但只有一个线程来处理,假设这个处理过程需要 100 分钟才能完成,如果线程数量增加一倍,处理时间将减少到 50 分钟。如果您启动第三个线程,处理时间也将减少,让我们到 37 分钟,使用第四个线程,处理时间将减少到 30 分钟,您可以看到时间的减少与线程数量有直接关系吗?【当然可以!].
常见的错误是假设“好的,那么…我将增加到 1000 个线程,时间将接* 0[零]!”。不是这样的,有一个极限,在某个时刻,无论你增加多少线程数,时间都不会减少,最有可能的是会增加
“好的,那么你是说没有办法把时间减少到接* 0[zero]?!"
不,我不是那个意思!
我要说的是,你遇到了一个倒 U 型情景,为了打破拐点,无论你增加多少其他变量,你都开始失去一些东西,这就需要适应和改变你的方法,类似于我们在这里解释的,这正是云计算的用武之地。
就云而言,我们假设轴 B ,是性能、请求数量、数据量,以及与您的解决方案相关的东西。轴 A 是你使用多少服务来做这件事。如果您开始增加虚拟机的数量(在 AWS、EC2 机器的情况下),您的轴 B 也会增加,直到几乎无法管理数千台机器。然后你决定拿出一些机器,使用带有冗余、副本和其他东西的数据库服务( RDS )。现在你的 DB,会继续上升[耶!!】,但是【没有但是,加油!],没有更大的数据库可以使用,它变得太慢太贵,解决方案是添加不同类型的存储,非 SQL 数据库( Dynamo )和对象存储(像 S3 )。
你能看出这将把我们引向何方吗?
你已经从几个服务[服务器]开始,你必须进化以避开倒 U 形图形的拐点,在云计算的情况下,你必须进化你的架构,以便进化你的应用。只有通过改变,而不仅仅是增加 a,才有可能达到更高的 B。
这就像爬悬崖一样,你从海滩开始,你走了一点点,突然你开始向山上走,然后再走几米[ 也许几公里 ]后,你仍然在向上走,你对海洋的看法越来越好,在某个时候你意识到这是线的尽头,你会继续走下去,掉到海里吗?还是需要适应,坐直升机,继续旅程?我打赌直升机听起来不错,对吧?!
睁大眼睛,满怀信心地投资
原文:https://towardsdatascience.com/invest-with-confidence-with-your-eyes-wide-open-1b5f0d846922?source=collection_archive---------29-----------------------
知道自己的风险。在做出投资决定之前,一种有意义的看待风险的方式。
当一个人在寻找共同基金或股票进行投资时,通常会看到评级、风险规模、绩效汇总统计数据,如下所示。
Taken from some popular Investment Portals
当试图比较不同的选择时,获得这种相对评级是非常好的。像“n”年的回报这样的汇总指标告诉我们一只基金在最*几年的表现如何,以及如果事情以同样的方式继续下去,人们可能期望获得什么样的回报。
但是,对于那些多年来一直关注金融市场和投资表现的人来说,很明显,事情很少以同样的方式继续下去!想想主要的市场变动事件或商业周期变化——衰退、繁荣期、政治变化、贸易战、真正的战争……你明白了!
考虑到所有这一切,人们可能想要以下问题的答案:
- 如果明年市场经历长期低迷,我会损失多少?
2.如果我在这次衰退中继续投资,需要多长时间才能收回我的损失?
3.如果像 2008 年次贷危机这样的事件现在再次重演会怎样?与正在进行的银行业和 NBFC 危机(及其对汽车行业可能的传染效应)有一些相似之处,因为它与资产质量有关。我的投资会下跌 20%还是 50%?
4.如果美联储可能宣布降息,会对我的投资有帮助吗?如果是,增加多少?
5.从短期来看,市场一周的糟糕表现会导致 2%或 10%的账面损失吗?我会因为这些动作失眠吗?
在本文的其余部分,让我们回顾一下看待风险的一种不同但有意义的方式,以及我们如何回答这些实际问题。
为印度共同基金和印度股票提供了直观的分析驱动工具。例如,请参见下图
短期的紧张
为了评估典型的周/月/季度表现,资产的历史回报分布可能非常有帮助。它们不仅帮助我们衡量预期的范围,还显示了真正糟糕的一周会是什么样子,以及这样的一周有多频繁。
下面让我们一起比较一下两只股票型共同基金的表现。如果我们仔细观察,左边的基金波动性更大,相对于右边的基金,它经历了更明显的季度收益和下跌。更高的 beta(对整体市场的敏感度)进一步验证了这一点。
因此,在其中一个季度,左侧基金在 2018 年经历了远超 16%的跌幅。对于上述提出的问题,如果有人选择了左侧基金,他们必须准备好忍受如此动荡的季度。
长期的市场萧条
经济衰退和市场低迷是投资金融市场不可避免的现实。最大提取额(MDD)是分析基金在此期间损失多少的好方法。
不同的资产类别经历不同程度的损失。因此,根据基金的构成,他们的 MDD 可能会有很大的不同。
上述基金在 2014 年 11 月至 2016 年 2 月期间经历了约 30%的提款。达到底部大约需要 1.5 年,再次回到同样的水*又需要 1.5 年。总的来说,大概花了 3 年时间才扯*。
其他一些市场低迷持续的时间比这更长。更接* 7-8 年。我想起了奥马哈先知沃伦·巴菲特关于长期投资的名言——“只买那些如果市场关闭 10 年你也会非常乐意持有的东西”。
如果一个人的投资时间范围不允许这么长的时间,一个更*衡的基金将是一个更好的选择。低于基金,经历了仅 10%的最大下降,甚至在短时间内恢复。
伪预测
现在,让我们进入一些假设,好吗?
比方说,如果我们决定在一只基金中投资 X 元。然后,我们忘记它,继续我们的主要业务。然后,我们会听到这样的新闻标题——油价在过去两个月上涨了 20%,或者印度市场指数 Sensex 在上个季度下跌了 10%。
这可能会促使我们去检查我们投资的现值,并想知道它的表现如何。如果我们能在决定购买之前提前分析这种情况会怎么样?
上图是针对 Sensex 指数在未来 3 个月上涨约 8.9%的情景。
使用历史数据、数学模拟和概率,我们可以估计初始投资为 10,000 卢比,最终在 9,300 卢比和 12,000 卢比之间,3 个月后的价值可能接* 10,960 卢比(上图中的天数是指交易日,不是日历日)。
一切都失控了!
继续假设,金融市场也有黑暗的一面。如果类似于 2007-2008 年美国次贷危机及其随后的全球蔓延现在突然发生,会怎样?
对印度市场而言,正在发生的 NBFC 违约及其基础资产质量问题似乎有些类似,但规模要小得多。
以“ICICI 保诚蓝筹基金-股息”为例,如果现在发生类似 2008 年全球市场崩盘的情况,其资产净值在未来一年内可能会降至 9.5(约为其当前价值的 43%)。
一种担忧可能是,如果在这样一场历史危机中,该基金从未存在过,那么如果这样的事件(或类似事件)现在发生,我们如何评估它的表现?事实上,上面的例子基金是 2009 年 4 月才开始的。
用于得出上述分析的方法允许我们为这种场景(压力事件)精确建模。适用于印度市场的四因素模型用于确定基金业绩对模型因素的敏感度。为基金生成的回归模型用于预测历史事件,即使该基金当时从未真正存在过。
包裹
果然,看待金融投资风险有多种方式。不同的性格和生活环境认为一种方式比其他方式更重要。但是,在我们睁大眼睛面对风险的情况下做出的投资决策应该会减轻很多焦虑和压力。
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
研究用于科学数据集的可区分神经架构搜索
原文:https://towardsdatascience.com/investigating-differentiable-neural-architecture-search-for-scientific-datasets-62899be8714e?source=collection_archive---------28-----------------------
哈佛数据科学顶点项目,2019 年秋季
In partnership with Google AI.
团队成员:迪伦·兰德尔、朱利安·拉斯里、迈克尔·伊曼纽尔、庄嘉玮
免责声明:本博客中表达的观点和意见仅属于作者个人,并不代表哈佛或谷歌。
对高效神经结构搜索(NAS)的需求
深度学习把我们从特征工程中解放出来,却产生了一个“架构工程的新问题。已经发明了许多神经网络体系结构,但是体系结构的设计感觉上更像是一门艺术而不是科学。人们对通过神经架构搜索(NAS) 来自动化这种耗时的设计过程非常感兴趣,正如数量迅速增长的研究论文所示:
Figure from Best Practices for Scientific Research on Neural Architecture Search.
典型的 NAS 工作流包括(1)在预定义的搜索空间内提出候选体系结构,(2)评估所提出的体系结构的性能,以及(3)根据搜索策略提出下一个候选体系结构。
Figure from Neural Architecture Search: A Survey.
有许多搜索策略(在调查中回顾),包括强化学习、贝叶斯优化、进化算法、基于梯度的优化,甚至随机搜索。一些策略可能非常昂贵,消耗大量能源,并导致数百万美元的云计算账单:
Figure from Energy and Policy Considerations for Deep Learning in NLP; NAS cost is based on evolutionary architecture search on Transformer.
在这个项目中,我们研究了一种高效的基于梯度的搜索方法,称为 DARTS(可区分架构搜索),最*在 ICLR 2019 发表。据显示,DARTS 比以前的方法如 NASNet 和 AmoebaNet 需要的 GPU 时间少 100 倍,并且与来自谷歌大脑的 ENAS 方法具有竞争力。我们将把 DARTS 与随机搜索(实际上相当不错,见下表)和最先进的手工设计的架构(如 ResNet )进行比较。
Figure from the DARTS paper.
科学数据集
大多数 NAS 研究,包括最初的 DARTS 论文,都使用标准图像数据集报告了实验结果,如 CIFAR 和 ImageNet 。然而,我们认为深度学习显示出科学研究的前景,包括生物学、医学、化学和各种物理科学。在这个项目中,我们想看看 DARTS 是否对科学数据集有用,以及神经结构如何在这些领域之间转移。
我们使用来自材料科学、天文学和医学成像的三个数据集,具体来说:
- 石墨烯 Kirigami: 切割石墨烯优化应力/应变。来自《物理评论快报》上的论文使用机器学习加速搜索和设计可拉伸石墨烯 kiri gami。
- 星系动物园:从望远镜图像中分类星系形态。来自银河动物园 2 和卡格尔银河动物园挑战赛。
- 胸透:从胸透预测疾病。来自论文 ChestX-ray8 和 Kaggle NIH 胸部 x 光数据集。
Example data from the three datasets (left to right): Graphene Kirigami, Galaxy Zoo, and Chest X-Ray.
我们还以(一个众所周知的用于分类手写数字的图像数据集)作为非科学基线进行了实验。
可区分神经结构搜索(DARTS)
有 3 个关键的想法使飞镖有效:(1)只搜索小“细胞”,(2)重量共享,和(3)持续放松。每个想法都解决了传统搜索方法中的一个问题,如下图所示。
Issues with brute-force NAS and solutions proposed by DARTS.
DARTS 搜索小“单元”以减少搜索空间
为了避免搜索所有“任意架构”的巨大空间,DARTS 利用了一个重要的观察结果,即流行的 ConvNet 架构通常包含重复的块,按顺序堆叠。例如,ResNet 是残差块的序列:
Figures from here and here.
遵循类似的思路,DARTS 只搜索最优的“块”或“单元”,而不是整个模型。一个单元通常由大约 5-10 个操作组成,用有向无环图(DAG)表示。所有单元按顺序堆叠以形成整个模型。
Example of a reduction cell stacked to create a full model.
DARTS 中定义了两种类型的单元:(1)保持输出空间维度与输入空间维度相同的“正常单元”,以及(2)将输出空间维度减半同时使滤波器/通道数量加倍的“缩减单元”。所有正常细胞共享相同的架构(操作和连接),但具有独立的待训练权重——所有 reductions 细胞也是如此。
DARTS 使用“连续松弛”来实现建筑参数的梯度下降
下图总结了查找最佳单元的步骤:
Schematic of the DARTS continuous relaxation and discretization methods.
“找到最佳单元”等同于“在 DAG 的边上找到操作的最佳位置”。DARTS 不是独立评估各种布局(每种布局都需要从头开始训练),而是叠加所有候选操作(例如,Conv 3x3、最大池、身份等)。)上,因此它们的权重可以在单个过程中一起训练。edge (i,j)处的实际操作是所有候选操作 o(x)的*均值,用α加权:
Each edge is a linear combination of pre-defined operations weighted by the softmax output of the architecture parameters.
有了一定的架构权重α的选择,相应的架构原则上可以被训练收敛,导致最优的模型权重 w (α)和最终的验证 损失 L ( w (α),α)。 L w.r.t .到α的梯度给出了架构参数梯度下降的方向。
通过每次训练 w 收敛来计算真实损耗 L 代价太高。因此,DARTS 只训练 w 一个步骤来获得代理损失:
DARTS utilizes a one-step approximation to avoid training weights to convergence at each architecture update step.
*其中最佳模型权重 w (α)通过一步训练来*似。
α和 w 的训练交替进行;
Bi-level optimization procedure for training regular model weights and architecture parameters.
实验结果
下面,我们总结了用 DARTS、随机搜索和 ResNet 得到的结果。我们报告了有和没有架构离散化(我们分别称之为“离散”和“连续”)的 DARTS 的结果。
Results of DARTS (continuous & discrete), Random Search, and ResNet on each dataset.
MNIST
如前所述,我们首先用 MNIST 做实验。这立即让我们发现了超参数在训练中确保稳定性的重要作用。下面我们展示了适当调整学习率(常规权重和架构权重)的效果。
Learning curves of DARTS on the MNIST dataset demonstrate the important of appropriate hyperparameters.
在 MNIST,雷斯内特比飞镖表现更好。这并不奇怪,因为手工设计的架构通常专门针对 MNIST(以及 ImageNet、CIFAR 等)等数据集进行了优化。).考虑到这一点,我们继续前进到主要的科学数据集。
石墨烯 Kirigami
石墨烯 Kirigami 的任务是从石墨烯片的切割构型预测拉伸性能。这些数据来自于(计算成本很高的)数值模拟。
Overview of the Graphene Kirigami task.
我们发现,连续(非离散)飞镖和 ResNet 在这项任务中表现得差不多。但是,我们也发现,这个任务可能过于简单,无法评价飞镖。下面我们展示了 DARTS、ResNet 和“微小”ResNet 的结果。请注意,即使这个“微小”的模型也达到了大约 0.92 的最佳 R。
*Table showing that even tiny models can perform well on the Graphene Kirigami task. Time to run 30 epochs on a single GPU.
这让我们得出结论,石墨烯 Kirigami 任务对飞镖来说太简单了,没有用。我们通过查看 a)学习到的架构权重的分布,以及 b)随机搜索架构的性能分布,进一步研究了这一概念,如下所示:
Graphene Kirigami architecture weights (left) and random search performance (right). Our conclusion is that simple problems admit many performant architectures, and that DARTS induces low sparsity in architecture weight space as a result.
特别值得注意的是,DARTS 学习的大部分架构权重几乎没有从它们的初始值 1/8 改变(在这个实验中我们有 8 个操作)。我们还看到,除了几个主要的异常值之外,来自随机搜索的架构都表现得非常相似。这使我们得出结论,石墨烯 Kirigami 问题允许许多高性能的架构,因此 DARTS 同样不会学习稀疏架构。
银河动物园
受到石墨烯任务中发现的明显缺乏难度的启发,我们寻求一个更复杂的科学兴趣问题。我们选定了银河动物园挑战赛。与典型的分类问题不同,由于目标标签是人类贴标机的*均预测,因此该任务基于均方根误差(RMSE)度量来评分。任务是将星系图像回归到人类标签员对 37 种不同属性的*均预测。
Summary of the Galaxy Zoo “decision tree”. It is a logical map over the various observed galaxy morphologies.
令人兴奋的是,我们发现飞镖(连续)表现最好。如果我们检查架构权重和随机搜索性能(如下),我们会看到 DARTS 学习了比石墨烯任务更稀疏的细胞。此外,随机架构性能的可变性(注意对数标度)非常大。这表明,对于星系动物园问题,确实有一些架构比其他架构好得多。看来飞镖在学习细胞中引起了一些稀疏,反映了这一点。
Galaxy Zoo architecture weights (left) and random search performance (right). Large variance in architectures → sparse cell learned by DARTS.
虽然这些结果表明 DARTS 能够学习优于 ResNet 的单元,但是在离散化架构之后,性能严重下降。这突出了一些评审员对原始 DARTS 论文的评论中提出的观点,特别是:
从某种意义上说,如何从一次性模型转移到单一模型的最后一步是这项工作最有趣的方面,但也是留下最多问题的一个方面:为什么这样做?是否存在这样的情况,我们通过将解舍入到最接*的离散值而任意地损失惨重,或者性能损失是有限的?从放松到离散选择的其他方式是如何工作的?
我们的发现表明,离散化步骤是启发式的,我们表明,它可以在实践中失败。
胸部 x 光
为了看看我们在《银河动物园》上的结果是否可以应用到另一个困难的科学数据集上,我们研究了胸部 x 光成像数据集。任务是对来自胸部 X 射线图像的各种疾病(多种疾病可能存在或不存在)进行多标签(二元)分类。
Example chest X-rays (left) and disease proportions in the training set (right).
在这里,我们发现连续飞镖适度优于 ResNet。检查架构权重和随机搜索性能(如下所示),我们看到一个类似于银河动物园的故事。从随机搜索性能图来看,似乎有些架构的性能比其他架构好得多(再次注意对数标度)。我们看到 DARTS 似乎已经学会了一些体系结构权重的稀疏性,这反映了所有体系结构空间中的一些体系结构比其他体系结构更适合这个任务的概念。
Chest X-Ray architecture weights (left) and random search performance (right) distributions. Again, large variance in architectures → sparse cell learned by DARTS.
我们再次注意到,离散的飞镖模型表现明显不如连续的。
结论
总之,我们认为飞镖是一个有用的工具,但对于简单的任务来说,它是多余的。我们表明 ResNet 和 random search 的性能相当好,但是 DARTS 的性能稍好一些。我们注意到 DARTS 引入了许多额外的超参数,必须仔细调整以确保稳定的学习。最重要的是,我们表明 DARTS 的“离散化步骤”在实践中可能会失败,需要更好的技术来确保健壮性。
我们对任何考虑飞镖的人的最后建议是:如果性能的小幅度提高对你很重要(例如准确度提高 1%),飞镖可能是有帮助的,值得你花时间去研究。
未来的工作
我们对未来工作的建议一般来自结论。具体来说,我们建议:
- 为超参数自动调整和/或设置更好的默认值
- 通过以下方式修正离散化试探:a)用 sparsemax 代替 softmax 来鼓励稀疏性,或者对架构权重进行 Lp 正则化(用p1 ),或者 b)在训练期间动态修剪架构以移除组件,消除重新训练离散化模型的需要。
作为最后一点的替代,可以简单地取消离散化步骤(正如我们在这里报告连续结果时所做的)。但是,这将不再是真正的“架构搜索”,而可能被视为一种全新的架构类型(这并没有什么错,但也许有些人对坚持架构搜索的目标感兴趣)。
承认
我们要感谢 Pavlos Protopapas(哈佛)、Javier Zazo(哈佛)和 Dogus Cubuk(谷歌)在整个工作过程中给予的支持和指导。
**有关哈佛数据科学峰会的更多信息,请访问:【capstone.iacs.seas.harvard.edu **
代码可用性
我们处理各种科学数据集的定制 DARTS 代码可以在:https://github.com/capstone2019-neuralsearch/darts找到
运行代码的完整说明可以在这里找到:https://github . com/capstone 2019-neural search/AC 297 r _ 2019 _ NAS
基于 ICA 和层次聚类的章鱼伪装研究
原文:https://towardsdatascience.com/investigating-octopus-camouflage-with-ica-and-hierarchical-clustering-df0e9a4ffaf4?source=collection_archive---------18-----------------------
神经科学家如何用机器学习算法研究这种惊人的技能
头足类动物(章鱼、鱿鱼、乌贼)在伪装的技术上是天生的大师:它们可以在几秒钟内改变皮肤的颜色,以适应周围的环境,并完全消失在背景中。如果你从未看过这个,我邀请你花 5 分钟来欣赏这个 Ted 演讲。如果你真的赶时间,可以直接跳到最后一分钟,欣赏章鱼的以下表现:
Hey there (from David Gallo’s Ted talk, at 4:19)
这种能力几十年来一直困扰着科学家和机器学习专家(没有必要坚持这种机制如果成功复制可能会对许多行业产生的结果……)。计算机视觉科学家目前需要在数千次试验中训练神经元网络,然后才能提取复制背景环境所需的特征。但是头足类动物有能力在几秒钟内完成这个动作。
A cuttlefish
出于这个原因,德国的一组神经科学家,在 Gilles Laurent 博士的带领下,对乌贼的伪装行为进行了录像研究。这篇文章描述了他们的一个发现。
(原文可以在这里找到*但是需要订阅《自然》杂志才能免费阅读...想了解更多信息,你还可以观看科学家们在* 这个视频 中讲述他们的工作。)
首先,一点生物学知识:头足类动物的皮肤怎么会变色?他们的皮肤一点也不像我们的皮肤。它们的皮肤表面覆盖着充满色素的小“袋子”,这些小“袋子”被称为 色素细胞 。视内部的色素而定,色素细胞可以有不同的颜色。简单来说,一般有两种:深色的和浅色的(黄色的)。
a) Zoom on an adorable squid’s skin, with dark and light chromatophores. b) Muscle contraction streches the chromatophores and the pigment expands. Figure adapted from this paper in Nature Communications.
诀窍在于这些色素细胞的大小是由动物控制的!每个袋子都由几块肌肉环绕着:如果肌肉放松,袋子就会变小。但是如果动物收缩这些肌肉,袋子就会膨胀,色素就会扩散。这些肌肉由一些被称为“运动神经元”的神经元控制。这项研究的全部目标是调查神经元,即使是间接的!
为了更好地理解伪装技巧,科学家们认为他们必须非常注意这些色素细胞的大小。因此,他们设计了一个分析管道,在动物皮肤上追踪它们。
开发一个工具箱来跟踪成千上万的色素细胞并提取它们的大小当动物在水箱中移动时,这本身就是一个巨大的成就。然而,我选择在这篇文章中关注另一个结果。因此,我邀请你快速浏览一下我的第一篇帖子这里,它描述了另一个例子(检测神经元并从一个透明的鱼大脑视频中提取它们的活动)的预处理管道的原理。我将其简单总结为 3 个步骤:
- 首先,来自乌贼皮肤的每个图像被对齐(旋转或*移)以匹配参考图像的方向。
- 然后,定位色素细胞。
- 最后,提取每个色素细胞内的像素数量。
The (simplified) analysis pipeline to monitor the size of thousands of chromatophores in time. Have a look at this post for more detailed explanations. Image modified from Fig1 in the original publication.
这个预处理步骤从乌贼图像中创建了一个可利用的数据集:一个矩阵【色素细胞 x 时间】,其中每个元素是一个时间点上一个色素细胞的大小。然后,机器学习算法可以很容易地应用于深入了解这些成千上万个充满颜料的袋子的行为。
(例如,主成分分析可用于将该数据集的维度从几千个减少到 3 个,以便在 3D 中绘制该系统的时间演变。这将在另一篇文章中描述:“神经科学中的 PCA 和 tSNE:可视化的降维”)
让我们关注主要目标:通过研究色素细胞大小的进化,神经科学家实际上想评估控制肌肉的运动神经元的活动。尺寸只是一个间接的测量。然而,事情并非如此简单(总是在研究中),因为人们很快意识到:
- 一个运动神经元可以控制几个色素细胞。
- 一个色素细胞可以由几个神经元控制。
这需要首先解决。这里的问题是在不知道源信号或混合过程的情况下,从混合信号(色素细胞活性)中推断源信号的值(运动神经元活性)。这是盲源分离的一种情况,在这种情况下使用的好算法是 ICA : 独立分量分析。ICA 的假设如下:
- 源信号在统计上是独立的
- 源信号是非高斯的
根据中心极限定理、如果源信号是独立的(hyp1),那么它们的混合将趋向于高斯分布,即使源信号本身不是高斯(在维基百科页面* 这里 ) 很好的图解了这个定理。如果加上假设 2,这意味着混合信号的分布将总是比源信号的分布更加高斯。目标是找到一个新的空间,使分布尽可能远离高斯分布,如下图所示:*
If the source signals are independent and non-gaussian : a) the ICA algorithm can recover them from the mixed signals. Adapted from an image found here. and b) a new space can be found where the distributions are as far away from gaussian as possible. Adapted from images found here.
实现 ICA 的方法有很多种,因此,在这篇文章中,我更愿意把直觉留给你,并邀请你查阅我们在 web 上可以找到的许多资源(比如来自法国神经科学家的这个* 网站 或者来自赫尔辛基大学的这个 网站*)。**
让我们回到我们的乌贼:根据色素细胞的活动,ICA 允许我们评估运动神经元的活动。Hyp 2 很容易满足,因为我们在生物学中记录的大多数东西都没有高斯分布。但是 Hyp1 有点棘手:我们不能假设每个运动神经元都是相互独立的,但是我们可以接受 ICA 将几个不独立的运动神经元组合在一起)。因此,色素细胞将被归入“运动元件”: 同一“运动元件”中的所有色素细胞基本上由同一运动神经元 (或运动神经元群)控制。
Reprinted by permission from Springer Nature : Nature, Elucidating the control and development of skin patterning in cuttlefish, Reiter et al (2018), License nb 4486000735048.
结果可以用这个图来说明(来自原始出版物):红色圆圈内的色素细胞被发现由同一个运动神经元控制(我们可以注意到它们都是黑色的),蓝色圆圈内的由另一个控制(它们都是黄色的,除了一个)。第一个定义是,一个运动神经元本质上控制几个相同颜色的色素细胞!左边的痕迹代表每个色素细胞在时间上的大小,我们称之为“活动”。在同一个运动元素内,活动看起来是同步的。然后使用*均活动来表征运动元素。
基于这一结果,科学家们使用层次聚类将具有相似活动** 的运动元素分组在一起(一个运动元素=一组代表一个运动神经元的色素细胞。)。在另一篇“迈向数据科学”的文章中已经很好地描述了分层聚类,我邀请您在这里 阅读 。(你也可以观看 这段视频 来了解在生物学中如何使用等级聚类来对具有相似表达的基因进行分组。)**
简而言之,该算法计算每个运动元素之间的相似性,并创建一个 树状图 。然后,选择一个阈值,该阈值将创建聚类。在这里,研究人员使用“相关距离”作为相似性度量: d = 1 — r (r 为相关系数)。
- 如果 2 个电机元件完全相关,r = 1,d = 0。它们之间的距离为零:它们在空间上非常接*,因为它们是相似的。
- 如果没有相关性,r = 0,d = 1。它们之间的距离增加了。
- 如果两个运动元素是反相关的,r = -1,d = 2。
结果可以在下图中看到:左上方是一张乌贼皮的照片。我们将重点关注由矩形界定的白色斑块。
Reprinted by permission from Springer Nature : Nature, Elucidating the control and development of skin patterning in cuttlefish, Reiter et al (2018), License nb 4486000735048.
右上方的图像显示了由 ICA 确定的在运动元素中分组的色素细胞,它们在彩色圆圈中,空的或填充的。这对应于阈值为 d = 0 (最大相关性 r = 1)的分层聚类。如果阈值取在 d = 0.4 (绿色箭头,下图)左右,我们可以看到一些运动元素被分组在十几个簇中。如果在 d = 2 附*取阈值(红色箭头,中间图片),我们可以清楚地看到 2 个反相关的簇:白色斑块和黑色边缘。
这表明
- 黑色和黄色的色素细胞由不同的运动神经元控制。
- 这些运动神经元的活动在时间上是反相关的。
这是有道理的:如果动物想要在黑暗的背景中消失,黑色的色素细胞需要扩散,而黄色的需要收缩。所以“黑色控制”的运动神经元会发出收缩肌肉的信息,而“黄色控制”的运动神经元会保持沉默。(如果你对肌肉收缩背后的生理学感到好奇,你可以看看这个视频来了解一下)。
当然,如果动物想要匹配浅色背景,反之亦然,如下图所示:
总之,利用独立分量分析和层次聚类,科学家们能够描述头足类动物如何在背景中伪装。这很鼓舞人心!
本研究由 萨姆·赖特菲利普·胡斯敦西奥多西娅·吴马塞尔·劳特巴赫杰西卡·s·埃伯勒 雅各布·迈耶-克雷多 , 弗里德里希·克雷奇默 , 朱利安·朗格 , 马蒂亚斯·卡舒贝 在的监督下 所有数字均经 Springer Nature 许可复制,许可证号 nb 4486000735048,来自原始出版物“阐明乌贼皮肤图案的控制和发展”,Nature,Reiter 等人(2018)。****
用深度学习研究机器阅读理解问题
原文:https://towardsdatascience.com/investigating-the-machine-reading-comprehension-problem-with-deep-learning-af850dbec4c0?source=collection_archive---------6-----------------------
教机器如何做标准化的类似考试的阅读题。
这个项目和文章是由 约纳曼*罗汉梅内塞斯 和我共同完成的。*
仔细想想,阅读理解是人类思维的奇迹。我们可以拿一段文字,在几乎没有上下文的情况下,深入理解文字的目的,甚至推断出文字中没有的事实,这真的很难,也令人印象深刻。在人工智能和机器学习的世界里,研究人员花费了数年甚至数十年的时间试图教会机器阅读和理解。在过去的几周里,我们的团队致力于解决“阅读理解难题”中的一小部分。
这个任务是如何建模的?
为了有效地测量机器“理解文本”的程度,让我们回想一下人类是如何测试他们的理解能力的:通过标准化的阅读考试!
还记得这些看起来无害,但是非常难的考试题目吗?
A reading comprehension worksheet.
好吧,这些问题看起来很简单。但是,情况并不总是这样!任何参加过更高水*标准化考试的人都知道,阅读理解题会变得很难。现在,我们将重点转向“填空”式问题:给一台机器一篇阅读文章,以及一个多项选择填空问题,它所要做的就是选择最能填补空白的正确选项!听起来很简单,对吧?
事实证明,这个问题对机器来说很难学习。我们称这种“填空”式的问题为完形填空式阅读理解任务。这里面临着许多困难:
- 首先,机器必须首先学习语言的结构和意义。不像人类那样,已经熟悉单词在句子中是如何组合在一起的,并且能够“理解”一个单词背后的真正含义,机器需要以某种方式被教会这一点。
- 第二,在文章中寻找问题的答案可能并不明显。一个人可能会花很长时间在一段文字中寻找答案,而答案可能就在那一页上。对于机器来说,甚至更难;因为语言是高度灵活的,你要找的一系列单词可能不会在文章中逐字出现。
阅读理解如此困难,没有单一的方法可以让机器来解决这个问题。那么,现在我们该怎么办?
再补充一点……机器学习!
为什么我们不利用机器学习的力量来帮助我们解决这个问题呢?
机器学习已经成为阅读文本并从中提取重要概念的一种极其强大的技术;过去几年来,这一直是大多数计算语言学家的困扰。
所以让我们把这种困扰变成一种好的困扰,并把它用在我们的问题上!
首先,简单绕一下:我们将在这个项目中使用 CNN/Daily Mail 数据集。请看一个示例文档/查询:
(@entity1)就是那种你在电影里看到的,像@entity6 在“@entity7”或者@entity9 的“@entity8”里的角色但是,在现实生活中,很难接受一个人被困在海上几天,几周,甚至几个月,还能活着谈论这件事。然而,奇迹确实会发生,而且不仅仅发生在@entity17…
查询:一个@entity156 的人说他从@entity103 漂到@placeholder 一年多了
每个文档和查询都已经经历了实体识别和标记化。目标是猜测应该将哪个实体替换到“@placeholder”中,以使查询有意义。
我们现在的目标是将这个问题公式化为一个合适的机器学习问题,我们可以训练一个模型,并用它来正确预测单词。本着这种精神,我们实际上可以将我们的问题形成为一个二元分类问题;也就是说,给定一个新的文档和查询对,我们可以将其转换成一组新的“文档-查询”对,使得它们的某个子集对应于正确地猜测一个实体符合空白,而另一个子集对应于否定的例子,即正确地猜测一个实体不应该填充空白。
对于每个文档-查询对,我们还创建一些特征来与该对相关联,因为此时将整个对输入到机器学习模型中是不可行的。
我们采用了一个逻辑回归模型来实现这个问题。在训练模型之后,我们达到了 29%的准确率,这意味着 29%的文档正确地填写了空白。对于上下文,数据集中的大多数文档包含大约 25 个实体,因此为每个文档随机猜测一个单词的准确率大约为 4%。所以这个模型表现得相当不错!
逻辑回归模型表现不错,但如果我们诚实地说,29%的准确性并不完全“像人类一样”。那么,如何才能让我们的模型更有效地学习呢?
这就是深度学习发挥作用的地方。当人们阅读文本时,他们不只是学习一些关于文本的启发,然后根据这些启发进行猜测。相反,他们学会理解文本的潜在含义,并根据他们的理解做出有意义的推论。这也是我们在这个问题上的目标!深度学习将为我们提供真正教会机器阅读所需的工具。
新方法带来新目标。从现在开始,我们不想将这个问题局限于二元分类问题,而是更全面地看待这个问题——我们的模型将被允许选择文档中的任何单词作为正确的实体来“填充空白”。这比我们以前的公式更能代表实际的学习。
看…深度学习
使用这些机器学习技术很棒,但我们能做得比这更好吗?一方面,逻辑回归是使用的有效机器学习模型,并且是获得基线准确性的快速方法,但是它在几个方面存在不足。逻辑回归决定一个词是否应该填空的方式过于死板;也就是说,逻辑回归只能学习线性函数,不适用于大范围的问题。
这就是我们现在可以转向深度学习和神经网络的力量来解决我们的问题的地方。神经网络是机器学习中最*的一个热门发展,它允许我们学习比逻辑回归等正常模型更复杂的函数。
在本文中,我们将考虑一种特殊的神经网络,称为长短期记忆,或简称为 LSTM 。这是 LSTM 的样子:
看似复杂,但如果我们一点一点分解,就能明白这个网络在做什么。想象阅读一个句子:当你阅读的时候,你的大脑一个字一个字地思考这个句子,一点一点地形成想法。LSTM 也是如此;它会取一个句子的每个单词,看到一个单词后生成一个隐藏状态。你可以把这种隐藏状态想象成 LSTM 在读到下一个单词时传递给下一个时间步骤的思想。
在我们的问题的上下文中,我们可以将问题后面的段落输入到我们的 LSTM 中,最后根据 LSTM 的最终输出猜测哪个单词最适合查询中的空白。(如果您想知道如何获得最终单词,我们获得的方法是从我们的 LSTM 中获取输出,并为每个可能填充空白单词的可能单词创建一个概率列表。然后我们选择概率最高的单词。)
LSTM 的特别之处(与其他具有类似结构的网络相比)在于,LSTM 能够“记住”句子中较长范围内的单词信息,并能够在必要时快速“忘记”信息。这使得 LSTM 人能够确定在看某个单词时什么是重要的,以及对于之前的单词需要记住什么。
你可能会问:“我们如何将单词输入网络?”我们可以将实际的字符串输入到网络中,但是神经网络很难解析原始的数据字符串。相反,我们使用嵌入来表示每个单词。这包括使用固定长度的向量来表示每个单词,这样 LSTM 就可以很容易地对单词进行计算。理想情况下,我们希望相互关联的单词在嵌入方面更加“接*”。
幸运的是,斯坦福大学 NLP 的优秀人才已经为我们完成了这项任务;他们有一个可下载的嵌入集,名为 GloVe(单词表示的全局向量),已经被证明在自然语言处理任务中非常有效。我们在我们的模型中使用这些,并实现了惊人的准确性提高:39%!这种对基础非深度模型的改进标志着深度学习在能够对这项任务进行建模方面的能力,以及 LSTM 的能力。
线性回归和 BiLSTM 损耗曲线。请注意 BiLSTM 损失率是如何下降的,这是奇妙学习的标志!
我们能做得更好吗?
但是现在我们再次问:我们能做得更好吗?对此的回答也是一个强有力的是!在高层次上,我们想要做的是让我们的模型更像人类一样思考。作为人类,当我们执行阅读理解任务时,我们不只是阅读文本,然后猜测应该在空白处写什么;相反,我们喜欢查看查询,寻找文档中哪些单词更相关,应该更仔细考虑的线索。同样,对于我们的模型,我们引入了注意力的概念。注意力的目标是生成一个矩阵,该矩阵的值表示模型应该给予每个文档单词的相对“注意力”。
为什么关注?
对注意力的直觉来自人类的思维方式。例如,当我们执行阅读理解任务时,我们使用查询来指导我们对文本的阅读。我们关注文本中与查询更相关的特定部分,忽略文本中不相关的部分。我们想对我们的模型做同样的事情。我们希望机器能够理解文本的哪些部分与查询相关,并关注这些部分。下面描述的架构试图做到这一点。
我们的架构:
An example model architecture using attention (Cui et al., 2016). GRUs are basically just fancy LSTMs.
有许多方法可以实现注意力,但是我们选择了上面描述的“注意力总和”模型的一个变体。如上图所示,我们开始将我们的文档和查询放入单独的 GRU 模块中(gru 是带有一些附加功能的 LSTMs)。然后每个 GRU 的输出被如下处理(这是模型的注意力部分!).我们首先计算一下什么叫做“对文档注意力的查询”。这意味着该模型试图理解给定查询中的一个单词,哪些文档单词是最重要的。但是这为每个查询词返回不同的值,所以问题变成了:如果每个查询词对不同的文档词赋予不同的重要性,我们如何决定我们实际上应该听哪个查询词?
为此,我们的模型现在提出这样一个问题:给定一个特定的文档单词,这些查询单词中的每一个有多重要?这给了我们一个衡量每个查询词重要性的标准。然后,我们对每个查询词的重要性进行*均,以获得最终的重要性。然后,将该最终重要性与先前计算的不同文档单词的重要性相结合,以计算每个文档单词的最终加权*均关注度。
The original “Attention over Attention” architecture. We want to improve the process by which the document and query are initially combined.
最后,我们实施了自己的创新,试图进一步改进这个模型。这个模型假设,如果一个文档单词和一个查询单词彼此非常重要,那么它们的表示将非常相似。然而,我们试图通过让模型学习文档和查询之间的重要性关系来改进这一点。类似于我们人类如何计算我们对文本的理解的权重以及文本与查询的联系的权重,我们也希望让机器学习这种关系。我们希望这能让机器对文本和所提问题有更细致的了解。
在撰写本文时,我们还没有设法为我们当前的架构获得好的结果。我们不认为这是因为我们的模型存在缺陷,而是因为一般情况下训练复杂的深度学习模型存在困难。我们从这个项目中得到的最重要的教训是,构建这些模型是极其困难的,测试和修复错误可能非常耗时。我们希望能够在未来进一步完善这个模型,并作为基础模型实现更好的准确性。
最后,我们从这个项目中获得的最重要的教训是深度学习教会机器解决复杂问题的有效性。我们用来建模我们的架构的最初的注意力超过注意力模型具有超过 70% 的最终测试准确性。与 29%的非深度基线相比,这是一个巨大的进步!深度学习在这类问题上大放异彩,我们希望继续并支持这项任务的未来工作,以进一步推进机器理解领域。
关于我们论文的链接,该论文讨论了更多的技术细节,参见 该链接 。
非常感谢Jeffrey Cheng、David Rolnick和Konrad Kording在宾夕法尼亚大学 2019 年春季推出 CIS 700(深度学习),以及他们在整个项目中不断的教学和指导。
为什么可解释的人工智能让风投们兴奋
原文:https://towardsdatascience.com/investor-view-explainable-ai-5ba66b31cd82?source=collection_archive---------16-----------------------
是什么推动了需求,现有公司如何应对,初创公司如何应对可解释性 2.0
Source: DARPA
可解释的人工智能
可解释的人工智能帮助用户理解机器的决策过程。而不是讨论可解释的人工智能的方法(例如,石灰,SHAP 等。),下面是一些维度来围绕这个概念。可解释的 AI 意味着什么,取决于用户、被解释的对象和底层数据。这是一个如此广阔和快速发展的领域,当深入讨论可解释的人工智能时,有一个它如何适应这些维度的心理框架是很好的。本文中的大多数例子都是为分析表格数据的业务决策者构建的产品。
这篇文章不会讨论分类和技术,但是这里有一本由 Christoph Molnar 写的关于分类和技术的很棒的书。未来的一篇文章将深入探讨帮助数据科学家解释、构建和部署模型的工具,如 DarwinAI 的*台,该*台在神经元和层级别探索深度学习模型,以帮助解释其工作原理(同时在相同的功能准确性下,使模型效率提高 4-10 倍)。
可解释人工智能的驱动因素
来自消费者
之前:消费者一直有解释的需求。企业既没有义务也没有动机做出解释。有些人有,大多数人没有。那些这样做的人通常是因为规章制度。
现在:这种情况在最*几年有所改变,大量媒体报道了为法庭( ProPublica )、招聘( Amazon )和贷款决策( Berkeley )开发的有偏见的模型。如果畅销书是消费者想要什么的指标,那么就有凯茜·奥尼尔的《数学毁灭武器》(2016 年 NYT 畅销书),萨拉·沃希特-博特彻的《技术上的错误》(2017 年快公司最佳书籍),以及弗吉尼亚·尤班克斯的《自动化不*等》(2018 年麦甘农图书奖)。虽然这些都集中在人工智能的危险上,但这本书重点介绍的一个常见解决方案是解释人工智能。
来自监管机构
很长一段时间以来,金融监管机构要求银行使用的模型是可以解释的。他们希望确保模型足够稳健,以防止可能反过来危及金融稳定的不良贷款决策。但重点是向监管者、数据科学家和决策者解释模型。《*等信贷机会法》是一个例外,它的重点是向消费者解释。监管机构要求银行提供消费者得不到贷款的主要原因。总体而言,重点是金融服务业。
现在:《GDPR》于 2018 年 5 月生效,是第一部广泛延伸“解释权”的法规。第 13(2)(f)条规定,控制者(决定处理目的和手段的实体)向数据主体提供进一步的必要信息,以确保公*和透明地处理
第二十二条第(1)款和第(4)款提及的自动决策的存在,包括特征分析,以及至少在这些情况下,关于所涉逻辑的有意义的信息,以及这种处理对数据主体的意义和预期后果。
旁注:这也有例外。就业是一个,根据我的阅读。因此,每年收到数百万份申请的公司不必解释每个决定,也不必处理异议或上诉,这是 GDPR 的另一项权利。
来自数据科学家和决策者
以前:没有监管者或用户的推动,对可解释性的需求主要集中在向同事、数据科学家和决策者解释。一个例外是脸书在 2014 年推出的“为什么我会看到这个广告”功能。
Source: Mashable
现在:企业对市场做出反应。随着用户和监管者越来越多地要求各种各样的解释,新的创业公司正在涌现以满足这种需求。推动需求的还有另一种趋势,一种更内在的趋势:工作性质的变化。
新的工作方式需要新的工具
回答“为什么”
在过去的几周里,我与几位数据科学家和分析师进行了交谈,以了解他们的工作情况。他们在解决什么样的问题?他们在想什么?一个共同的线索是,他们的工作是回答“为什么”。为什么销量有增无减?用户为什么会流失?服务器为什么关机?
数据分析师受雇挖掘数据来回答这类问题。有几种类型的分析师,下面选择了其中的一大部分。根据 BLS 的数据,2016 年有超过 200 万名分析师(数据录入员、科学家、IT 分析师除外)受雇,收入 1750 亿美元。
Source: McKinsey
分析师不会花大部分时间直接回答“为什么”的问题。80%花费在收集和清理数据上。10%在分析数据。10%从事沟通和其他行政工作。虽然 10%的时间花在分析数据以回答“为什么”上,但可以说价值超过了 10%。但即使上限为 10%,也至少值 180 亿美元。根据经验法则,一个新产品必须比它好 10 倍或者更便宜,那么这个价值就是 20 亿美元。
改变工作的性质
工作的性质已经改变了。体力和机械工作占据了我们大约 50%的时间,10 年后将减少到大约 40%。这可能看起来不像是一个大的变动,但这里有数据点来显示这是多么大。从 2000 年到 2015 年,互联网、个人电脑、云计算和大数据的普及。有了这些新技术,我们开始自动化工作。然而,从 2002 年到 2016 年,花费在身体和基本认知任务上的时间进一步增加了 2%。我们现在正处于一个转折点,自动化的步伐将会加快。在接下来的 15 年里,花费在机械工作上的工作时间预计将减少 12%。从过去来看,这是一个突然的转变。
Source: McKinsey
随着从死记硬背的工作中“节省”出来的时间转移到更高的认知和社交技能上,工作也将变得对脑力要求更高。根据经合组织的数据,美国员工每年的工作时间保持在 1800 小时左右。更多的时间将花在复杂的数据处理、人员管理和学习新技术上。更多的时间花在回答“为什么”和决定做什么上。这种新的工作方式将导致对有助于这类工作的工具的需求。在下面的章节中,我们展示了一些例子,说明成熟的产品是如何融入新的功能来跟上时代的,而初创公司已经在解决可解释性的下一个问题。
既定产品的可解释性
Mixpanel 的异常解释(2018 年 6 月)
去年,Mixpanel 向其自动异常检测产品添加了解释。一旦检测到异常,Mixpanel 将挖掘数据以找到任何关键驱动因素,这样您就可以节省时间并更快地采取行动。
Source: Mixpanel
Tableau 的解释数据(2019 年 9 月)
Tableau 最*推出了一项新功能“解释数据”,以了解数据点背后的“为什么”。该功能将评估数百种可能的解释,并给出一组有针对性的解释,这样你就可以避免花时间去寻找不存在的答案
Source: Tableau
可解释性的下一步是什么?
现任者已经在构建可解释的特性。但是下一步是什么呢?缺少的是对因果关系的明确关注。我们已经根深蒂固地接受了这样一句格言:“相关性并不意味着因果关系。”但是当我们问“为什么”时,我们真正想知道的是原因。建立因果关系的黄金标准是进行实验(如 A/B 测试)。但是创造和管理实验是昂贵的。因此,像 Optimizely 这样的产品变得有用。它使 A/B 测试变得更加容易。但是在很多用例中,实验是不可行的,或者进行起来仍然很昂贵。我们不能使用我们已经拥有的大量观测数据吗?
来自观察数据的因果关系是下一个可解释的。这不仅是学术研究中的一个活跃领域,也是创业公司中的一个活跃领域。这里有三家有趣的初创公司,它们正处于建立产品市场契合度的种子期和首轮融资阶段。
ClearBrain
一个营销优化*台,使用因果分析来提取用户行为的因果原因(例如,转化、搅动)。它通过自动确定原因,确定可能的行动,估计每种行动的好处,在某种程度上取代了你的分析师。
- 目标用户:营销、增长和产品团队,以发展业务
- 对象:结果
- 数据类型:表格
- 最新融资:$ 2018 年 4 月由 Harrison Metal 领投的 2M 种子轮
Source: ClearBrain
提琴手实验室
一个可解释的人工智能*台来理解模型预测和性能。UI 允许轻松访问可解释技术、行为可视化和审计。他们的团队正在积极研究解决从观察数据推断因果关系的陷阱的方法。
- 目标用户:数据科学家/分析师、决策者/模型用户和监管者
- 对象:结果和模型
- 数据类型:表格(目前)
- 最新融资:2019 年 9 月光速领投的 1000 万美元 A 轮
Source: Fiddler
Sisu 数据
一个运营分析*台,监控您的业务 KPI,并告诉您其变化的原因。插入您的数据库,选择您想要跟踪的 KPI,它将在几秒钟内自动分析大型数据集。它以一种不同的方式处理可解释性——通过将最相关的数据点联系起来。分析师被流数据淹没了。一些公司每秒处理数百万个事件。
- 目标用户:促进业务发展的营销、增长和产品团队
- 对象:结果
- 数据类型:表格
- 最新融资:【2019 年 10 月 a16z 和 NEA 5250 万美元 B 轮
Source: Sisu Data
Kubit AI
专注于 KPI 的增强分析*台,可以处理(真正的)大数据。它能够快速识别异常和原因,同时允许您与您的团队在同一页面上工作。KPI 还针对您的行业(如社交)和使用案例(如参与)进行了优化。
- 目标用户:拓展业务的营销、成长和产品团队
- 对象:结果
- 数据类型:表格
- 最新融资:2019 年 10 月沙斯塔风投 450 万美元种子轮
Source: Kubit AI
对于可解释性和因果关系,仍然有很多领域——文本和图像数据是研究的活跃领域。如果你在这个领域工作,我想请你喝杯酒聊聊天。
观点是我自己的。也可从 kenn.io 获得
看不见的颗粒物质云穿越欧洲
原文:https://towardsdatascience.com/invisible-clouds-of-particulate-matter-move-across-europe-6b39e2d57511?source=collection_archive---------21-----------------------
这些 PM10 和 PM2.5 的云是从哪里来的?
在之前的帖子中,我解释了我如何设置我的室外空气质量传感器,以及它如何产生作为公民科学项目一部分的开放数据。(https://medium . com/@ ignazw/air-quality-measurements-FCC 32d 59 DCA 7)
这是公开数据,任何人都可以分析。在这篇文章中,我将向你展示如何使用 Luftdaten.info 网站来寻找大规模的空气污染模式。
情况
Luftdaten.info 在地图上显示了世界各地所有传感器测量的快照(【http://deutschland.maps.luftdaten.info/#6/51.165/10.455】T2)。大多数传感器在欧洲,所以我将限制我对欧洲的看法。
Sample image from Luftdaten.info
大约每五分钟拍摄一次快照,并更新地图。我想知道如果我们把这些快照拍成延时电影会是什么样子。我们能找到什么模式吗?
获取数据
为了制作延时电影,我们需要捕捉每个快照。Luftdaten.info 上没有维护旧地图,所以我们必须自己收集。
捕获快照需要每五分钟向 web 服务器执行一次 HTTP 请求。我在运行于 raspberry pi 3 上的一个小脚本的帮助下做到了这一点。我想为每张快照拍摄两张照片:一张是欧洲大部分地区的概览,另一张是我居住的比利时的更详细的照片。
在 raspberry pi 上,我在无头模式下使用 chromium web 浏览器,即没有显示。
#!/bin/bash
chromium-browser --headless --disable-gpu \
--screenshot --window-size=1920x1080 \
http://deutschland.maps.luftdaten.info/#7/50.958/8.218
mv screenshot.png ./data/new/de`date +”%Y%m%d%H%M%S”`.png
您可能需要在您的系统上安装或升级 chromium 浏览器。我用的是 72 版的浏览器。确保您运行它是无头的,并禁用 gpu 使用(以避免不必要的库加载到内存中)。
luftdaten.info 网站使用 javascript 呈现地图,但 chromium 浏览器默认执行 javascript。你截取一张截图,然后定义图片的大小。默认的图片名为“screenshot.png ”,因此可以将其重命名为一个独特的名称,比如拍摄的时间。
然后编辑 crontab 以每五分钟运行一次该脚本。
这种大小的一个图像的大小超过 3 MB,因此您需要确保它不会填满您的磁盘。我每天运行一个脚本,将所有图像复制到外部存储空间,我可以从那里提取图像以备将来使用。
我在 MacOS X 上做进一步的处理,包括给截图加注释,并把它变成电影。
我在每个截图上标注了拍摄的时间和数据。我用的是 ImageMagick 包,通过自制软件安装。
#!/bin/bash
for f in $(ls ./images/raw/*.png)
do
fn=${f##*/}
anno=${fn%.png}
magick ./images/raw/$fn -pointsize 72 -gravity southwest \
-annotate +150+50 $anno ./images/annotated/$fn
mv ./images/raw/$fn ./images/tmp/$fn
done
这个脚本读取我在一个目录中准备的所有文件名,并且是 Pi 上收集的图像的副本。它在文件名中包含截图的日期和时间。
对于每个文件,我从文件名中获取日期和时间,并将其设置为图像上的注释。+150+50 定义了距离边缘的像素数。在这个位置,它非常易读。
我将注释后的原始图像移动到一个临时目录,在确定处理正常后,我可以删除它。
下一步是用带注释的图像制作一部电影。为此,我使用 ffmpeg 包,您可能需要像安装 ImageMagick 一样安装它。
以下脚本创建了电影。
#! /bin/bash
# create movie for Germany
ffmpeg -f image2 -pattern_type glob -framerate 5 \
-i ‘images/annotated/de*.png’ -s 1920x1080 -f mp4
-vcodec libx264 -pix_fmt yuv420p germany.mp4
f 标志定义了图像格式。如果您想使用 globbing 来收集图像列表,您需要定义 globbing。你需要在 fps 中设置帧率,然后是实际的输入文件。接下来是输出电影的大小、格式和编解码器。像素格式定义是为了确保 quicktime 也可以播放电影。最后,您命名输出文件。
就这么简单。一旦准备好一些脚本,就很容易多次重新运行。
延时电影
这里有两部时间跨度为 2019 年 3 月 25 日至 31 日的延时电影。一个片段展示了欧洲的大部分,另一个片段放大了比利时。
PM clouds over Europe
PM clouds over Belgium
对结果的讨论
欧洲电影表明,高水*的 PM 是由于大规模的 PM 云在欧洲移动。毫无疑问和天气有关系,但是这些颗粒都是从哪里来的呢?
比利时电影聚焦布鲁塞尔。你可能会认为 PM 水*与交通高峰时间相关,但这在电影中并不清楚,需要进一步研究。也没有显示出与乡村露天壁炉的相关性。如果这种相关性存在,它们也远低于整个欧洲 PM 云的宏观运动水*。
没想到这种行为先验。我们似乎都把责任归咎于交通,毫无疑问,这是原因之一,但更重要的事情正在发生。我们将在以后的文章中深入探讨这个问题。
公民科学很酷!
6 行代码中的 iOS 自然语言处理
原文:https://towardsdatascience.com/ios-natural-language-processing-in-6-lines-of-code-36b08af7f440?source=collection_archive---------14-----------------------
从真实的推文中判断人们的感受
Photo by Hannes Wolf on Unsplash
使用苹果的 CreateML 库和人们过去的推文中的文本,可以非常容易地实现和导出一个用于确定人们感受的 iOS 和 MacOS 自然语言处理模型。让我们下载数据并进行测试!
从上面的链接中解压数据后,拖放。csv 文件放在方便的地方。接下来,在 Xcode 上打开一个游乐场,选择 MacOS,选择一个空白文件。
Make sure to select Mac OS
完成后,导入所需的库:
接下来,从。csv 文件,请确保将文件 URL 路径更改为您下载数据的位置
接下来,我们需要将数据分成训练和测试两部分,可以随意试验分割比例
如果您想要设置种子以便以后跟踪随机分割,请将上面的行更改为:
如果你看一下数据,你会看到它分为两列:一列是标签(正面、负面或中性),另一列包含推文的文本
A look at the csv data
现在我们可以用我们的训练数据来训练模型,
您的 Xcode 控制台现在应该开始解析数据了,
然后它开始训练,
最后,我们可以测试一下它的表现。这超过了我们的 6 线限制,但模型已经完成,所以这不算😏
我把误差降低到了 28%,
如果你能进一步降低错误,让我知道你是怎么做的。就是这样!你做到了!如果您想使用该模型来测试一个随机的文本字符串,以查看它是正面的、负面的还是中性的,这里有一个示例:
当我运行时,我的模型能够正确地预测“pos”。
Correctly identified “pos” on last line
最后,如果您想要导出模型,
像所有 CreateML 模型一样,它将保存为. mlmodel
结论和完整的源代码
所以我们学到了三件事:
- 如果我们有正确的数据,从人们的推文中判断他们的情绪是可能的
- 苹果的 CreateML 库让这变得超级简单
- 整个训练和测试可以在六行代码中完成
既然你知道了这个,你打算用它做什么?你要向你的朋友炫耀吗?你会试着让它更精确吗?或者,你是不是很大胆,打算建立一个股票预测器,利用人们在推特上的情绪来决定价格波动?最后一个可能很难,但我说你要去争取!祝你好运!完整的源代码如下。
有问题吗?你可以在 www.cggonzalez.com 的找到我
物联网在行动
原文:https://towardsdatascience.com/iot-in-action-a8b7fac83619?source=collection_archive---------14-----------------------
什么是物联网,物联网是如何工作的?
它是我们经常听到谈论的一个术语。物联网是一个有点抽象的概念,但在最*几个月越来越受欢迎。他的名字“连接到互联网的日常事物”很好地说明了它试图表达的思想,但实际上,它远不止于此。
要了解物联网是什么,我们还必须了解它的基础一点也不新。大约 30 年来,它一直致力于让所有日常物品变得更具互动性。在我们意识到互联家庭进入物联网之前,智能家庭(也被称为明日之家)等想法已经发展起来。物联网为以前通过闭合电路连接的对象供电,如通信器、相机、传感器等,并允许它们通过使用网络的网络进行全球通信。
如果我们要给物联网下一个定义,可能最好的说法是它是一个使用互联网将物理对象相互连接的网络。所提到的对象使用嵌入式系统,或者相同的专用硬件,其不仅允许互联网连接,而且还基于远程指示的任务来调度特定事件。
来源 hipertextual.com
为什么是物联网?
物联网为组织提供了管理和监控远程操作的创新方法。它允许在遥远的地方拥有眼睛和耳朵,不断地向应用程序和数据存储提供信息。“东西”的低成本允许观察和管理以前遥不可及的活动。借助物联网,还可以收集曾经不可见的事件信息,例如将天气模式与工业生产相关联。
简而言之,物联网是一个基于任何产品与其周围任何其他产品互联的概念。从一本书到你自己家里的冰箱。目标是让所有这些设备相互通信,因此更加智能和独立。为此,有必要使用 IPv6 协议并开发该领域主要公司目前正在设计的众多技术。
其意义在经济和社会领域都至关重要。甚至比数字时代还要古老。那就是物联网允许计算机与现实生活中的元素进行交互,并从人类那里获得独立性,让我们掌握真正重要的东西。
来源 expressvpn.com
source unsplash.com
物联网家庭自动化是物联网的主要应用领域之一。
一个实际的例子:由于物联网,我们的冰箱将能够测量里面剩余的食物,并指示指定的供应商提供用过的物品。因此,我们将永远不用担心买牛奶,鸡蛋或我们最喜欢的酸奶。冰箱将持续测量库存,并相应地独立行动。
可穿戴设备是另一个例子。
由于这一概念的应用,t 恤、手表或手镯等日常用品变得智能。现在,时钟不仅为我们提供时间,还连接到互联网,与外部服务器交换数据,并根据从传感器和服务器收集的信息采取相应的行动。
物联网可穿戴设备是日常物品连接到互联网的一个明显例子。它们也可以更深入地应用于家庭。通过分布一系列传感器和处理器,我们可以自动控制窗户、室内温度、灯光等。而且,由于整个系统都连接到互联网上,也有可能无线控制我们想要的东西。
智慧城市。
物联网的另一个主要应用领域是城市,使城市更加智能和高效。例如,很多时候我们以一种完全荒谬的方式等待红灯,因为我们周围没有车或任何人。由于物联网,这些交通灯可以连接到分布在整个城市的摄像头电路,这些摄像头可以识别交通和群众运动的水*,从而避免在限制运动的区域进行荒谬的等待。
物联网的标准化将产生巨大的经济和社会影响
source unsplash.com
自动驾驶汽车。
物联网物联网也将打开自动驾驶汽车的大门。
物联网应用于城市的另一个例子是交通标志。应用物联网,如果我们以高于允许的速度行驶,我们的汽车将在接收到我们周围任何信号的数据后自动降低速度。与此同时,这将促进自动驾驶汽车在我们生活中的到来和扩展。
如果把物联网带到国家安全或者商业等更广泛的领域,意义和可能性就更大了。例如,自动化果园、智能照明、机器监控……这类项目的经济影响将是惊人的,因为它将取代许多现有的工作,最重要的是,它将节省大量的长期成本。这几乎是第二次工业革命。
正如我们所看到的,物联网显然是科技行业的下一个重大进步。它开启了一个无限可能的世界,甚至比当时开启数字时代的世界还要大。一切都将基于上下文,实现更大的独立性,从人类,因此,更大的效率和舒适。第一步已经开始了(标准、第一个原型和项目等)。),但是,根据各种分析师的说法,直到 2020 年,物联网才会开始在人类中变得更加成熟和普遍。
物联网中的隐私和安全问题
source unsplash.com
最*的一项研究表明,许多公司拥有数以千计的物联网设备(物联网),这些设备与业务没有直接关系,但每天都连接到他们的网络。
来源 universidadviu.com
随着个人财产物联网产品在工作场所的使用越来越多,管理企业网络上未经授权的设备的任务在许多组织中变得越来越困难。
最*,Infoblox 委托对美国 1000 名 IT 主管进行了调查。UU。美国、英国、德国和阿拉伯联合酋长国了解个人用户拥有的物联网设备的安全影响,而不是组织网络中的企业。结果令人震惊:
在前三个国家中,35%的受访者报告说,他们*均每天有超过 5000 台非商业物联网设备连接到他们的商业网络。
在美国、英国和德国,三分之一的受访者表示,在正常工作日,可以发现超过 1,000 台物联网设备连接到他们的网络。
39%的美国 UU 受访者。英国表示,他们在连接到公司网络时使用个人物联网设备来访问社交网络,24%的人承认使用这些类型的设备来下载应用程序,而 13%的人这样做是为了访问他们喜欢的游戏。
商业网络中最常见的未经授权的物联网设备如下:
- 身体活动跟踪器,如 Fitbit 和 Gear Fit。
- 数字助理,比如 Google Home 和亚马逊 Alexa。
- 智能电视
- 智能厨房设备,如微波炉和水壶连接。
这类物联网设备的激增显著增加了组织的安全负担,并提高了风险阈值。由于这种技术的使用增加及其在日常生活中的正常化,安全管理员有一个巨大的任务,只需管理公司网络中受制裁的设备。
L 笔记本电脑和*板电脑正在与另一类物联网设备共享公司网络,其中许多设备的连接不受组织的任何控制,组织甚至不知道它的存在。
添加到公司网络中的不安全和未经授权的物联网设备数量呈指数级增长,这使公司、其用户、客户及其整个网络处于风险之中,因为由于许多这些消费设备的安全级别较低,因此需要应对真正的威胁。
这些类型的不安全和易受攻击的物联网设备为网络中的网络犯罪分子提供了一个薄弱的切入点,并为公司带来了严重的安全风险,可以通过培训、信息和评估来检测它们在网络上的存在,以便及时采取措施。
您是否知道安全性不足的物联网设备可以为网络犯罪分子提供进入公司网络的入口?您是否知道他们会通过 DNS 隧道等方法来帮助窃取数据?
总结一下…
物联网为我们的社会带来了下一次工业革命的无数可能性,即将到来的设备将足够自主,来执行我们今天所做的重复任务,并有可能通过技术将城市、社区和人们相互连接起来。
感谢阅读,如果你喜欢这个故事,请分享!: )
iPhone 的进化并没有受阻,它正处于(机器)学习曲线上
原文:https://towardsdatascience.com/iphone-evolution-hasnt-stunted-it-s-on-a-machine-learning-curve-b29237c0adbe?source=collection_archive---------17-----------------------
苹果在 ML 上的进步正在改变 iOS 的一切
The new A13 Bionic chip announced for the new iPhone 11 Line-up. Screenshot taken from Apple’s iPhone 11 Pro Announcement.
从各种媒体的角度来看,智能手机的发展似乎非常缓慢。这十年的早些时候,当我们对高清显示屏、3G“移动宽带”的飞跃、前置摄像头的增加以及更小(然后,最终更大)的手机尺寸感到兴奋时,很难没有这种感觉。这些有形的硬件特征是巨大技术进步的视觉标志。我们变得习惯于设定很高的期望并让他们被超越。
我们活着就是为了,我喜欢称之为,即时满足的特征。苹果(和他们的竞争对手)知道这一点,在这个时代,这种功能是少而薄的。这就是为什么我们现在获得了像素数量增加(一般消费者的眼睛几乎注意不到)、额外的相机镜头和更长的电池寿命(等等)的年度展示。
如果你去 iPhone 11 Pro 产品页面,页面的四分之三都在专门展示摄像头和显示屏的增强功能。没什么可轻视的,但由于所有的新功能,它们已经成为通常的怀疑对象,这些功能仍然会引起普通消费者的轻微上升。
面对现实吧。*年来,iPhone 最大的轰动不是而是其中之一是凹口设计和价格上涨。
(某种)无名英雄
在同一个 iPhone 11 Pro 产品页面上,在相机和显示器营销之后的第三个季度,是关于新 A13 仿生芯片的信息。苹果肯定对其下一代芯片感到兴奋,并且从未保守秘密。但我认为普通消费者会这样看待这一部分:
听起来是不是很花哨?它有“仿生”这个词,所以是的。背景中“A13”的高科技图形看起来酷吗?检查。对我这个普通消费者来说意味着什么?更快,更快,核心,增强现实,更快…哦,优化的电池寿命!下一部分是关于更好的电池寿命!太棒了,我们继续吧!
结束场景。
只是一个模子刻出来的?
这可能是一种过度的描述,但它离现实并不远。我们都坐着看完了演示的这一部分,但我无法告诉你有多少次人们和我一起看(请注意,是在技术方面!)开始看他们的手表,说“已经开始吃好东西了!”。
我们期望我们设备的内部性能逐年提高。这种主要的技术已经在个人电脑市场上出现了。可以理解的是,普通消费者并不完全了解这些改进与他们所了解的功能之间的关系,这也于事无补。在我看来,不能将点点滴滴联系起来,就是为什么我们对这些年来的进步以及它如何影响我们今天手机的每一个功能几乎都变得麻木了。
这就像当一名运动员花了整个休赛期的训练比以往任何时候都更加努力,一个新的养生法,几乎在球员的每个方面都有要求。我们的期望是他们会训练,所以我们不会欣赏他们的任何进步,直到我们,球迷,看到了在行动中证明的结果,在胜利中,当然,还有幻想的分数。
Think of a swimmer who trains, focuses on areas of their technique to tweak, and adopts new practices into their daily regimen. All of that just to optimize power, performance, and efficiency, ultimately shaving off crucial seconds on their time.
这可能就是为什么两年前大多数消费者只是点头通过 A 系列仿生介绍。它为 iPhone 的工作方式引入了一个全新的优化架构。但不仅如此,它给了我们一个神经引擎,一个机器学习和人工智能的移动发电站。这就是为什么 Face-ID 可以同时推出的原因(这意味着它也启用了凹槽设计)。
仿生成就
以下是 A 系列仿生进化的一些公认的第一方成就:
Sribalan Santhanam, Apple’s VP of Silicon Engineering, introduced some of A13 Bionic’s improvements and new capabilities at the September event
- 摄像头:苹果在其网站上声明,A 系列的神经引擎是三摄像头系统背后的“驱动力”。虽然镜头有所增加和改进,但大脑使人像模式、夜间模式和 SmartHDR 等功能工作得如此出色。
- 视频和游戏:随着更高分辨率的显示器,4K 流成为一种规范,以及移动游戏图形接*上一代游戏机的水*,无疑需要更多的马力。然而,A13 中的 GPU 速度提高了 20%,而功耗却降低了 40%。也许 iOS 上的 Skyrim 终究不是太遥远…
- 速度和电池寿命:仿生机器人内部的架构很复杂(CPU、GPU、神经引擎等),这是有道理的。还记得在学校的小组项目吗?如果在团队中分配工作,特别是当任务分配给那些有天赋的人时,整个事情会进行得更快。然而,当团队将它留给一个不幸的人时,这个人不得不管理项目的所有方面,有时不得不牺牲他们擅长的方面的质量,因为他们需要在他们不擅长的领域花费更多的时间和精力。这个概念适用于这里。
未来是学习
这个行业总是在寻找“下一件大事”。iPhone 本身是智能手机和应用程序革命的催化剂,这场革命改变了科技领域的一切,并为那些投身其中的人赚了很多钱。那么下一步是什么?
机器学习是佼佼者。现在它无处不在,从 Alexa ,到 IBM Watson ,到你手机上的纵向模式。潜在的应用是无限的,可以跨越金融、医药、建筑和安全。
为什么是现在
今天,传媒业发展更快,因为它所依靠的技术更容易获得,更强大,更省时,也更便宜。进化把我们从房间大小的大型计算机带到了网络上的远程云机器,现在有一个完整的神经引擎内置在你的口袋里的手机里。
对于 iOS 和 ML/数据科学开发者来说,这是一个异常激动人心的时刻(或者至少应该是)。苹果通过两种重要的方式让开发者可以使用 ML。首先,他们提供了开发者工具包和工具,简化了在我们的应用程序中使用 ML 的流程(T2 的核心 ML 和 T4 的创建 ML 是其中的几个)。第二,他们已经把所需的硬件放进了用户的口袋。以前,如果在移动设备上运行,开发人员要么不得不缩小他们的人工智能能力,要么他们需要在一些远程服务器上运行工作,他们要么支付租金,要么拥有和维护并发回结果。苹果本质上是通过弥补差距为开发者进入 ML 进行投资。
Just some of the new and enhanced features introduced to developers at Apple’s WWDC 2019. Screenshot taken from WWDC presentation.
随着越来越多的开发人员意识到,即使是最小的 ML 集成也可以转化为他们应用程序中令人难以置信的新功能和增强功能,这种投资将会得到回报。随着第三方和第一方应用集成越来越多的 ML 功能,苹果可以为其用户吹嘘一个更强大、更稳健的应用商店目录。这可能会给开发者和苹果应用商店带来更大的创纪录利润和收入。
从内到外设定期望
智能手机新功能的未来像老鹰一样盯着它,这是一件好事也是一件坏事。虽然它促使手机制造商首先尝试并提出新的创新,但有时最终结果可能是噱头或不完整的(比如:某种折叠手机)。
消费者不应该把他们的注意力从这上面移开,而是应该把更多的注意力放在引擎盖下取得的进步和它给他们带来的价值上。我建议每个人都学习人工智能和人工智能是愚蠢的,但同时,它甚至不再是指日可待的了。就在此时此地。
IPython 笔记本对 Visual Studio 代码的支持终于来了
原文:https://towardsdatascience.com/ipython-notebook-support-is-finally-here-for-visual-studio-code-b578abe0361c?source=collection_archive---------7-----------------------
这个月 Visual Studio Code code 得到了一些意想不到的,有点酷的特性。直到现在,除了在浏览器内的笔记本环境(据我所知是)之外,在任何地方编辑 IPython 笔记本都是不可能的,但现在不再是这样了。
在本文中,我将向您展示如何在您最喜欢的代码编辑器(可能是)中直接编辑笔记本,并且我们将讨论是否值得进行转换。几年来,Visual Studio 代码一直是我的首选代码编辑器,主要是因为有大量的插件。此外,主题是整洁的。
在过去一年左右的时间里,我的工作主要是面向数据科学,这意味着我可以通过使用笔记本环境而不是大多数开发人员认为最佳的经典文本编辑器方法,在更短的时间内完成更多工作。不能像我想的那样使用我最喜欢的代码编辑器是一件非常令人失望的事情,但事实就是如此。至少到目前为止。
让我们快速浏览一下本文将涉及的主题:
- 如何下载 Visual Studio 代码
- 下载插件和编辑笔记本
- 选择正确的主题
- 结束语
事不宜迟,让我们进入第一个话题。
如何下载 Visual Studio 代码
根据您的操作系统,安装过程会有所不同。我在 Windows 上,所以这就是我要覆盖的。我怀疑在 Mac 或 Linux 上安装会更困难。首先要做的是打开这个页面,点击那个蓝色的大粗体按钮,上面写着Windows下载:
下载完成后,你只需要打开 。exe 文件,并点击下一步几次。大约一分钟后,你就可以开始摇滚了。
一旦 VS 代码第一次被打开,它看起来就不会那么神奇了。这是它在我的机器上的样子:
我们将很快解决这个有点难看的外观。
下载插件和编辑笔记本
如果你马上打开 IPython 笔记本,你不会得到你想要的:
你得到一些看起来像 JSON 的代码,这不是你应该编辑的。我的意思是如果你想的话,你可以,但是为什么呢?
首先,你需要安装由微软开发的对 Python 的支持。点击我在下图中时髦地高亮显示的按钮,输入 python 。安装您看到的第一个:
该扩展将在几秒钟内安装完毕,您可以开始使用了:
如果您现在打开某个 IPython 笔记本,结果会更令人满意(记住,在这里打开笔记本比在 Jupyter 环境中打开要花更长的时间):
瞧啊。很简单,对吧?好吧,让我们现在做点什么,让一切看起来像是 2019 年。
选择正确的主题
在开始之前,我只想声明,这部分是有偏见的,我所说的一切只是我的观点。您应该以任何您认为理想的方式来设计编辑器的样式。你可以像几分钟前安装 Python 插件一样安装主题。简单。
以下是我发现非常适合笔记本的主题列表:
- 原子一暗
2。Monokai 变暗
3。灯光(Visual Studio)
尽管我是材质主题的超级粉丝,但我真的不推荐它们用于笔记本设置,因为它们移除了单元格边界——最终结果看起来有点奇怪。
这就是了,一切都和 Jupyter 中的一样。你通过按 SHIFT + ENTER 来运行单元格,一切都感觉像它应该感觉的那样。
但是开关值得吗? 下一节找出我的看法。
结束语
到目前为止一切顺利。
问题仍然是,你真的应该做出改变吗?
此时此刻,我的答案是否定的,原因有二
- 代码执行比在 Jupyter 环境中要慢一些。不至于影响到你偶尔的数据分析项目,但是如果你每天都这样做,那么 Jupyter 仍然是一个不错的选择。
- 打开笔记本需要更多的时间
像 Jupyter Lab 这样的环境,看起来已经有点像一个复杂的代码编辑器,我发现缺少 Visual Studio 代码。至少现在,谁知道未来会带来什么。你至少应该尝试一下,我不建议你只依靠我的意见。也就是说,我希望插件在未来得到优化。
你有什么想法?你换了吗?让我知道。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
* [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)*
智商与成功——在双变量分布中使用蒙特卡罗模拟
原文:https://towardsdatascience.com/iq-vs-success-using-monte-carlo-simulations-in-bi-variate-distributions-a19b32ef8882?source=collection_archive---------20-----------------------
塔勒布关于智商的推特帖子,今天在办公室引发了一场有趣的讨论。智力(用智商来衡量)能有效预测工作成功吗?
对于一个智商高于*均水*的员工,他/她的表现高于*均水*的概率是多少。研究表明智商和成功的相关系数为 0.5。成绩和智商都是正态分布。
在本帖中,我们将使用蒙特卡洛模拟来回答这个问题。我们将探讨联合概率分布、相关性和双变量正态分布的概念。
联合概率分布
解决这个问题的最重要的想法是理解联合概率分布的概念。特别是在这种情况下,我们想要计算“成功”和“智商”的联合概率分布函数(PDF)。为了理解联合 PDF,让我们举一个最简单的抛硬币的例子。比方说,我们有两个硬币,我们把它们一个接一个地扔出去。每次翻转都是具有伯努利分布的伯努利轨迹。掷硬币的联合概率密度函数定义了每对结果的概率,如下所示。
Joint probability distribution for coin toss
计算“成功”和“智商”的联合 PDF 有点复杂,因为这些变量是连续的。但是你可以想象一种情况,你想计算“成功”在一个特定范围内而“智商”在另一个范围内的概率。作为一个例子,你可以用下面的表格来计算“成功”和“智商”(附加说明:两个变量的比例是任意的)。
如果我们能够生成上面的表格,我们就能够计算出一个智商高于*均水*的人会有多成功。但在此之前,我们必须理解相关性和/或协方差的概念。
相关性和协方差
在上面掷硬币的例子中,投掷是独立的。第二次投掷和第一次投掷没有联系。因此,当我们看到一个头作为结果 1 时,我们同样有可能得到头或尾作为结果 2。在这种情况下,“成功”和“智商”这两个变量是相互关联的。有许多关于成功和智商之间关系的研究。快速的互联网搜索会产生多个结果。一些研究表明相关性很高,一些研究表明相关性很低。这里让我们坚持 0.5 的较高相关性,一些研究已经将相关性降低到 0.3。
此外,我们假设“成功”和“智商”都是正态分布的。根据定义,智商是正态分布的。成功不一定。许多组织使用正态曲线来评定员工,但在现实世界中,成功可能不是正态分布的。对于我们这里的例子,我们假设成功也是正常的。由于两个输出变量都是正态分布,已知联合概率分布是二元正态分布或二元高斯分布。
二元正态分布
如果 X 和 Y 是两个正态分布的随机变量。二元正态分布的联合概率密度函数由下式给出
Expression to compute the joint normal PDF given X & Y
其中 𝜌 是相关系数。方程式的推导超出了本笔记的范围。但是,我们将尝试使用 plotly 中的一些可视化工具来探索这种分布的特性。
相互关系
让我们探讨一下“成功”和“智商”是独立的情况。在这种情况下,相关性为零。在下图中,观察 PDF 在 x-y、x-z 和 y-z *面上的投影。x 投影、Y 投影呈正态分布。而 Z 投影是圆形等高线图。
PDF with 𝜌 = 0
Z 的投影非常清楚地显示了 X 和 y 的独立性。轮廓椭圆是圆形的,并且沿 X 轴和 y 轴对称。
Projection of the PDF along XY plane
如果“成功”和“智商”高度相关——比如说 𝜌 = 0.9,我们应该观察到一个轴倾斜 45 度的拉长的椭圆。下面的两幅图展示了“成功”和“智商”高度相关的情况。
PDF with 𝜌 = .9
Projection of the PDF along XY plane
使用蒙特卡罗模拟计算概率
最后,下图的相关性为 0.5,显示了我们感兴趣的区域。为了计算概率,我们需要计算我们感兴趣区域的 PDF 下的体积。
使用 Python 中的 numpy 计算新员工的成功概率实际上非常简单。我们将使用函数numpy . random . multivariate _ normal()。由于该函数接受协方差作为参数,我们必须将相关性转换为协方差矩阵。如果我们假设智商和成功的方差都是 1(任何其他关于方差的假设都会给出相同的结果)。协方差矩阵与相关矩阵相同。我们用函数画出 10000 个‘成功’和‘智商’的值。假设两个变量*均值为零,相关性为 0.5。
下面的代码应该给出大约 0.67 的结果。我们的新员工表现优于*均水*的可能性比我们从随机选择过程中对“智商”的预期高出约 17%。
# Mean for both success and IQ is zero
mean = (0, 0) # covarinance matrix with assumption of sd =1 (any other sd gives the same result)cov = [[1, .5], [.5, 1]]# we draw from both IQ and Success from a Multivariate
x = np.random.multivariate_normal(mean, cov, 10000) count_both = 0
count_pos_iq = 0
for i in range(len(x)):
if (x[i, 0] > 0):
count_pos_iq += 1
if (x[i, 1] > 0):
count_both += 1# ratio of values where Succuess > 0, IQ >0 to those where IQ > 0
print(count_both/count_pos_iq)
密码
该代码可在本回购中获得。
可能利用伊拉克的美元拍卖
原文:https://towardsdatascience.com/iranian-exploitation-of-iraqs-dollar-auction-3391af5032e0?source=collection_archive---------22-----------------------
将隔离森林应用于伊拉克中央银行的数据。
背景
2019 年 9 月 4 日,美国国务院宣布了一项正义奖励计划,为导致伊朗革命卫队圣城部队金融网络中断的信息提供高达 1500 万美元的奖励。对此,我最喜欢的中东粉丝之一尼布拉斯·卡希米在推特上写道:
作为背景,萨达姆政权倒台后,美元对伊拉克经济变得至关重要。为了获得这些美元,伊拉克在美联储银行有一个账户,该账户可以动用伊拉克的石油储备。一叠叠 100 美元钞票被空运到巴格达,存放在伊拉克中央银行。然后,伊拉克中央银行在每日拍卖中将这些美元卖给伊拉克和地区银行以及较大的汇款公司,以换取伊拉克第纳尔。
因此,多年来的拍卖已经成熟,从伊朗到伊斯兰国的每个人都可以利用,CBI 实际上已经将几家伊朗银行和较小的货币服务企业列入“黑名单”或禁止参与。
假设
据推测,根据 JCPOA 核协议,伊朗不再需要这次拍卖提供的美元,因此伊朗的开采减少了。然而,美国宣布将于 2018 年 5 月 8 日退出 JCPOA,JCPOA 之前的制裁制度将“迅速恢复”原状。第一轮骤回制裁于 2018 年 8 月 6 日生效,全面重新实施发生在 11 月 4 日。Nibras 在上述推文中所说的是,随着美国对伊朗重新实施制裁,该政权已经回到伊拉克拍卖作为美元的来源。
因此,我想看看我是否能证明 Nibras 的说法,首先从伊拉克中央银行的网站上收集每日拍卖数据,然后对数据应用隔离森林异常检测算法,以揭示异常的拍卖会话。
数据收集
每次拍卖后,英国工业联合会的网站都会提供一些信息。第一个数字(190,058,455)是用于覆盖国外账户的卖出总额。第二个数字(35,900,000)是现金销售总额,第三个数字(225,958,455)是销售总额,即前两个数字的总和。所以我想收集的就是这三个数字。
令人欣慰的是,CBI 的网站将这些结果发布在连续的 URL 上,这意味着我只需要找到 URL 的范围并遍历它。为了刮,我使用了 BeautifulSoup,并将数据存储在 CSV 文件中。页面的 HTML 格式变化相当频繁,尽管在 web 浏览器中查看页面时不会特别明显。这需要修改脚本来考虑页面布局的每一个变化。
为了限制不同剧本的数量,也因为我最关注 2018 年美国对伊朗重新实施制裁后的事件,我从 2017 年 9 月 18 日举行的拍卖开始(https://CBI . IQ/currency _ auction/view/124)。该页面的 HTML 布局一直持续到 2018 年 9 月 18 日的拍卖。2018 年 9 月 18 日拍卖结果的页面格式(大部分)一直延续到最*的拍卖(撰写本文时为 2020 年 2 月 9 日)。
在抓取之后,我在可视化之前进行了一些基本的数据清理和类型转换。
肉眼观察
我用散景来绘制一段时间内的数量。给定刮出的“总计”字段中缺失的数据量,我通过对前两个量求和来虚构一个。7 天滚动*均值提供了更*滑的结果图。
隔离森林
虽然看起来拍卖金额普遍增加了,但我希望隔离森林能够识别特定的异常拍卖时段。
隔离林的工作方式是通过随机选择一个要素来隔离数据点,然后在所选要素的最大值和最小值之间划分分割值。因为这种递归划分可以用树结构来表示,所以分离给定样本所需的分裂次数等于从根节点到终端节点的路径长度。这种路径长度,在这种树的森林中*均,构成了常态的度量。
最反常的观察将具有来自这种随机划分的最短路径,因为它们将首先“分裂”。因此,当一片树林为特定的观察产生较短的路径长度时,这些观察很可能是异常的。对于一个优秀的,可视化的概述,我推荐这个视频。
假设我在这个实例中没有标记数据,我以无人监管的方式使用隔离森林来为每个数据点生成异常分数。异常分数的最终分布:
因为我只在两个特征上训练模型,所以关于哪些点获得最低异常分数(即,最异常的那些点)是相当简单的。
检查大多数异常点
该模型评分为最异常的许多时段是因为现金销售总额或国外销售总额或两者都很低。此外,这些“轻松”的会议似乎都是由于他们发生在伊拉克的假期。
最反常的一届,得分为-0.232,发生在 2020 年 1 月 6 日;1 月 6 日是建军节,是伊拉克的公共假日。同样,2019 年 7 月 14 日的会议是第二大异常会议;7 月 14 日是共和国日,纪念 1958 年推翻君主制。
另一方面,大额现金销售交易和海外交易的大额总额也被评为高度异常。2018 年 4 月 16 日,数据集中最大的总现金拍卖是第八大异常观察。看来高额现金主要来自拉希德银行和国家伊斯兰银行的大额采购。拉希德银行是一家伊拉克国有银行,但没有显著的新闻事件可能推动这一大笔收购。
另一个异常大额现金时段是 2018 年 5 月 15 日。看来伊拉克中东投资银行是那天最大的买家。 ⁵:我迅速浏览了那一天与银行相关的新闻,但一无所获。
同样有趣的是,外国拍卖总额最大的那一个交易日只是第 18 个最反常的一天。正如散点图所示,大额现金交易似乎比大额外国账户交易更不正常。
结论
虽然拍卖总额似乎有所上升,但我们应该谨慎,不要得出太多结论。
首先,这是整个拍卖的总额,这意味着即使流向伊朗的美元大幅增加,也可能被其他参与者购买量的减少所抵消。
这里的样本量并不大(只有 611 个观察值),而且只有重新实施制裁前一年的数据。所有这一切让我不敢假设自己有一个好的基线,可以据此判断拍卖金额的任何变化。
Isolation Forest 合理地将特别小和特别大的拍卖会议确定为最不正常的。很多金额最低的时段可以用国定假日来解释;最大规模拍卖的背后是什么还远不清楚。不管怎样,这并没有帮助揭露任何表面上潜在的伊朗对拍卖的利用。
未来方向
- 收集更多的历史数据,以更好地定义零假设。
- 使用 CBI 更详细的报告来监控每个参与者的拍卖金额并进行分析。掌握每个拍卖参与者的信息将使我能够更好地评估拍卖金额变化的原因。
- 使用时间序列预测来检测异常。这将考虑到拍卖的顺序,并给出金额的背景。
本项目静态网站住 这里;此处的 为项目生命 的回购。
[1]https://cbi.iq/currency_auction/view/124有 2017 年 9 月 18 日的拍卖结果,https://cbi.iq/currency_auction/view/125有 2017 年 9 月 19 日的拍卖结果。
全球气温上升 2 度是一件大事吗?
原文:https://towardsdatascience.com/is-a-2-degree-increase-in-global-temperatures-such-a-big-deal-72f18c528d29?source=collection_archive---------17-----------------------
分布均值的微小变化会极大地增加尾部事件的概率。
Photo by Marcelo Novais on Unsplash
现在是七月中旬,我正坐在里面写中型文章,而不是骑自行车或在后院烧烤晚餐,因为外面气温高达 99 度!
当然,我不知道这是否是气候变化造成的。我都不知道这是不是个有意义的问题。但是,它让我思考…和写作。
最*,我有幸参加了总统科技顾问委员会(以前存在的机构)前联合主席约翰·霍尔德伦的演讲。除了他展示的所有伟大的科学之外,他还分享了一个让我拍脑门的统计洞见,因为这其实有点显而易见,但我没想过。所以,冒着阐述这种显而易见的事实的风险,我想我应该分享一下。
老实说,我从来没有完全理解为什么*均气温上升 2 度是一件大事。我相信这是一件大事,因为我相信有些事情科学家知道而我不知道。但是,从本质上来说,如果今年每天都比往年热 2 度,这并不是什么值得庆祝的事情,但也不会让人无法忍受。坦白地说,我怀疑大多数人都是这样想的。
在霍尔德伦的演讲中,当他做了一个简单的陈述时,他的额头被拍了一下:
换句话说,*均每天可能只热 2 度,但我们将会看到更多非常热的日子。
为了证明这是真的以及为什么,我从国家海洋和大气管理局(NOAA) 的网站上下载了 1970 年到 2010 年 8 月份纽约市每天的高温读数。这是一个直方图:
覆盖的橙色线是最接*数据的正态分布:*均值 82.2 度,标准偏差 5.6 度。实际分布看起来不太正常。例如,左尾巴比右尾巴长很多。但是,它足够接*,我们可以安全地使用正态分布来理解霍尔德伦的观点。
气候变化科学的一个重要论断是,天气模式变得越来越不稳定。但是,为了隔离均值漂移的影响,让我们采取更保守的假设,即当*均温度升高时,标准差保持不变。
与原始分布(上图中的分布)相比,新分布的*均值为 84.2,而不是 82.2:
看起来是个小变化。例如,82 度天气的概率*从大约 7.2%下降到大约 7.0%。农民或气候科学家会注意到这一点,但我不会。
然而,在温度非常高的日子里,这种影响更加明显。让我们把和今天一样热或比今天更热的一天,即 99 度或更热的一天,称为“大热天”。炙热天气的概率很低。但是,在相对基础上,这种可能性急剧增加,从 0.13%增加到 0.40%,这意味着*均气温上升 2 度,酷热的可能性增加两倍以上!
*均温度再升高几度,这种影响就会变得更强:
相反的情况发生在分布的左侧。随着*均温度的上升,凉爽天气(比如 75 度及以下)的可能性急剧下降:
要了解为什么会发生这种情况,让我们重新看看这两个发行版:
放大橙色框突出显示的区域,即右侧尾部:
观察到 99 度或更高的高温(炙热)的总概率是分布下阴影区域的面积。对于由蓝色实线表示的原始分布,该区域(深蓝色阴影)为 0.13%。高 2 度均值分布包括最初的 0.13%,加上额外的 0.27%。还是那句话,绝对数字小,但相对涨幅超过 200%。
你可能已经注意到,随着*均值的上升,炙热天气的概率呈指数增长。在+2 度,酷热的可能性增加了两倍。上升了+5 度,大约高了 15 倍。并且,在+10 度时,它高出 80 多倍。
为了理解这种影响,下面的阴影图比较了基线和+5 度分布的右侧尾部:
比较基线和+10 度分布:
注意事项:
- *为了让这篇文章易于理解,我偶尔会对概率和概率密度之间的区别有所马虎。因为我通常以完整的度数说话,特定的温度实际上是范围的代理,所以这是一个相当小的错误。
- 这是一篇关于统计的文章,不是关于气候变化的。我的方法有很多可以批评的地方。请不要因为经验或政治上的顾虑而错过了不可否认的数学观点。
- 尾部事件和均值之间的关系取决于分布。举例来说,如果高温的分布是均匀的(显然不是),那么这种效应就会消失。
- 您可以在这里找到用于创建图表的数据和代码。
数据分析师是数据科学家吗?
原文:https://towardsdatascience.com/is-a-data-analyst-a-data-scientist-890e24087737?source=collection_archive---------13-----------------------
有什么区别?
世界上有许多职业,每一个都是这个世界这个错综复杂的机器中的一个齿轮——按照他们的步伐前进,发挥他们的潜力,让这个世界变得更美好。然而,运行这台机器并为整个系统提供动力所需的燃料是“技术”
技术一直处于人类所知的几乎每一个职业的最前沿。自世界诞生以来,人类已经从手中拥有长矛和剑发展到拥有数字笔和移动设备。这种技术的发展帮助人类以指数速度进步。
今天,世界继续探索新的方法来减轻人类背上的负担,提供创新的机会来了解这个世界、它的地*线和其他地方。因此,新的职业不断涌现,管理和运作社会的现有发展。
在这个时代的一些新兴职业中,已经观察到对能够利用每天产生的大量数据的人的需求。这些人被期望一点一点地收集、分析和解释数据集,以揭示其中有意义的模式。
【大数据】是指每天淹没业务的大量结构化或非结构化数据,因此无法通过传统的数据处理技术进行处理。
解释这些大量的数据并不是一件轻而易举的事情,因此需要一个严肃的专业人士来处理和解释这些数据。然后,他/她可以通过从中发现有意义的趋势和阐释,为企业提供可行的解决方案来实施。
处理大数据的两个主要专业定义相当模糊,有时可以互换使用,显然破坏了它们之间的明确区别。这两种职业是“数据分析师”和“数据科学家”这两种职业都要求拥有不同的技能。以下是这两种职业在他们做什么以及哪里需要他们方面的一些区别。
他们是谁,做什么的?
在沟通、统计、商业和数学领域,职业需要的技能和知识量有很大的不同。
数据分析师
数据分析师仔细阅读大量数据,并从中得出真知灼见。他们负责收集数据,组织数据,并从中获得统计解释。这些解释通过可视化和报告给出,因此企业可以从中做出战略决策。
数据科学家
与数据分析师不同,数据科学家可以做出预测,帮助企业做出准确的决策。他们几乎可以做数据分析师能做的所有工作,因为他们也精通数学、统计学和计算机应用技能。他们能够有效地挑选和解决正确的问题,帮助企业脱颖而出。
The Data Scientist Venn Diagram shows the difference between different professions in the Big Data world (Stack Exchange)
他们需要什么技能?
数据科学家和数据分析师在专业知识方面有许多相似之处;然而,有一些主要的特征使数据科学家优于数据分析师。
数据分析师
他们需要对算法、数学、统计学有一个基本的了解,如果他们有很好的沟通技巧和相当多的计算机科学知识,这是最好的。数据分析师是 SQL 方面的大师,使用通用表达式可以轻松地剖析数据并从中找出意义。此外,他们需要通过理解数据集中发现的模式和趋势来帮助组织做出决策。
除了数据存储和检索技能,他们还应该了解基于 Hadoop 的分析,如 HBase、Hive、Impala、Cascading 和一个非常著名的工具 Google Analytics 。此外,他们需要熟悉各种 ETL 工具,用于将不同来源的数据转换为分析数据存储。
数据科学家
数据科学家拥有数据分析师的所有技能,对建模、统计、数学和计算机科学有深刻的了解。拥有数学、统计和数据挖掘方面的超级技能,数据科学家是预测建模和机器学习方面的专家。因此,他们可以创建复杂的预测模型,根据历史数据给出有效的建议。
然而,与众不同的因素是强大的商业敏锐性,这使他们有别于分析师。数据科学家必须能够以故事的形式将研究结果传达给 It 专业人员和业务经理,以便他们能够根据数据科学家提供的信息承担预计的风险并做出可行的决策。
哪里需要他们?
如今,医疗保健、旅游和 IT 行业对数据分析师的需求很大。他们还积极参与各种业务的数据处理和分析工作。
A demand trend for Data Analysts (Courtesy: Google)
另一方面,数据科学家通常在电子商务、搜索引擎优化(SEO)和公司金融服务中需要。
此外,企业需要它们根据现有数据预测行业的未来趋势,并根据这些未来趋势做出合理的决策。
The demand for Data Scientists soared after 2012 as shown by the graph (Courtesy: Google)
他们挣多少钱?
对于每一个职业来说,工资是一个人追求职业兴趣的主要关注点。毫无疑问,提供给数据分析师和数据科学家的薪水在数据行业是有竞争力的;然而,由于数据科学家在各自领域的专业水*,他们比数据分析师挣得多。
根据 indeed.com 的数据,美国数据分析师的*均年薪为 65,245 美元,数据科学家的*均年薪为 120,655 美元。
这种差异是由于两种职业所需的知识基础、专业知识和经验。
最后的想法
不管有何异同,这两个职业都在各自的位置上发挥着举足轻重的作用,任何一个都不会错。
普华永道 2018 年的一项研究预测,
“到 2020 年,数据分析师和数据科学职位将有 270 万个职位空缺”。
该研究进一步阐述了理想的候选人必须是 T 型 ,这意味着除了具备分析和技术技能,他/她还必须具备“软技能”,如出色的沟通、团队合作和创造力。因此,明智的做法是,潜在的候选人应该发展强大的分析、技术和软技能,向那些拼命为公司寻找数据处理人员的企业证明自己的价值。