TowardsDataScience 博客中文翻译 2019(二百九十九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

强化学习简介—第 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 的四个主要子元素

  1. 策略— 是从感知的环境状态到处于这些状态时要采取的行动的映射。策略是强化学习代理的核心,因为它本身就足以决定行为。它可能是随机的,规定了每个动作的概率。
  2. 奖励— 在每个时间步上,环境向强化学习代理发送一个称为奖励的单一数字。代理人的唯一目标是最大化其长期获得的总回报。因此,回报信号定义了对代理人来说什么是好信号,什么是坏信号。它可能是状态和行为的随机函数。
  3. 价值函数— 粗略地说,一个状态的价值就是一个主体从那个状态开始,在未来可以期望积累的报酬总额。奖励决定了环境状态的直接的、内在的可取性,而值在考虑了可能发生的状态和这些状态中可用的奖励之后,指示了状态的长期可取性。例如,一个州可能总是产生较低的即时奖励,但仍然有很高的价值,因为它经常被产生高奖励的其他州跟随,或者相反。
  4. 环境模型— 这模仿了环境的行为,允许对环境将如何表现做出推断。例如,给定一个状态和一个动作,模型可以预测下一个状态和下一个奖励。使用模型解决强化学习问题的方法称为基于模型的方法,与更简单的无模型方法,即试错学习器相对。

从某种意义上说,回报是第一位的,而作为回报预测的价值是第二位的。没有回报就没有价值,评估价值的唯一目的是为了获得更多的回报。然而,在做决策和评估决策时,我们最关心的是价值观。

一个例子:井字游戏

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 2. Sequence of Tic-Tac-Toe Moves

解决井字游戏的强化学习方法;

  1. 建立一个数字表,每个数字代表一种可能的游戏状态。
  2. 每一个数字都是我们对该州获胜概率的最新估计。
  3. 这个估计值就是状态的 ,整个表就是学习值函数。
  4. 假设我们总是玩 x,那么对于一行(列和对角线)中有 3 个 x 的所有状态,获胜的概率是 1.0
  5. 对于一行(列和对角线)中有 3 个 0 的所有州,获胜的概率是 0.0
  6. 我们将所有其他状态的初始值设置为 0.5 (表示我们有 50%的胜算。)

然后我们和对手打很多场比赛。要选择我们的行动:

  1. 我们检查每个可能的移动所产生的状态,并在表中查找它们的当前值。
  2. 大多数时候,我们贪婪地行动,选择能带来最大价值的行动。(最高中奖概率)
  3. 偶尔,我们会从其他动作中随机选择。(探索)

玩的时候,我们会改变自己所处状态的价值观:

  1. 在每次贪婪的移动之后,从 A 到 B,我们更新 A 的值以更接近 B 的值。
  2. 这是通过以下公式实现的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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]的转变完全独立于过去。因此,如果系统具有马尔可夫性质,方程的 RHSLHS 的含义相同。直观上意味着我们的当前状态已经捕获了过去状态的信息。

状态转移概率:

现在我们知道了转移概率,我们可以将状态转移概率定义如下:

对于从 S[t]到 S[t+1]的马尔可夫状态,即任何其他后续状态,状态转移概率由下式给出

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

State Transition Probability

我们可以通过以下方式将状态转移概率公式化为状态转移概率矩阵:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

State Transition Probability Matrix

矩阵中的每一行代表从我们的原始或开始状态移动到任何后续状态的概率。每行的总和等于 1。

马尔可夫过程或马尔可夫链

马尔可夫过程是记忆较少的 随机过程 即一个随机状态的序列 S[1],S[2],…。S[n]具有马尔可夫性质。所以,它基本上是一个具有马尔可夫性质的状态序列。它可以用一组状态(S)和转移概率矩阵§来定义。使用状态(S)和转移概率矩阵§可以完全定义环境的动态。

但是 随机过程 是什么意思呢?

为了回答这个问题,我们来看一个例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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)和转移概率矩阵§来定义环境的动态性的。但是,我们知道强化学习的目的是最大化回报。所以,让我们把 加奖励 到我们的马尔可夫链中。这给了我们马尔科夫的奖励过程。

马尔可夫奖励过程:顾名思义,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 一样,但现在我们有了真正的机构来做决定或采取行动。

它是一个( SAPR𝛾 )的元组,其中:

  • s 是一组状态,
  • a 是代理可以选择采取的一组操作,
  • p 是转移概率矩阵,
  • r 是代理人的行动所累积的报酬,
  • 𝛾 是贴现因子。

p 和 R 将有轻微的变化,如下所示:

转移概率矩阵

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Transition Probability Matrix w.r.t action

奖励功能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Reward Function w.r.t action

现在,我们的奖励函数依赖于行动。

到目前为止,我们已经讨论了当我们的代理遵循一个策略π通过一组状态时获得奖励®。实际上,在马尔可夫决策过程(MDP)中,策略是做出决策的机制。所以现在我们有了一个选择采取行动的机制。

MDP 的政策取决于当前的状态。他们不依赖于历史。这就是马尔可夫性质。因此,我们目前所处的状态是历史的特征。

我们已经看到代理处于特定状态(状态-值函数)有多好。现在,让我们看看遵循状态 s 的政策π(行动-价值函数)采取特定行动有多好。

状态-动作值函数或 Q 函数

该函数指定代理在具有策略π** 的状态下采取行动(a)的效果有多好。**

数学上,我们可以将状态-动作值函数定义为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

State-action value function

基本上,它告诉我们在具有策略π的状态下执行某个动作(a)的值。

让我们看一个马尔可夫决策过程的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of MDP

现在,我们可以看到没有更多的概率。事实上,现在我们的代理可以做出选择,比如醒来后,我们可以选择看《网飞》或者编码和调试。当然,代理人的行为是根据某个策略π来定义的,并且会得到相应的报酬。

太棒了。

恭喜你坚持到最后!👍

到目前为止,我们已经讨论了 MDP 的构建模块,在接下来的故事中,我们将讨论和贝尔曼期望方程更多关于最优策略和最优价值函数,高效的价值发现方法,即动态规划(价值迭代和策略迭代算法)并用 Python 编程。

希望这个故事能增加你对 MDP 的了解。很乐意在 Instagram 上与您联系。

谢谢你与我分享你的时间!

关于马尔可夫决策过程的第 1 部分、第 2 部分和第 3 部分:

参考资料:

待深

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 中剩余网络的另一个伟大实现

层之间的跳过连接将先前层的输出添加到堆叠层的输出。这使得能够训练比以前更深的网络。ResNet 架构的作者在 CIFAR-10 数据集上用 100 和 1,000 个层测试了他们的网络。他们在具有 152 层的 ImageNet 数据集上进行测试,该数据集仍然比 VGG 网络[4]具有更少的参数,后者是另一种非常流行的深度 CNN 架构。深度残差网络的集合在 ImageNet 上实现了 3.57%的错误率,在 ILSVRC 2015 分类竞赛中获得了第一名。

一种类似的方法被称为“高速公路网”。这些网络也实现跳跃连接,然而,类似于 LSTM,这些跳跃连接通过参数门。这些门决定了有多少信息通过跳过连接。作者指出,当门接近关闭时,层表示非剩余函数,而 ResNet 的标识函数从不关闭。根据经验,作者注意到,高速公路网络的作者没有显示出他们用 ResNets 显示的网络深度的准确性收益。

他们用来测试跳过连接的架构遵循了 2 个启发自 VGG 网络的启发[4]。

  1. 如果输出特征图具有相同的分辨率,例如 32×32→32×32,那么滤波器图深度保持不变
  2. 如果输出特征图大小减半,例如 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)和注意力。我会尽量使它简单。你只需要知道:

  1. 线性代数
  2. 神经网络

如果你对这些主题感到生疏,在开始阅读之前,请点击上面的链接,随意查看。

我记得当我第一次学习前馈神经网络时,我对自己说,有可能以更好的方式建立这个神经元网络吗?因为在人脑中,神经元的连接方式比前馈神经网络更复杂。事实证明,研究人员不断找到新的方法来排列神经元,让它们做一些有用的事情。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 中,我们用valvar声明变量,我们将讨论两者之间的区别。值得注意的是,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中的myArrfor每个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 上关注他,了解关于深度学习和机器学习的最新文章。

参考文献:

免责声明 —这篇文章中可能有一些相关资源的附属链接。你可以以尽可能低的价格购买捆绑包。如果你购买这门课程,我会收到一小笔佣金。

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 核心表示技术的长期统治已经出现了一系列令人兴奋的新挑战者,如 ELMoBERTRoBERTaALBERTXLNetErnieULMFiTOpenAI 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斯坦福 CoreNLPNLTKOpenNLP ,不如最新科学论文可能实现的精确。

声称提供最先进的准确性和速度使我们不断追求最新的科学进步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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 算法时,我们是认真的。例如, NERDLModelNerDLApproach 标注器在 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

为了估计β系数,我们可以使用最大似然。基本思想是估计β,使得结果的估计值和观察值尽可能接近。在二元分类中,观察到的类为 10 ,我们可以说似然函数看起来像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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 HubsAWS 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,是一名狂热的软件工程师、开源贡献者、博客作者,也是 PluralsightUdacity 和 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 的实验跟踪工具可视化指标。

入门

  1. 打开这个 Colab 笔记本
  2. 单击“在操场上打开”为自己创建此笔记本的副本。
  3. 在 Google Drive 中为自己保存一份副本。
  4. 浏览下面的每个部分,按代码块上的 play 运行单元。

结果将被记录到 a 共享 W & B 项目页面

训练模型

让我们回顾一下我在上面的 Colab 笔记本中使用的关键 wandb 命令。

设置

  • pip 安装 wandb —安装 W & B 库
  • 导入 wandb —导入 wandb 库
  • wandb 登录 —登录您的 W & B 账户,这样您就可以在一个地方记录您的所有指标
  • wandb.init() —初始化一个新的 W & B 运行。每次运行都是训练脚本的一次执行。

初始化超参数

  • wandb.config —将所有的超参数保存在一个配置对象中。您可以使用我们的应用程序,通过超参数值对您的跑步进行排序和比较。

追踪结果

  • wandb.log() —记录您的指标,以便您可以可视化您的神经网络随时间推移的性能。

可视化结果

一旦你训练了你的模型,你可以可视化你的模型所做的预测,它的训练和损失,梯度,最佳超参数,并审查相关的代码。

要查看此打开项目中的人员创建的跑步记录:

  1. 查看项目页面
  2. 展开 runs 表,比较每个尝试过该脚本的人的所有结果。
  3. 单击一次跑步的名称,在其跑步页面上深入了解该次跑步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可视化渐变

单击单次运行,查看有关该运行的更多详细信息。例如,在这个运行页面上,您可以看到我运行这个脚本时记录的梯度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

审查代码

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. 装置
  2. 例子
  3. 结论

事不宜迟,我们开始吧!

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 来可视化它,并呈现两个视频来显示训练有素的代理和未训练的代理之间的差异。

非常感谢,祝你有美好的一天!

参考

  1. https://github.com/tensorflow/agents
  2. 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. 方法 1 —仅分析内容描述
  2. 方法 2——从用户评价的内容建立用户简档和项目简档
  3. 两种方法的利弊

本文将重点解释这两种方法的主要区别,可能不会详细讨论编码。请访问这里的获取各自的 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 profileitem 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 或评论区联系我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值