强化学习:自然主义者、享乐主义者和自律主义者
塑造强化学习的思想史
Embracing the chaos of a biological brain and the order of an electronic one. — Image credit: http://www.gregadunn.com/microetchings/cortical-circuitboard/
对人工智能的追求总是与另一场斗争交织在一起,这场斗争更富有哲理,更浪漫,却不那么有形。对人类智能的理解。
尽管目前监督学习的突破似乎是基于优化的硬件、复杂的训练算法和过于复杂的神经网络架构,但强化学习仍然是一所老派学校。
这个想法很简单:你是一个环境中的学习者。如果我们做一般假设,你有满足自己的目标(我们不都是吗?),然后你执行动作。基于这些行为,环境会以奖励来回应,而你,基于这些奖励,会调整你的行为来最大化你的满意度。
Does RL have limits? “The day will never come when a computer defeats a pro shogi player”, a proclamation by the deceased shogi player Satoshi Murayama, found its refutant in the face of AlphaGo Zero. — Image Credit: https://www.hokusai-katsushika.org/shogi-chess-board.html
没过多久,我们就在生物通过强化学习的能力和人工智能之间找到了联系。早在 1948 年,图灵描述了一个快乐-痛苦系统,该系统遵循几十年后建立的强化学习的当前规则。
智力是适应变化的能力——斯蒂芬·霍金斯
社区的第一次尝试针对的是双陆棋游戏,因为它简单,提供了少量的离散状态和简单的规则。如今,我们有人工智能代理使用强化学习来玩雅达利游戏、《我的世界》和翻煎饼。那么,我们是如何完成这一切的呢?
简单的答案是深度学习。
这篇文章将冒险给出一个更长的答案。它将探索我们已经使用了几十年的强化学习算法背后的思想来源。我们最近的成功不仅仅是深度神经网络的产物,而是观察、结论和试图理解学习机制的深刻历史。
强化学习是一个起源很难追溯的领域。它的大部分理论基础要归功于控制理论家。马尔可夫决策过程是最优控制问题的离散随机版本,因此几乎所有的强化学习算法都基于控制理论中导出的解决方案,这并不奇怪。
然而,控制理论提供的背景并不足以创造强化学习。我们今天仍在使用的算法需要一些想法,如经典条件反射和时差学习,来形式化学习过程。
如果没有少数好奇的生物学家、心理学家和不墨守成规的计算机科学家,人工智能社区可能不会拥有实现学习的工具。
我们如何在不可预见的情况发生前采取行动?如何采纳我们的行为?环境如何影响我们的行为?我们如何改进?一项技能是如何习得的?
这是一个试错的世界
1898 年,桑代克要么对他的猫非常生气,要么对动物的行为非常好奇。他把它放在一个配有门闩的笼子里,并在外面放了一盘诱人的鱼。那只猫只有拉一下杠杆才能逃出笼子。
猫会有什么反应?
没有推理,没有推论或比较的过程;没有对事物的思考,没有把两两放在一起;没有想法——动物不会想到盒子、食物或它要做的动作。
桑代克观察到,这只猫的行为似乎并不聪明:它开始在盒子里随意移动和行动。只有当它偶然拉动杠杆并释放自己时,它才开始提高逃跑的技巧。
基于这一观察,桑代克提出了一个效应定律,该定律指出,任何伴随着令人愉快的后果的行为都有可能被重复,任何伴随着令人不快的后果的行为都有可能被停止。
这个定律催生了操作性条件作用领域,由斯金纳在 1938 年正式定义。对于强化学习社区来说,它提供了制定代理的理由,这些代理基于奖励和它们与环境的交互来学习策略。
它也为我们提供了一个关于动物学习的新观点,因为效果定律可疑地类似于另一个当时众所周知的定律:自然选择。我们的知性可能只是一种适者生存的想法吗?
然而,有两个特征使得强化学习成为一个独特的过程:
- 这是选择性的。这使它不同于监督学习,因为一个代理通过比较它们的结果来尝试和选择它们。
- 它是联想的。这意味着,通过选择找到的替代方案与特定的情况或状态相关联,从而形成代理人的策略。自然选择是选择过程的一个主要例子,但它不是联合的。
我们就是我们反复做的事情。因此,优秀不是一种行为,而是一种习惯。”
― 亚里士多德
享乐主义者的学习指南
谈到分析人类思维,Klopf 相当简洁:
“人的根本本性是什么?
人是享乐主义者。"
在他备受争议的著作《享乐主义神经元——记忆、学习和智力理论》中, Klopf 运用神经科学、生物学、心理学以及他推理中令人信服的简单性和好奇心来说服我们,我们的神经元是享乐主义者。是的,你的神经元和你一样追求快感。
当面对他那个时代占主导地位的神经元模型,罗森布拉特的感知机(这是今天神经网络的构建模块)时,克洛普夫想知道:
“如果神经元被假设为非目标寻求组件,那么目标寻求大脑功能必须被视为一种涌现现象。这种观点能解释记忆、学习以及更普遍的智力吗?
他提出了一个新的构建模块,称为基本异质状态,作为未来人工智能研究的基础。Klopf 还认为,体内平衡,即追求良好、稳定的状态,并不是复杂系统(如人类和动物)的目的。解释植物的目的可能已经足够好了,但我们可以假设,人类在确保体内平衡后,会追求快乐的最大化,而不是稳定快乐。为什么我们的神经元会不同?
这些想法听起来可能难以置信,但它们可能会撼动人工智能的世界。Klopf 认识到,随着学习研究者几乎完全专注于监督学习,适应性行为的基本方面正在消失。根据 Klopf 的说法,所缺少的是行为的享乐方面,即从环境中获得某种结果的驱动力,控制环境朝着期望的目标发展,远离不期望的目标。
在批评当前控制论原理(机器学习在当时被称为控制论)的广泛章节中,人们可以强调三条攻击路线:
我们应该使用深度神经网络吗?
明确一点,两层足以让 50 年代的网络被称为深度网络。Klopf 似乎对感知器模型感到满意,但他质疑将其置于深度网络中的学习能力。Klopf 提出了一个问题,即使在今天,任何机器学习科学家都无法回避这个问题:
“[…]然而,该算法仅适用于单层自适应网络。许多后来的研究未能为多层网络的更一般情况产生真正可行的确定性自适应机制。一般情况下的中心问题是,当系统行为不适当时,确定任何给定的网络元件应该做什么。这被证明是非常困难的,因为在一个深层网络中,单个元素的大部分输出与系统的最终输出有着高度间接的关系。”
AI 的目的是什么?
Klopf 也质疑人工智能研究的追求。在他试图接近学习的正确目标时,他使用了一个论点,我在 lafter 强化学习研究者中也发现了这个论点:
“生命已经在这个星球上进化了大约 30 亿年。在那段时间里,90%的时间花在进化我们和爬行动物共有的神经基质上。从爬行动物时代开始,到人类的出现,只有相对短暂的 3 亿年。一个关于通向智慧的过程的问题出现了。如果进化过程花了 90%的时间开发神经基质,剩下的 10%制定有效的高级机制,为什么人工智能研究人员试图反过来做呢?”
智力是聪明的吗?
在下面的摘录中,感觉桑代克和克洛普夫是强化学习的伙伴:
还有另一种方式,人工智能研究人员对智力的感知似乎与生命系统现象的本质不一致。[……]在生命系统中,智能经常不是智能的,至少不是研究人员有时看待这一现象的那种智能意义上的智能。更确切地说,生命系统中的智能常常是简单有效的。如果智能生物在日常信息处理中具有“蛮力”的天性,那将会出现很多问题。[……]即使对最聪明的人来说,更聪明的活动形式也是困难的。[……]因此,人们不禁要问,智能与更高级信息处理的联系是否让人工智能研究者对这一现象的看法过于狭隘和狭隘。在短期内,一个更温和的观点会产生更多的理论吗?
巴甫洛夫的狗玩双陆棋
到目前为止,我们可能一直在谈论强化学习,但事实是,这个术语是由巴甫洛夫首先使用的,在巴甫洛夫关于条件反射的专著的 1927 年英译本中。
巴甫洛夫在他著名的实验中观察到的是,当给狗提供食物并且在接近喂食时间时发出声音时,狗学会了将喂食与这种声音联系起来,并且即使在没有食物的情况下,当听到这种声音时也会分泌唾液。
通过这一观察,巴甫洛夫为经典条件反射奠定了基础,这是第一个将时间纳入学习过程的理论。现在,RL 算法主要采用时间差学习,这意味着当计算一个动作的“质量”以做出决定时,我们还会考虑未来的回报。
1989 年,Chris Watkins 开发了 Q-learning,这是最著名的强化学习算法之一,这使得时间差和最优控制线程完全结合在一起。
1992 年,特索罗在玩双陆棋的代理人身上运用了时差学习的概念。这是说服研究界这种类型的机器学习有潜力的时刻和应用。
尽管目前的研究思路集中在深度学习和游戏上,但如果不是一群人在谈论猫、神经元和狗,我们今天就不会有强化学习领域。
可以说,我们从解决双陆棋中获得的回报,直到那一点难以想象的困难任务,激励我们进一步探索强化学习的潜力。这个强化学习的例子怎么样?
强化学习:怪癖
在过去的几个月里,我一直致力于强化学习,对此我只能说:它是不同的。我所经历的强化学习的常见怪癖和挫折的记录。
位置
作为实习的一部分,我一直在各种开放人工智能体育馆环境中应用 A3C 和 GA3C 算法的变体。在此之前,除了一些入门课程,我没有任何广泛的强化学习经验,所以这对我来说很新鲜。
我很快了解到,强化学习与我之前完成的默认分类和回归任务非常不同——但它非常令人兴奋!让我告诉你我在整个过程中遇到的问题。
时间
在深度强化学习中,训练数据通常是“在工作中”收集的,这意味着代理在没有他的环境的先验知识的情况下开始,然后在与模拟交互时开始收集经验。
这意味着需要一些时间来收集内存缓冲区中的数据,然后需要更多时间来将其传递到算法中并更新网络权重。这可以通过使用异步方法来优化——比如上面提到的 A3C 算法——这使得事情变得更加复杂。这意味着即使一些简单的代理也需要几个小时的培训,而更复杂的系统需要几天甚至几周的时间。
计算能力
在 NVIDIA AI 工作带来了一些明显的好处——纯粹的无限计算能力。
Two NVIDIA Geforce GTX GPUs
意识到大多数强化学习工作是在 CPU 上完成的就越糟糕。
使用 GA3C 算法,一些权力被转移到 GPU,允许更大和更复杂的网络,但在我的经验中,限制通常来自 CPU,这在深度学习领域的其他领域非常不寻常。
探索与开发
这个最疼。“探索与剥削”似乎是一个非常普遍的问题。基本上,在探索你的环境和采取最好的行动之间有一个权衡。让我们从迷宫的角度来看这个问题。
如果你探索得太多,你的机器人总是会尝试寻找新的方法来更好地解决迷宫。一开始听起来不错,但这也意味着,如果你的机器人找到了解决迷宫的完美方法——它不会相信这是最好的,下次会尝试另一条路线,可能永远不会再找到“最佳方法”。
如果你探索得太少/利用得太多,你的机器人可能会找到一种方法来解决这个迷宫,并会继续走同样的路。这可能意味着它在到达迷宫的核心之前会穿过每一条走廊——但这对它来说已经足够了,它会永远这样做。
根据我的经验,第二种情况发生得更多。我读了由亚瑟·朱利安尼写的这篇关于一些探索技巧的精彩文章,我可以把它推荐给任何尝试 RL 的人。
具有 Keras + OpenAI 的强化学习:演员-评论家模型
快速回顾
上次在我们的 Keras/OpenAI 教程中,我们讨论了强化学习中一个非常基础的算法:DQN。深度 Q 网络实际上是一个相当新的出现,仅在几年前才出现,所以如果你能够理解并实现这个刚刚在该领域起步的算法,那将是非常不可思议的。与最初的帖子一样,让我们花一点时间来欣赏一下我们取得了多么不可思议的结果:在连续输出空间场景中,从绝对没有关于“获胜”需要什么的知识开始,我们能够探索我们的环境并“完成”试验。
把自己放在这个模拟的情境中。这基本上就像要求你玩一个游戏,没有规则手册或具体的最终目标,并要求你继续玩,直到你赢了为止(这似乎有点残酷)。不仅如此:你可以通过一系列动作达到的可能结果状态是无限的(即连续的观察空间)!然而,DQN 惊人地快速收敛,通过维持和缓慢更新行动的内在价值来解决这个看似不可能的任务。
更加复杂的环境
从之前的登山车环境到钟摆的升级与从横拉杆到登山车的升级非常相似:我们正在从离散的环境扩展到连续的环境。钟摆环境有一个无限的输入空间,这意味着您在任何给定时间可以采取的行动数量是无限的。为什么 DQN 不再适用于这种环境?我们的实现不是完全独立于环境动作的结构吗?
Unlike the MountainCar-v0, Pendulum-v0 poses an even greater challenge by giving us an infinite input space to work with.
虽然与的动作无关,但 DQN 基本上是以有限的输出空间为前提的。毕竟,想想我们是如何构建代码的:预测试图在每个时间步(给定当前环境状态)为每个可能的操作分配一个分数,并简单地采取具有最高分数的操作。我们之前已经将强化学习的问题简化为有效地给动作分配分数。但是,如果我们有一个无限的输入空间,这怎么可能呢?我们需要一个无限大的表来记录所有的 Q 值!
Infinite spreadsheets sound pretty far from ideal!
那么,我们如何着手解决这个看似不可能的任务呢?毕竟,我们被要求做一些比以前更疯狂的事情:我们不仅得到了一个没有玩和赢的指令的游戏,而且这个游戏有一个上面有无限按钮的控制器!让我们看看为什么 DQN 被限制在有限数量的行动。
原因源于模型是如何构建的:我们必须能够在每个时间步迭代来更新我们在特定动作上的位置是如何变化的。这就是为什么我们让模型预测 Q 值,而不是直接预测采取什么行动。如果我们做了后者,我们将不知道如何更新模型来考虑预测以及我们对未来预测的回报。因此,基本问题源于这样一个事实,似乎我们的模型已经输出了与所有可能的行动相关的回报的列表计算。相反,如果我们打破这个模式会怎么样?如果我们有两个独立的模型:一个输出期望的动作(在连续空间中),另一个接受动作作为输入,从 dqn 产生 Q 值,会怎么样?这似乎解决了我们的问题,也正是演员-评论家模式的基础!
演员-评论家模式理论
Unlike DQNs, the Actor-critic model (as implied by its name) has two separate networks: one that’s used for doing predictions on what action to take given the current environment state and another to find the value of an action/state
正如我们在上一节中所讲的,整个演员-评论家(AC)方法的前提是有两个相互作用的模型。拥有多个相互作用的神经网络的主题在 RL 和监督学习中越来越相关,即 GANs、AC、A3C、DDQN(决斗 DQN)等。第一次熟悉这些体系结构可能有些令人生畏,但肯定是一次值得的练习:您将能够理解并编写一些处于该领域现代研究前沿的算法!
回到当前的主题,AC 模型有两个恰当命名的组件:演员和评论家。前者考虑当前的环境状态,并从中确定最佳的行动。本质上,这似乎是实现 DQN 的自然方式。批评家在 DQN 中扮演“评估”的角色,他接受环境状态和一个动作,并返回一个表示该动作对该状态有多合适的分数。
想象这是一个有一个孩子(“演员”)和她的父母(“评论家”)的游乐场。这个孩子四处张望,探索这个环境中所有可能的选择,比如滑上滑梯,荡秋千,拔地上的草。父母会看着孩子,根据她所做的,考虑到环境因素,进行批评或补充。父母的决定取决于环境这一事实既重要又直观:毕竟,如果孩子试图在秋千上荡来荡去,得到的赞扬远不如她试图在滑梯上荡来荡去!
简述:链式法则(可选)
你需要理解的理论要点是支撑现代机器学习的一大部分:链式法则。可以毫不夸张地说,链式法则可能是理解实用机器学习的最关键(尽管有些简单)的思想之一。事实上,如果你只是直觉地理解链式法则在概念上的约定,你可能没有什么数学背景。我将花很短的时间来描述链式法则,但是如果你对它感觉很舒服,请随意跳到下一部分,在那里我们实际上看到了开发 AC 模型的实用大纲是什么样子的,以及链式法则如何适应该计划。
A seemingly simple concept probably from your first calculus class, but one that forms the modern basis of practical machine learning, due to the incredible speedup it enabled in backprop and similar algorithms
形象地说,这个等式似乎非常直观:毕竟,只是“取消分子/分母。”然而,这种“直觉解释”有一个主要问题:这种解释中的推理完全是逆向的!重要的是要记住,数学不仅是为了理解概念,也是为了发展直觉符号。因此,人们开发了这个“分数”符号*,因为链式法则的行为非常类似于简化分数乘积。所以,试图仅仅通过符号来解释概念的人跳过了一个关键步骤:为什么这个符号是适用的?比如,为什么的*衍生品会有这样的表现?
The classic series of springs example is actually a pretty direct way you can visualize the chain rule in movement
潜在的概念实际上并不比这个符号更难理解。想象一下,我们有一系列的绳子,在一些固定的点绑在一起,类似于串联弹簧的连接方式。假设你拿着弹簧系统的一端,你的目标是以 10 英尺/秒的速度摇动另一端。你可以以这个速度摇动你的一端,并让它传播到另一端。或您可以连接一些中间系统,以较低的速率(即 5 英尺/秒)振动中间连接。在这种情况下,您只需以 2 英尺/秒的速度移动您的末端,因为无论您做什么移动,都将从您移动的位置持续到终点。这是因为物理连接迫使一端的运动进行到底。注意:当然,与任何类比一样,这里也有不一致的地方,但这主要是为了形象化。
同样,如果我们有两个系统,其中一个系统的输出馈入另一个系统的输入,摇动“馈入网络”的参数将会摇动其输出,输出将会传播并被任何进一步的变化放大,直到管道的末端。
AC 型号概述
因此,我们必须开发一个 ActorCritic 类,它与我们以前实现的 DQN 有一些重叠,但是在训练方面更复杂。因为我们需要一些更高级的特性,所以我们必须利用 Keras 所依赖的底层库:Tensorflow。注意:你当然也可以在 Theano 中实现它,但是我过去没有使用过它,所以没有包括它的代码。如果你愿意的话,可以随时向 Theano 提交这段代码的扩展!
模型实施将由四个主要部分组成,这与我们实施 DQN 代理的方式直接相关:
- 模型参数/设置
- 培训代码
- 预测代码
交流参数
首先,只是我们需要的进口品:
import gym
import numpy as np
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Input
from keras.layers.merge import Add, Multiply
from keras.optimizers import Adam
import keras.backend as Kimport tensorflow as tfimport random
from collections import deque
这些参数与 DQN 的参数非常相似。毕竟,除了在两个独立的模块中,这种演员兼评论家的模式必须做与 DQN 完全相同的任务。我们还继续使用我们在《DQN 邮报》中讨论过的“目标网络黑客”来确保网络成功收敛。唯一的新参数被称为“tau ”,并且涉及在这种情况下目标网络学习如何发生的微小变化:
class ActorCritic:
def __init__(self, env, sess):
self.env = env
self.sess = sess self.learning_rate = 0.001
self.epsilon = 1.0
self.epsilon_decay = .995
self.gamma = .95
self.tau = .125
self.memory = deque(maxlen=2000)
tau 参数的确切使用将在随后的训练部分中详细解释,但其本质上起着从预测模型逐渐转换到目标模型的作用。现在,我们到达感兴趣的要点:定义模型。如上所述,我们有两个独立的模型,每个模型都与自己的目标网络相关联。
我们从定义演员模型开始。参与者模型的目的是,给定环境的当前状态,确定要采取的最佳行动。再一次,这个任务有给我们的数字数据,这意味着除了我们到目前为止使用的简单的密集/全连接层之外,没有空间或需要在网络中涉及任何更复杂的层。因此,演员模型是一系列完全连接的层,从环境观察映射到环境空间中的一个点:
def create_actor_model(self):
state_input = Input(shape=self.env.observation_space.shape)
h1 = Dense(24, activation='relu')(state_input)
h2 = Dense(48, activation='relu')(h1)
h3 = Dense(24, activation='relu')(h2)
output = Dense(self.env.action_space.shape[0],
activation='relu')(h3)
model = Model(input=state_input, output=output)
adam = Adam(lr=0.001)
model.compile(loss="mse", optimizer=adam)
return state_input, model
主要的区别是我们返回一个对输入层的引用。这一点的原因在本节结束时会更加清楚,但简单地说,这是为了我们如何以不同的方式处理 actor 模型的训练。
演员模型的棘手之处在于决定如何训练它,这就是链式法则发挥作用的地方。但在我们讨论之前,让我们想想为什么它与标准的评论家/DQN 网络培训有所不同。毕竟,我们不就是要像 DQN 的情况一样,根据当前的状态来拟合模型,并根据当前和贴现的未来回报来拟合最佳行动吗?问题在于:如果我们能够做到我们所要求的,那么这将是一个解决的问题。问题在于我们如何决定采取什么样的“最佳行动”,因为现在在评论家网络中 Q 分数是分开计算的。
因此,为了克服这一点,我们选择了另一种方法。我们本质上是在爬山,而不是找到“最佳选择”并适应它。对于那些不熟悉这个概念的人来说,爬山是一个简单的概念:从你当地的视点出发,确定最陡的倾斜方向,然后朝那个方向递增。换句话说,爬山就是试图通过简单地做一些简单的事情,并遵循局部最大值的方向来达到全局最大值。有些情况下,你可以想象这是完全错误的,但通常情况下,它在实际情况下工作得很好。
因此,我们希望使用这种方法来更新我们的演员模型:我们希望确定(演员模型中)参数的什么变化会导致 Q 值的最大增加(由 critic 模型预测)。由于行动者模型的输出是动作,而批评家基于环境状态+动作对进行评估,因此我们可以看到链式规则将如何发挥作用。我们想看看改变 actor 的参数将如何改变最终的 Q,使用 actor 网络的输出作为我们的“中间链接”(下面的代码都在“ init(self) ”方法中):
self.actor_state_input, self.actor_model = \
self.create_actor_model()
_, self.target_actor_model = self.create_actor_model() self.actor_critic_grad = tf.placeholder(tf.float32,
[None, self.env.action_space.shape[0]])
actor_model_weights = self.actor_model.trainable_weights
self.actor_grads = tf.gradients(self.actor_model.output,
actor_model_weights, -self.actor_critic_grad)
grads = zip(self.actor_grads, actor_model_weights)
self.optimize = tf.train.AdamOptimizer(
self.learning_rate).apply_gradients(grads)
我们看到,这里我们保持模型权重和输出(动作)之间的梯度。我们还通过否定自我来缩放它。actor_critic_grad(因为我们想在这种情况下做梯度上升),它由一个占位符保存。对于不熟悉 Tensorflow 或第一次学习的人,占位符在运行 Tensorflow 会话时充当“输入数据”的角色。我不会详细说明它是如何工作的,但是 tensorflow.org 教程很好地介绍了这些材料。
转到评论家网络,我们基本上面临着相反的问题。也就是说,网络定义稍微复杂一些,但是它的训练相对简单。批评家网络旨在将和环境状态和行为作为输入,并计算相应的估价。我们通过一系列完全连接的层来实现这一点,中间有一层在组合成最终 Q 值预测之前将两者合并:
def create_critic_model(self):
state_input = Input(shape=self.env.observation_space.shape)
state_h1 = Dense(24, activation='relu')(state_input)
state_h2 = Dense(48)(state_h1)
action_input = Input(shape=self.env.action_space.shape)
action_h1 = Dense(48)(action_input)
merged = Add()([state_h2, action_h1])
merged_h1 = Dense(24, activation='relu')(merged)
output = Dense(1, activation='relu')(merged_h1)
model = Model(input=[state_input,action_input],
output=output)
adam = Adam(lr=0.001)
model.compile(loss="mse", optimizer=adam)
return state_input, action_input, model
值得注意的要点是我们处理输入和返回内容的不对称。对于第一点,与动作相比,我们在环境状态输入上有一个额外的 FC(全连接)层。我之所以这样做,是因为这是这些交流网络的推荐架构,但在两个输入端都加上 FC 层的情况下,它可能同样工作良好(或稍差)。至于后一点(我们返回的内容),我们需要保留对输入状态和动作的引用,因为我们需要在更新参与者网络时使用它们:
self.critic_state_input, self.critic_action_input, \
self.critic_model = self.create_critic_model()
_, _, self.target_critic_model = self.create_critic_model() self.critic_grads = tf.gradients(self.critic_model.output,
self.critic_action_input)
# Initialize for later gradient calculations
self.sess.run(tf.initialize_all_variables())
这里我们设置要计算的缺失梯度:关于动作权重的输出 Q。这在训练代码中被直接调用,正如我们现在将要研究的。
交流训练
这个代码与 DQN 不同的最后一个主要部分是实际的训练。然而,我们确实利用了同样的基本结构,从记忆中提取情节并从中学习。由于我们有两种训练方法,我们将代码分成不同的训练函数,明确地称它们为:
def train(self):
batch_size = 32
if len(self.memory) < batch_size:
return rewards = []
samples = random.sample(self.memory, batch_size)
self._train_critic(samples)
self._train_actor(samples)
现在我们定义两种训练方法。然而,这与 DQN 的情况非常相似:我们只是找到了贴现的未来奖励和培训。唯一的区别是,我们正在对状态/动作对进行训练,并使用 target_critic_model 来预测未来的回报,而不是演员:
def _train_critic(self, samples):
for sample in samples:
cur_state, action, reward, new_state, done = sample
if not done:
target_action =
self.target_actor_model.predict(new_state)
future_reward = self.target_critic_model.predict(
[new_state, target_action])[0][0]
reward += self.gamma * future_reward
self.critic_model.fit([cur_state, action],
reward, verbose=0)
至于演员,我们很幸运地做了之前所有的努力!我们已经设置了梯度在网络中的工作方式,现在只需用我们遇到的动作和状态来调用它:
def _train_actor(self, samples):
for sample in samples:
cur_state, action, reward, new_state, _ = sample
predicted_action = self.actor_model.predict(cur_state)
grads = self.sess.run(self.critic_grads, feed_dict={
self.critic_state_input: cur_state,
self.critic_action_input: predicted_action
})[0] self.sess.run(self.optimize, feed_dict={
self.actor_state_input: cur_state,
self.actor_critic_grad: grads
})
如前所述,我们利用了目标模型。因此,我们必须在每个时间步更新它的权重。然而,我们只是缓慢地这样做。更具体地,我们通过分数selfτ保留目标模型的值,并将其更新为相应的模型权重余数*(1-selfτ)*分数。我们对演员/评论家都这样做,但下面只给出了演员(你可以在帖子底部的完整代码中看到评论家):
def _update_actor_target(self):
actor_model_weights = self.actor_model.get_weights()
actor_target_weights =self.target_critic_model.get_weights()
for i in range(len(actor_target_weights)):
actor_target_weights[i] = actor_model_weights[i]
self.target_critic_model.set_weights(actor_target_weights
交流预测
这与我们在 DQN 的做法相同,因此没有太多关于其实施的讨论:
def act(self, cur_state):
self.epsilon *= self.epsilon_decay
if np.random.random() < self.epsilon:
return self.env.action_space.sample()
return self.actor_model.predict(cur_state)
预测码
预测代码也与以前的强化学习算法非常相似。也就是说,我们只需重复试验,并在代理上调用预测、记忆和训练:
def main():
sess = tf.Session()
K.set_session(sess)
env = gym.make("Pendulum-v0")
actor_critic = ActorCritic(env, sess)
num_trials = 10000
trial_len = 500
cur_state = env.reset()
action = env.action_space.sample()
while True:
env.render()
cur_state = cur_state.reshape((1,
env.observation_space.shape[0]))
action = actor_critic.act(cur_state)
action = action.reshape((1, env.action_space.shape[0]))
new_state, reward, done, _ = env.step(action)
new_state = new_state.reshape((1,
env.observation_space.shape[0]))
actor_critic.remember(cur_state, action, reward,
new_state, done)
actor_critic.train()
cur_state = new_state
完整代码
这里是使用 AC(演员-评论家)在“钟摆-v0”环境下进行训练的完整代码!
好家伙,那很长:谢谢你从头到尾读完(或者至少略读)!敬请关注下一期 Keras+OpenAI 教程!
评论并点击下面❤️以示支持!
带有 Keras + OpenAI 的强化学习:DQNs
快速回顾
上次在我们的 Keras/OpenAI 教程中,我们讨论了一个将深度学习应用于强化学习上下文的非常基本的例子。回想起来,这真是一场不可思议的演出!如果你查看训练数据,随机机会模型通常只能执行中值 60 步。然而,通过对这些看起来非常普通的数据进行训练,我们能够“击败”环境(即获得> 200 步的性能)。这怎么可能呢?
对此我们可以有一个直观的感受。让我们想象一下我们用作训练数据的完全随机序列。任何两个序列都极不可能彼此高度重叠,因为它们完全是随机生成的。然而,有一些关键特征在成功的试验之间是共同的,例如当杆子向右倾斜时,推车向右推,反之亦然。因此,通过在所有这些试验数据上训练我们的神经网络,我们提取了促成它们成功的共有模式,并能够消除导致它们独立失败的细节。
也就是说,我们本周考虑的环境比上周要困难得多:登山车。
更复杂的环境
尽管看起来我们应该能够应用与上周应用的技术相同的技术,但这里有一个关键特征使得这样做不可能:我们不能生成训练数据。与非常简单的横翻筋斗的例子不同,采取随机的动作通常只会导致我们在山脚下结束试验。也就是说,我们有几个试验结果都是一样的,最后都是 200。这对于用作训练数据实际上是无用的。想象一下,你在一个班级里,不管你在试卷上写了什么答案,你都得了零分!你将如何从这些经历中学习?
Random inputs for the “MountainCar-v0” environment does not produce any output that is worthwhile or useful to train on
与此一致,我们必须找到一种方法来逐步改善以前的试验。为此,我们使用一个最基本的强化学习的垫脚石:Q-learning!
DQN 理论背景
Q-learning(顺便说一下,它不代表任何东西)的核心是创建一个“虚拟表”,说明在给定环境的当前状态下,每个可能的行为会获得多少奖励。让我们一步一步地分解它:
You can imagine the DQN network as internally maintaining a spreadsheet of the values of each of the possible actions that can be taken given the current environment state
我们所说的“虚拟表”是什么意思想象一下,对于输入空间的每一种可能的配置,您有一个表,为您可以采取的每一种可能的行动分配一个分数。如果这是神奇的可能,那么对你来说“战胜”环境将是极其容易的:简单地选择得分最高的行动!关于这个分数有两点需要注意。首先,这个分数通常被称为“Q 分数”,这就是整个算法名称的来源。第二,与任何其他分数一样,这些 Q 分数在它们的模拟环境之外没有意义。也就是说,它们没有的绝对意义,但这完全没问题,因为我们只需要它来做比较。
那么,为什么我们需要虚拟表用于的每个输入配置呢?为什么我们不能用一张桌子来统治所有人呢?原因是这样做没有意义:这就等于说,在谷底时采取的最佳行动正是你站在左斜坡最高点时应该采取的行动。
现在,我所描述的(为每个输入配置维护一个虚拟表)的主要问题是这是不可能的:我们有一个连续(无限)的输入空间!我们可以通过离散化输入空间来解决这个问题,但这似乎是一个非常粗糙的解决方案,我们在未来的情况下会反复遇到这个问题。那么,我们如何解决这个问题呢?通过将神经网络应用于这种情况:这就是 DQN 的 D 的来源!
DQN 代理
因此,我们现在已经把问题简化为找到一种方法,在给定当前状态的情况下,给不同的动作分配 Q 分数。当使用任何神经网络时,这是一个非常自然的第一个问题的答案:我们的模型的输入和输出是什么?对于这个模型,您需要理解的数学范围是下面的等式(不要担心,我们会分解它):
如前所述,q 代表给定当前状态(s)和所采取的行动(a)时由我们的模型估计的值。然而,目标是确定一个状态的总值。我这么说是什么意思?的总体值是**,既是你将获得的即时回报又是**你在该职位上未来将获得的预期回报。也就是说,我们要考虑一个事实,即一个职位的价值往往不仅反映其眼前的收益,还反映其所能实现的未来收益(该死,深)。在任何情况下,我们都会对未来的回报进行贴现,因为如果我比较两种情况,在这两种情况中,我期望得到 100 美元,其中一种是在未来,我将总是选择目前的交易,因为未来的交易在我做交易和我收到钱之间可能会发生变化。伽马因子反映了该州预期未来回报的折余值。
就是这样:这就是我们需要的所有数学知识!是时候开始写代码了!
DQN 代理实现
深度 Q 网络围绕着持续学习,这意味着我们不会简单地积累一堆试验/训练数据并将其输入模型。相反,我们通过运行试验来创建训练数据,并在运行试验后直接将这些信息输入其中。如果这一切现在看起来有些模糊,不要担心:是时候看看关于这一点的一些代码了。代码主要围绕着定义一个 DQN 类,算法的所有逻辑都将在这个类中实现,并且我们为实际的训练公开一组简单的函数。
DQN 超参数
首先,我们将讨论一些与 dqn 相关的参数。它们中的大多数是大多数神经网络实现的标准:
class DQN:
def __init__(self, env):
self.env = env
self.memory = deque(maxlen=2000)
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.learning_rate = 0.01
让我们一步一步地看完这些。第一个是简单的环境,当我们需要在创建模型时引用形状时,我们提供它是为了方便。“记忆”是 DQNs 的关键组成部分:如前所述,试验用于持续训练模型。然而,我们不是在试验出现时进行训练,而是将它们添加到记忆中,并在记忆的随机样本上进行训练。为什么要这样做,而不只是将最近的 x 次试验作为我们的“样本”进行训练原因有些微妙。想象一下,我们只是将最近的试验作为样本进行训练:在这种情况下,我们的结果将只学习它最近的行动,这可能与未来的预测没有直接关系。特别是在这种环境下,如果我们沿着斜坡的右侧向下移动,那么对最近试验的训练将需要对您向右上坡时的数据进行训练。但是,这与确定在你即将面临的爬上左山坡的场景中采取什么行动完全没有关系。因此,通过采取随机样本,我们不会偏向我们的训练集,而是理想地了解如何同样好地扩展我们会遇到的所有环境。
因此,我们现在讨论模型的超参数:伽马、ε/ε衰减和学习速率。第一个是未来回报折旧因素(<1) discussed in the earlier equation, and the last is the standard learning rate parameter, so I won’t discuss that here. The second, however, is an interesting facet of RL that deserves a moment to discuss. In any sort of learning experience, we always have the choice between exploration vs. exploitation. This isn’t limited to computer science or academics: we do this on a day to day basis!
Consider the restaurants in your local neighborhood. When was the last time you went to a new one? Probably a long time ago. That corresponds to your shift from 探索到开发):你不去寻找新的更好的机会,而是满足于你在过去的经历中找到的最好的机会,并从那里最大化你的效用。相比之下,当你搬进你的房子时:那时,你不知道什么餐馆是好的或不好的,所以被诱惑去探索你的选择。换句话说,学习有一个明显的趋势:在你没有意识到的时候探索你所有的选择,一旦你对其中一些有了看法,就逐渐转向利用。同样,我们希望我们的模型能够捕捉到这种自然的学习模式,而 epsilon 就扮演了这一角色。
ε表示我们将致力于探索的时间比例。也就是说,试验的一小部分selfε,我们将简单地采取随机行动,而不是我们预测在那种情况下最好的行动。如前所述,在我们对该问题形成稳定的估值之前,我们希望在开始时更多地这样做,因此在开始时将ε初始化为接近 1.0,并在每个连续的时间步将其衰减某个分数< 1。
DQN 车型
在上面的 DQN 初始化中,有一个关键的东西被排除在外:用于预测的实际模型!就像在我们最初的 Keras RL 教程中一样,我们直接以数字向量的形式给出输入和输出。因此,在我们的网络中,除了完全连接的层之外,没有必要采用更复杂的层。具体来说,我们将模型定义为:
def create_model(self):
model = Sequential()
state_shape = self.env.observation_space.shape
model.add(Dense(24, input_dim=state_shape[0],
activation="relu"))
model.add(Dense(48, activation="relu"))
model.add(Dense(24, activation="relu"))
model.add(Dense(self.env.action_space.n))
model.compile(loss="mean_squared_error",
optimizer=Adam(lr=self.learning_rate))
return model
并使用它来定义模型和目标模型(解释如下):
def __init__(self, env):
self.env = env
self.memory = deque(maxlen=2000)
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.learning_rate = 0.01
self.tau = .05 self.model = self.create_model()
# "hack" implemented by DeepMind to improve convergence
self.target_model = self.create_model()
事实上,有两个独立的模型,一个用于预测,一个用于跟踪“目标值”,这绝对是违反直觉的。明确地说,模型( self.model )的角色是对要采取的行动进行实际预测,而目标模型( self.target_model )跟踪我们希望我们的模型采取的行动。
为什么不采用一种模式来实现这两种功能呢?毕竟,如果有东西在预测要采取的行动,难道不应该隐含地决定我们想要我们的模型采取什么模型吗?这实际上是 DeepMind 在深度学习中开发的那些“奇怪的技巧”之一,用于在 DQN 算法中实现收敛。如果你使用一个单一的模型,它可以(并且经常)在简单的环境中收敛(比如横竿)。但是,它在这些更复杂的环境中不收敛的原因是因为我们如何训练模型:如前所述,我们正在“动态地”训练它
因此,我们在每个时间步进行训练,如果我们使用单一网络,也将在每个时间步改变“目标”。想想那会有多混乱!这就像一个老师告诉你去完成 pg。6,当你读完一半的时候,她把它改成了 pg。当你完成一半的时候,她让你做 pg。21!因此,这由于缺乏使用优化器的明确方向而导致缺乏收敛,即梯度变化太快而无法稳定收敛。因此,作为补偿,我们有一个变化较慢的网络来跟踪我们的最终目标,并努力实现这些目标。
DQN 培训
训练包括三个主要步骤:记忆、学习和重新定位目标。第一个基本上只是随着我们经历更多的试验而增加记忆:
def remember(self, state, action, reward, new_state, done):
self.memory.append([state, action, reward, new_state, done])
这里没有什么值得注意的,除了我们必须存储 done 阶段,以便稍后更新奖励函数。转到 DQN 的主体,我们有火车功能。这是我们利用我们储存的记忆,并从我们过去看到的东西中积极学习的地方。我们首先从整个内存中抽取一个样本。从那以后,我们对每个样品进行不同的处理。正如我们在前面的等式中看到的,我们希望将 Q 函数更新为当前奖励和预期未来奖励(按 gamma 折旧)之和。在我们处于试验末期的情况下,没有这样的未来奖励,所以这种状态的全部价值只是我们当前收到的奖励。然而,在非终结状态下,我们希望看到如果我们能够采取任何可能的行动,我们将获得的最大回报是什么,从中我们得到:
def replay(self):
batch_size = 32
if len(self.memory) < batch_size:
return samples = random.sample(self.memory, batch_size)
for sample in samples:
state, action, reward, new_state, done = sample
target = self.target_model.predict(state)
if done:
target[0][action] = reward
else:
Q_future = max(
self.target_model.predict(new_state)[0])
target[0][action] = reward + Q_future * self.gamma
self.model.fit(state, target, epochs=1, verbose=0)
最后,我们必须重新定位我们的目标,简单地将权重从主模型复制到目标模型中。然而,与主训练方法不同,此目标更新的调用频率较低:
def target_train(self):
weights = self.model.get_weights()
target_weights = self.target_model.get_weights()
for i in range(len(target_weights)):
target_weights[i] = weights[i]
self.target_model.set_weights(target_weights)
DQN 行动
最后一步是简单地让 DQN 实际执行期望的动作,该动作基于给定的ε参数在采取随机动作和基于过去训练的动作之间交替,如下所示:
def act(self, state):
self.epsilon *= self.epsilon_decay
self.epsilon = max(self.epsilon_min, self.epsilon)
if np.random.random() < self.epsilon:
return self.env.action_space.sample()
return np.argmax(self.model.predict(state)[0])
培训代理
现在,我们开发的复杂代理自然会对代理进行培训。我们必须实例化它,将我们遇到的经验输入它,训练代理,并更新目标网络:
def main():
env = gym.make("MountainCar-v0")
gamma = 0.9
epsilon = .95 trials = 100
trial_len = 500 updateTargetNetwork = 1000
dqn_agent = DQN(env=env)
steps = []
for trial in range(trials):
cur_state = env.reset().reshape(1,2)
for step in range(trial_len):
action = dqn_agent.act(cur_state)
env.render()
new_state, reward, done, _ = env.step(action) reward = reward if not done else -20
print(reward)
new_state = new_state.reshape(1,2)
dqn_agent.remember(cur_state, action,
reward, new_state, done)
dqn_agent.replay()
dqn_agent.target_train() cur_state = new_state
if done:
break
if step >= 199:
print("Failed to complete trial")
else:
print("Completed in {} trials".format(trial))
break
完整代码
这里是使用 DQN 在“MountainCar-v0”环境下进行训练的完整代码!
敬请关注下一期 Keras+OpenAI 教程!
评论并点击下面❤️以示支持!
简介:用 OpenAI Gym 强化学习
强化学习快速入门& OpenAI 健身房的基础知识。欢迎使用导航和驾驶任务实用 RL 入门指南。
了解基本的 goto 概念,快速开始强化学习,并学习使用 OpenAI gym 测试您的算法,以获得以研究为中心的可重复结果。
本文首先向您介绍强化学习的基础知识、其当前的进步以及一个有点详细的自动驾驶实际用例。在那之后,我们开始学习代码,并了解 OpenAI Gym,这是一个经常被研究人员用于标准化和基准测试结果的工具。当编码部分到来时,请打开您的终端,准备好动手操作。一个节省时间的提示:如果你想跳过基础,只想直接尝试开放式人工智能健身房,你可以直接跳到“概念理解”部分。
Earlier behavioral psychology experiments somewhat did pave the way for current RL movement in computer science by providing strong theoretical understanding behind the agent’s motivation. Image Courtesy: verywell
这里有什么区别?
主要有三类学习:监督学习、非监督学习和强化学习。让我们看看它们之间的基本区别。在监督学习中,我们试图预测一个目标值或类,其中用于训练的输入数据已经被分配了标签。而无监督学习使用未标记的数据来查看模式以形成聚类,或者进行 PCA/异常检测。RL 算法类似于寻找最佳方法以获得最大回报的优化程序,即给出获胜策略以实现目标。
Consider a Banking Use Case of Different Learning Types. Image Courtesy: Preydata
在强化学习中,有多种范例以自己的方式实现这种成功的策略。在复杂的情况下,计算精确的获胜策略或精确的奖励价值函数变得非常困难,特别是当我们的代理人开始从互动中学习而不是从先前获得的经验中学习时。例如,一只狗发现它最喜欢的玩具藏在新房子里。这只狗会搜索房子,并根据它的互动得到一个关于房子示意图的大概想法。但是,仍然有一个很好的机会,如果它位于一个新的未探索的位置,狗会发现很难再找到隐藏的玩具。
这种基于交互的学习通常也被称为无模型学习,其中代理不具有环境的确切知识,即代理不存储状态-动作概率转移函数的知识。它试图接近成功的策略(即政策)或回报-价值收益(即价值函数)。在主人的房子里寻找他的隐藏玩具的同一只狗将具有先前的经验,即先前的环境知识,并且将在房子内的任何位置舒适地寻找玩具。这种寻找隐藏玩具的学习在 RL 中被称为基于模型的学习。
强化学习:导论
根据强化学习的定义,一个主体在给定的环境中以连续或离散的方式采取行动,以最大化编码在其中的某种回报概念。听起来太深奥了,但它的研究基础可以追溯到经典的行为主义心理学、博弈论、优化算法等。但是,对我们有好处的是,已经为我们做了很多*‘搭建舞台’*的工作,让我们直接进入问题公式化的世界,发现新事物。
本质上,其中最重要的是,在完全已知/可观测的确定性环境中,智能体的强化学习场景可以被公式化为动态规划问题。从根本上说,这意味着代理人必须以系统的方式执行一系列步骤,以便它能够学习理想的解决方案,并从奖励值中获得指导。用数学术语表达这种情况的方程被称为贝尔曼方程,我们将在某个时候看到它的作用。
It takes into account some initial choices and future choices to come to formulate decision problems at a certain point.
代理和环境
在进一步理解关于 RL 的技术细节之前,让我们首先定性地正式定义主体和环境的概念。环境是智能体的世界,它通过在其上执行给定的动作来改变智能体的状态。智能体是通过传感器感知环境并用执行器执行动作的系统。在下面的情况中,Homer(左)和 Bart(右)是我们的 代理 ,世界是他们的 环境 。他们在其中采取行动,并通过获得快乐或满足作为回报来改善他们的存在状态。
Positive and Negative rewards increase and decrease the tendency of a given behavior respectively. Eventually leading to better results in that environment over a period of time. Image Courtesy: psychestudy
最近的进展和范围
从 IBM 的深蓝 v/s Kasparov 以来最受欢迎的游戏系列开始,它为 AI 创造了巨大的宣传。以及围棋比赛系列中 AlpaGo v/s Lee Sedol 对于深度强化学习智能体的类人感知。控制一个棋盘配置比宇宙中的原子还要多的游戏来对抗一个 den 9 master 显示了这样的智能系统所拥有的力量。此外,最近 RL 的研究突破和用 OpenAI 的 Dota 机器人战胜世界职业选手也值得称赞。随着代理人接受处理如此复杂和动态环境的训练,掌握这些游戏是测试人工智能代理人处理非常复杂的类似等级的情况的极限的一个例子。就应用而言,像无人驾驶汽车、智能无人机这样已经很复杂的应用正在现实世界中运行。
我们再了解一些强化学习的基础知识,然后从 OpenAI 健身房开始做自己的代理。之后,我会建议你向深度学习迈进,处理更复杂的情况。所有 RL 应用的范围超出想象,可以应用于许多领域,如时间序列预测、医疗保健、供应链自动化等。但是,这里我们将讨论自动驾驶汽车和导航任务中最受欢迎的应用用例之一。
Got the reference ?
一遍又一遍地在同一状态上运行算法的独特能力有助于它学习特定状态的最佳行动,以前进到理想的下一个状态,这本质上相当于打破时间的构造,让人类几乎在任何时间都可以获得无限的学习经验。
Restricting Lookaheads with Monte Carlo Look Search Tree: AlphaGo must restrict Breath and Depth of search among all board configurations with heuristics information supplied by neural network training and determining winning policy for max reward. Image Courtesy: ajudaily
概念理解
以 RL 为框架,agent 通过一定的动作来改变 agent 的状态,每个动作都与奖励值相关联。它还使用一个策略来确定它的下一个动作,该策略由一系列步骤组成,这些步骤将状态-动作对映射到计算出的奖励值。策略可以定性地定义为代理在给定时间的行为方式。现在,策略可以是确定性的和随机的,找到一个最优策略是解决给定任务的关键。
同样,**不同动作在不同状态会有不同的关联奖励值。**就像口袋坦克游戏中的“开火”命令一样不能总是有相同的奖励值与之相关,因为有时最好保留一个战略上有利的位置。为了以有计划的方式处理这种具有如此巨大组合的复杂动态问题,我们需要一个 Q 值(或动作值)表,该表存储一个 映射 或 状态-动作对以进行奖励。
Depending on terrain and position along with power combinations being available our reward values will vary even after being present in the same state.
现在,将 RL 环境中的环境定义为功能组件,它简单地将给定状态下的动作作为输入,并返回与动作-状态对相关联的新状态和奖励值。
For Atari Environments like Mario, Atari, PAC-MAN etc.; Q-learning with CNN loss approximation can be used. Image Courtesy: leonardoaraujosantos
然而,有趣的是,当环境变得非常复杂,难以用计算限制性迭代算法处理时,神经网络凭借其学习状态-动作对的能力轻松进入画面,这被称为深度 RL。喜欢玩早期的游戏,如马里奥,雅达利,吃豆人等。
这里,我们将只限于简单的 Q 学习,即 w/o 神经网络,其中 Q 函数将状态-动作对映射到最大值,并结合即时奖励和未来奖励,即对于新状态,学习值是当前奖励加上未来奖励估计值。将其量化为一个具有不同参数的方程,如学习率和折扣因子,以指导代理的行动选择。我们得出以下方程:在结构上,它与贝尔曼方程有许多相似之处。
Q-Function Equation, tells about the maximum expected cumulative award for a given pair. Image Courtesy: Wikipedia
动手:为什么要开健身房?
2016 年《自然》杂志的一项调查表明,超过 70%的研究人员试图重现另一位科学家的实验,但失败了,超过一半的人没能重现他们自己的实验。
OpenAI 是为了消除论文中缺乏标准化的问题而创建的,其目的是通过提供易于设置的多种多样的环境来创建更好的基准。这个工具的目的是增加人工智能领域的可复制性,并提供工具让每个人都可以学习人工智能的基础知识。
打开你的终端,准备一些 CTRL+C 和 CTRL+V 的工作!!但是,我当然会建议反对。
让我们一起去健身吧
什么是 OpenAI 健身房?这个 python 库给了我们大量的测试环境来处理我们的 RL 代理的算法,这些算法带有用于编写通用算法和测试它们的共享接口。让我们开始吧,只需在终端上键入pip install gym
即可轻松安装,您将获得一些经典环境来开始在您的代理上工作。复制下面的代码并运行它,你的环境将被加载。您可以在这里查看其他可用的环境,如 Algorithmic、Atari、Box2D 和 Robotics ,并使用下面列出的第二个代码片段组件列出所有可用的环境。
# 1\. It renders instances for 500 timesteps, performing random actions.
import gym
env = gym.make('Acrobot-v1')
env.reset()
for _ in range(500):
env.render()
env.step(env.action_space.sample())
# 2\. To check all env available, uninstalled ones are also shown.
from gym import envs
print(envs.registry.all())
当对象通过一个动作与环境交互时,然后 step() 函数返回通常表示环境下一个状态的observation
、reward
前一个动作的奖励浮动、done
当该重置环境或实现的目标时,以及info
用于调试的 dict ,如果它包含环境上一个状态的原始概率,它可以用于学习。从下面的代码片段看它是如何工作的。另外,观察Space
类型的observation
在不同环境下有何不同。
import gym
env = gym.make('MountainCarContinuous-v0') # try for different environments
observation = env.reset()
for t in range(100):
env.render()
print observation
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
print observation, reward, done, info
if done:
print("Finished after {} timesteps".format(t+1))
break[Output For Mountain Car Cont Env:]
[-0.56252328 0.00184034]
[-0.56081509 0.00170819] -0.00796802138459 False {}[Output For CartPole Env:]
[ 0.1895078 0.55386028 -0.19064739 -1.03988221]
[ 0.20058501 0.36171167 -0.21144503 -0.81259279] 1.0 True {}
Finished after 52 timesteps
上面代码中的动作空间是什么?action-space
& observation-space
描述了特定环境的动作&状态参数的有效格式。只需看看返回值。
import gym
env = gym.make('CartPole-v0')
print(env.action_space) #[Output: ] Discrete(2)
print(env.observation_space) # [Output: ] Box(4,)
env = gym.make('MountainCarContinuous-v0')
print(env.action_space) #[Output: ] Box(1,)
print(env.observation_space) #[Output: ] Box(2,)
离散为非负的可能值,大于 0 或 1 相当于左右移动横拉杆平衡。方框代表 n 维阵列。这些标准接口有助于为不同的环境编写通用代码。因为我们可以简单地检查边界env.observation_space.high/[low]
并将它们编码到我们的通用算法中。
一幅插图
这里,我们使用 Python3.x 作为下面 Q-Learning 算法的高亮代码样本。
sudo pip install 'gym[all]'
让我们开始构建我们的 Q 表算法,它将尝试解决 FrozenLake 导航环境。在这种环境下,我们的目标是在一个可能有洞的冰湖上达到目标。这是这个玩具文本环境是如何描绘表面的。
SFFF (S: starting point, safe)
FHFH (F: frozen surface, safe)
FFFH (H: hole, fall to your doom)
HFFG (G: goal, where the frisbee is located)
q 表包含映射到奖励的状态-动作对。因此,我们将构建一个数组,在算法执行期间将不同的状态和动作映射到奖励值。它的维度将清楚地|陈述| x |动作|。让我们用 Q 学习算法的代码来写。
import gym
import numpy as np # 1\. Load Environment and Q-table structure
env = gym.make('FrozenLake8x8-v0')
Q = np.zeros([env.observation_space.n,env.action_space.n])
# env.observation.n, env.action_space.n gives number of states and action in env loaded# 2\. Parameters of Q-learning
eta = .628
gma = .9
epis = 5000
rev_list = [] # rewards per episode calculate# 3\. Q-learning Algorithmfor i in range(epis):
# Reset environment
s = env.reset()
rAll = 0
d = False
j = 0
#The Q-Table learning algorithm
while j < 99:
env.render()
j+=1
# Choose action from Q table
a = np.argmax(Q[s,:] + np.random.randn(1,env.action_space.n)*(1./(i+1)))
#Get new state & reward from environment
s1,r,d,_ = env.step(a)
#Update Q-Table with new knowledge
Q[s,a] = Q[s,a] + eta*(r + gma*np.max(Q[s1,:]) - Q[s,a])
rAll += r
s = s1
if d == True:
break
rev_list.append(rAll)
env.render()print("Reward Sum on all episodes " + str(sum(rev_list)/epis))
print("Final Values Q-Table")
print(Q)
如果您对使用其他环境感兴趣,您可以选择使用下面突出显示的代码片段。
Frozen Lake Environment Visualization Diagram.
# Reset environment
s = env.reset()
d = False
# The Q-Table learning algorithm
while d != True:
env.render()
# Choose action from Q table
a = np.argmax(Q[s,:] + np.random.randn(1,env.action_space.n)*(1./(i+1)))
#Get new state & reward from environment
s1,r,d,_ = env.step(a)
#Update Q-Table with new knowledge
Q[s,a] = Q[s,a] + eta*(r + gma*np.max(Q[s1,:]) - Q[s,a])
s = s1
# Code will stop at d == True, and render one state before it
但是请记住,即使有一个公共接口,不同环境的代码复杂度也是不同的。在上面的环境中,我们只有一个简单的 64 状态环境,只需要处理很少的动作。我们能够非常容易地将它们存储在一个二维数组中用于奖励映射。现在,让我们考虑更复杂的环境案例,如 Atari envs ,看看需要什么方法。
env = gym.make("Breakout-v0")
env.action_space.n
Out[...]: 4
env.env.get_action_meanings()
Out[...]: ['NOOP', 'FIRE', 'RIGHT', 'LEFT']
env.observation_space
Out[...]: Box(210, 160, 3)
需要用 210×160×3 张量来表示,这使得我们的 Q 表更加复杂。同样,每个动作在 k 帧的持续时间内重复执行,其中 k 是从{2,3,4}中均匀采样的。RGB 通道中有 33,600 个像素,值的范围从 0 到 255,环境显然变得过于复杂。这里不能使用简单的 Q 学习方法。深度学习及其 CNN 架构是这个问题的解决方案,也是这篇介绍性文章后续应该关注的主题。
结论
现在,有了上面的教程,你就有了关于健身房的基本知识,以及开始健身所需要的一切。Gym 也兼容 TensorFlow & PyTorch,但为了保持教程简单,我没有在这里使用它们。在试用了体育馆 软件包之后,你必须开始使用稳定基线 3 来学习 RL 算法的良好实现,以比较你的实现。要查看所有 OpenAI 工具,请查看它们的 github 页面。人工智能是一个不断扩展的领域,在许多领域都有应用,它将在未来的人工智能突破中发挥重要作用。希望你继续你的 RL 之旅&感谢阅读!!
光荣的插头
C’Mon… What did you expect? Image Courtesy: MCU
是的,和你分享可耻的然而 光荣的 入门项目插头,以防你刚入门强化学习。选择这些实践项目的额外优势是获得完整的导师支持&美妙的免费强化学习资源,如书籍、视频等。有趣的是,有两个现场项目我会推荐给你进一步研究:
- 如果你想在初级/中级水平的完整强化学习概念的基础上开始一个实践项目,你可以选择下面嵌入的 liveProject。在这里,在这个 liveProject 中,我讨论了实现最佳性能的自动驾驶汽车所需的研究原则。****
在这个 liveProject 中,您将开发一个可以模拟独立驾驶的 AI 驾驶代理。你的代理应该是…
www.manning.com](https://www.manning.com/liveproject/reinforcement-learning-for-self-driving-vehicles?utm_source=ashishrana&utm_medium=affiliate&utm_campaign=liveproject_rana_reinforcement_7_6_21&a_aid=ashishrana&a_bid=8f38c809)
另外,第一个里程碑是这个 liveProject 的 免费 练习。即使你不推进 liveProject,我保证你会从第一个里程碑的中了解到很多关于 自动驾驶 RL 任务的信息。干杯!
重要提示:**如果你在 2021 年 7 月 26 日之前来到这里,并且有兴趣继续进行第一个 liveProject。请使用代码 lprana 在这个项目上你会得到 45%的折扣。太棒了。!
- 第二,如果你特别想把你的注意力和努力放在 RL 的深度 Q 学习概念上。请随时查看下面的 liveProject。第一个里程碑是免费练习!
在这个 liveProject 中,您将研究强化学习方法,它将允许自动机器人推车…
www.manning.com](https://www.manning.com/liveproject/deep-reinforcement-learning-for-self-driving-robots?utm_source=ashishrana&utm_medium=affiliate&utm_campaign=liveproject_galbraith_deep_6_2_21&a_aid=ashishrana&a_bid=e4173afc)
朝现在!如果你选择了第一个项目,我们在那里见…***
复发触发因素:用人工智能预测压力
从问题的形成到解决方案的部署,今天的文章全面介绍了数据科学和机器学习在帮助阿片类药物成瘾患者的道路上的旅程。
问题定式化
try cycle Data(【trycycledata.com】T2)于 2017 年开始开发一个数据驱动的系统,以帮助解决阿片类药物的流行。这个概念的早期阶段可以追溯到 2012 年。针对处于危险或危机中的个人的自助解决方案不起作用。相反,TryCycle 采取了相反的方法,将他们的技术专长集中在寻找帮助卫生资源与客户保持联系的方法上,并监控他们作为门诊病人的复发风险。具体来说,TryCycle 设计了一个简单但功能强大的移动数据收集系统,用于收集受控护理环境之外的数据。这使得现有的临床医生-客户关系和治疗得以扩展,因此临床医生可以在风险水平上升之前更好地了解和监测复发的症状。
成瘾者研究压力预测因子的动机
根据美国疾病控制中心(CDC)的数据,药物过量死亡的人数从未如此之高,其中大多数死亡病例,2016 年有 66%涉及阿片类药物。提高数据质量和跟踪趋势,已被 CDC 认可为帮助了解问题的严重程度、将资源集中在最需要的地方以及评估预防和应对工作的成功的关键。
慢性压力与吸毒和易成瘾有很大关系(更多在这里、和这里)。我们也知道压力会增加上瘾的风险(这里的、和这里的)。有大量的研究将压力与成瘾联系起来(这里有更多的),并表明压力会导致康复中的人退出治疗(这里有更多的)。
嗯,我们可以看到复发与压力有关,但为什么不简单地预测复发呢?为什么要从预测压力开始?预测复发太远了,无法纠正。我们希望这种工具能够预测压力,以便在复发即将来临之前,能够在护理范围内减轻复发的触发因素。
数据收集
本文使用的专有数据集包含来自 16 个个人的 500 多个条目,历时五个月(2018 年 5 月-2018 年 9 月)。这是整个 TryCycle 数据集的一个小样本,是在知情同意的情况下收集的,用于研究。TryCycle 的移动应用程序收集了手机位置和其他数据,以及个人日志条目和定期自我评估,如下所示。
The TryCycle dashboard for reviewing client history and risk of relapse.
数据收集:J 日志
鼓励客户保持私人日志,并定期更新。这些数据可以由机器以保护隐私的方式进行分析,揭示情绪和其他有助于监控风险因素的因素。
数据收集:定期自我评估
按照规定的时间表(每天、每天两次、每周或每周两次,取决于诊所如何设置)提示客户完成基于技术的评估,包括八个复发指标,也称为复发线索或警告信号。这些因素与复发前行为、态度、感觉或想法的变化有关。由于许多研究表明压力是成瘾发展的主要因素,并可能引发复发过程,TryCycle 将压力作为其指标测量之一。
One screen in the TryCycle mobile app for collecting self-reports on relapse indicators.
TryCycle 评估监测的复发指标如下。在自我评估过程中,客户使用一系列滑动条给每个指标打分,范围从-1(差)到+1(好)。
为了了解复发风险,TryCycle 开发了一种专有算法,对上述所有 8 个复发指标以及数据趋势和计算提交之间的差异进行加权,为每个被监测的人分配一个分数和风险水平。
有了这个数据收集系统,下一个问题是如何从这些数据中预测未来的压力水平。目标是找到导致复发的预警信号之间的相关性。我们决定把重点放在压力上,更具体地说,从收集的数据中的其他因素来预测压力。
数据科学
在构建预测模型之前,我们需要评估和探索数据,以了解数据集中的特征。这里的关键免责声明是,如上所述,这个数据集相对较小,因此这些初步分析在这一点上是非常初步的。
研究复发指标如何相互关联
我们研究了复发指标之间的相互关系。如下图所示,每个指标之间都有关联。
Correlation matrix showing how the relapse indicators are all related.
这个结果很有意义。这些因素应该都指向同一个东西(复发)。它们都是同一个风险等式中的因素,一些比另一些更强。我们有一些根据相关性的强度将相关性分成不同类别的标准。以下是我们的相关标准:
使用上述标准,三个强相关指标是:
1.“渴望或触发”和“使用您选择的药物”
2.“药物治疗依从性”和“使用您选择的药物”
3.“渴望或触发”和“触发的关系”
基于这些早期发现,如果我们监测正确的指标,就有可能提前发现复发的诱因。上述发现是一个好迹象,表明预测模型可以告诉我们一些有用的东西。
随着我们对数据的深入挖掘,并查看适度的相关性,我们发现了“情绪波动”、“压力”和“履行责任”之间的关系。
Correlation matrix focusing in on how a subset of indicators are all related.
观察这些指标之间的相关性,我们得出结论:
1.“压力”与“情绪波动”和“履行职责”都有关联
2.“情绪波动”和“履行责任”与“渴望和触发因素”有适度的关联,在较小程度上与“触发关系”有关联
现在,相关性不是因果关系,但我们开始围绕压力指标到压力本身的路径建立一个论题。我们从前面提到的文章中知道,压力会导致复发。也许我们在这里有一个信号,我们在数据集中收集的因素可以提供一个做出结论的途径。例如:“压力”导致“情绪波动”和(不)履行责任,从而导致“渴望和触发”和“触发关系”,最终旧病复发?
我们在数据中寻找其他佐证信息。如果我们评估复发指标与一周中各天的相关性,我们会得到以下结果:
这些相关性都很弱。看起来周一可能会对情绪产生一些影响。这证实了我们的直觉,即回去工作并不有趣。我们还可以看到,“渴望和触发”和“触发的关系”似乎仍然在同一天匹配(周二、周三和周日)。
让我们继续查看按一周中的天和一天中的小时分组的平均值,看看是否有任何线索(下面并排的图表)。
The average value for each relapse indicator was grouped by day of the week (right), and hour of the day (left)
我们观察到,如果我们按一天中的小时或一周中的天对数据进行分组,压力(棕色)始终是输入的最低值之一。回想一下,低意味着坏。这告诉我们,正如我们所预料的那样,人口报告了高压力。现在,我们能预测这种压力,然后,也许,在咨询或医疗访问中解决这种压力吗?
预测模型
我们希望根据最近报告到系统中的可用数据来预测未来的压力水平。这种预测分析模型有助于护理圈内的每个人在压力转化为复发之前做出反应。
深入挖掘机器学习解决方案的细节,我们使用了 scikit learn 的随机森林分类器,因为这个模型非常适合数据。这种分类器通过学习与数据分离方式相对应的决策树来拟合数据。理解这种方法的一种方式是把这个模型想象成一本“选择你自己的冒险”的书。正如这本书创建了一个从故事开始到一些逻辑结论的分支路径,这个模型学习设置哪些路径来模仿数据中的模式。房地产领域一个直观的例子是 R2D3 的 这个。向下滚动链接可以看到这个过程的一个很好的动画例子。TryCycle 的模型从一个复发风险参数开始,并定义了一个决策树(又称决策树),即“如果高就向左走”,否则就“向右走”。当然,该模型还知道每个决策使用什么权重。
用于预测未来压力的数据包括七个指标,以及收集这些数据时的“星期几”和“一天中的小时”数据。当模型符合数据时,我们就可以进行预测。生成的决策树如下所示:
让我们后退一步,看看每个指标的重要性,以便更好地理解模型的作用。
从这些结果来看,“药物治疗依从性”和“选择药物的使用”这两个指标不能很好地预测压力,这是有道理的,因为我们认为压力才是它们的预测因素。似乎责任和关系是预测未来压力的关键因素。该模型现在检查这一小时是在午餐之前还是之后(12.5 小时)还是在工作之前和之后(14-17 小时),这显然比一天中的实际时间与压力有更强的联系。该模型还区分了工作日和周末报告的结果。
既然我们已经了解了模型是如何做出决策的,那么这些决策有多正确呢?
为了制作下面的图表,我们为一个测试用户在给定的一天将一个指标数据传递到我们的模型中,模型返回第二天的压力预测。我们对 61 个数据点反复这样做,以得到应力预测曲线(橙色)和实际报告的应力(蓝色)。同样,蓝线是该用户报告的压力水平,而橙线是基于前一天数据的预测压力值。如果两条线完全重叠,那么我们将有一个完美的预测。我们可以看到预测实际上相当不错。在一些地方,应力预测先于实际应力观测!
准确度是每个预测值与下一个报告值之间差异的平均值,上图中该患者的标称准确度为 95.63%。然而,点的平均精度是而不是我们正在寻找的值。我们真正想要的是能够在压力的变化和发生之前预测它们。看下面图表中的数据,客户报告的压力变化有 7 次。
Observing the prediction of changes in stress level (orange) against the actual changes in reported stress level (blue).
在上图中,我们可以看到,在许多压力变化被报道之前,我们确实猜测到了或者至少是朝着正确的方向发展(有时甚至是提前几天)。预测有许多小的变化,但预测中较大的变化通常接近实际报告的变化。因此,较大的预测似乎比较小的预测更精确,但趋势变化也有助于预测。
我们可以调整我们的算法,以支持精确度(低假阳性,但有时会错过压力峰值)或回忆(捕捉更多的压力峰值,但更多的假阳性)。数据集在不断增长,因此随着时间的推移,结果有望得到改善。随着收集的数据越来越多,我们也在考虑数据的季节性,以及数据中的特殊情况,如假期。
把这些放在一起帮助真实的人
TryCycle 从一个问题开始:识别复发的触发因素,并在护理圈内积极应对这些触发因素。希望本文能让您对产品的开发和部署有所了解。这个数据科学和机器学习之旅的最终结果是一个帮助陷入阿片类药物流行的成瘾者的系统。
来自 TryCycle Data 的消息:我们希望将我们的方法推广到更多的医疗保健机构。要预订演示并了解定量门诊护理的好处,请 点击此处联系 。
这篇文章是关于预测恢复中的吸毒者的压力。有关总体评估工具的更广泛概述,请参阅以下 2018 年案例报告:
如果你喜欢这篇关于人工智能预测戒毒者压力的文章,那么按下跟随按钮,拍拍拍手的东西,在社交频道上分享,并看看我过去读过的一些最热门的文章,比如“T2”如何为人工智能项目定价“和“T4”如何聘请人工智能顾问”。此外,退房请尝试循环。除了商业相关的文章之外,我还准备了一些关于那些希望采用深度机器学习的公司所面临的其他问题的文章,比如“没有云或 API 的机器学习”。
下次见!
-丹尼尔
daniel@lemay.ai 问好。
LEMAY . AI
1(855)LEMAY-AI
您可能喜欢的其他文章:
使用 Jupyter 笔记本电脑进行远程计算
[## 想在数据科学方面变得更好吗?
当我在我发布独家帖子的媒体和个人网站上发布新内容时,请单击此处获得通知。](https://bobbywlindsey.ck.page/5dca5d4310)
不久前,我让 AWS 为我提供了一个唯一的 URL,我可以导航并使用 Jupyter 笔记本。我钦佩它的便利性和能力,只要启动一个计算程序,关上笔记本电脑,就知道我的计算会继续进行。然而,根据您的使用情况,使用 AWS P2 实例会非常昂贵,对我来说,每月大约 600 美元。所以,我想我可以用这些钱建造一台电脑,作为深度学习的平台,偶尔玩玩视频游戏。
这篇文章描述了配置设置一旦你已经建立了你的电脑并且安装了像 Ubuntu 这样的 Linux 版本。事实证明,下面的配置对我来说比 AWS 更容易设置,在别名的帮助下,连接到我的服务器比以往任何时候都容易。我们开始吧!
装置
所以首先你需要在你的 Ubuntu 服务器上安装以下软件:
- Anaconda ,它将提供许多您需要的默认 Python 包
- openssh-server,可以安装以下软件:
sudo apt-get install openssh-server -y
- tmux,可以安装
sudo apt-get install tmux -y
如果您需要查看 openssh-server 的状态或重启它,请在您的终端中键入以下内容:
systemctl status ssh sudo service ssh restart
本地连接到您的服务器
为了确保大多数事情都设置正确,我们首先需要验证您可以连接到本地网络上的服务器。
好吧!所以在你的服务器上,打开位于/etc/ssh/sshd_config
的sshd_config
文件。要对其进行更改,您需要 sudo 权限。文件打开后,您需要指定连接时要使用的端口。无论您选择什么,我强烈建议不要使用默认端口 22。假设您决定使用端口 22222。在您的sshd_config
文件中有一个名为Port
的条目,您应该这样编辑它:
Port 22222
在AllowUsers
下,输入您登录服务器时使用的用户名。
AllowUsers your_username
接下来,将PasswordAuthentication
设置为yes
。
最后,为了确保 Ubuntu 不会阻止端口 8888 上的网络流量,我们需要调整它的 iptables:
sudo iptables -I INPUT -p tcp -s 0.0.0.0/0 --dport 8888 -j ACCEPT sudo iptables -I INPUT -p tcp -s 0.0.0.0/0 --dport 443 -j ACCEPT sudo netfilter-persistent save
现在,记下您的服务器的 IP 地址。这可以通过在您的终端中键入ifconfig
并查找类似于inet 192.168.1.112
的内容来找到。一旦您在本地网络上确定了服务器的 IP 地址,就该拿起您的笔记本电脑并尝试登录了:
ssh your_username@192.168.1.112 -p 22222
如果你得到一个终端提示,你就成功了!
远程连接到您的服务器
现在,设置远程计算的全部目的是,当你在别人的网络上时,你可以离开你的房子,远程进入你的服务器。要做到这一点,只需要做一些更改(要求您仍然在自己的网络上):
- 如果您的笔记本电脑上还没有一组公钥和私钥,生成它们
- 将您的公钥复制到您的服务器:
ssh-copy-id your_username@192.168.1.112 -p 22222
- 通过在您的服务器终端键入
curl 'https://api.ipify.org'
来识别您的服务器的 WAN IP 地址(注意,您的 ISP 经常更改此地址,这就是我使用 Google Wifi 的原因,它允许我从任何地方检查我的 WAN 地址) - 在路由器上,打开端口转发。使用我们的示例,您需要将端口 22222 转发到端口 22222。
现在尝试使用您找到的 WAN 地址远程访问您的服务器!
ssh your_username@server_wan_ip -p 22222
如果你看到一个提示,干得好!最后一件事是在你的sshd_config
文件中设置PasswordAuthentication
为no
,因为现在你用 ssh 密钥登录;这样,没有人可以尝试暴力破解您的密码。
你现在可以从你的网络之外访问你的服务器,去拿你自己的星巴克咖啡:)。
启动远程 Jupyter 笔记本
现在所有困难的工作都已完成,您可以通过以下步骤轻松使用远程 Jupyter 笔记本电脑:
- ssh 进入你的服务器:
ssh your_username@server_wan_ip -p 22222
- 开始一个新的 tmux 会话,您以后可以轻松地从该会话中退出:
tmux new -s session-name
- 无浏览器启动 jupyter-笔记本:
jupyter-notebook --no-browser --port=8889
- 现在,在笔记本电脑上的新终端中,将服务器端口流量转发到笔记本电脑的本地端口:
ssh -N -L localhost:8888:localhost:8889 your_username@server_wan_ip -p 22222
- 在您的网络浏览器中,导航到
localhost:8888/tree
,您应该会看到您的 Jupyter 笔记本!
现在,您可以在笔记本电脑上轻松使用 Jupyter 笔记本,而是使用服务器的强大资源来进行计算。
最后一件事,在想通了上面的步骤后,我想我应该通过使用别名和函数使这个过程变得更简单。以下是我添加到笔记本电脑的.bashrc
文件中的相关行:
server-connect() {
ssh your_username@$1 -p 22222
}jn-connect() {
ssh -N -L localhost:8888:localhost:8889 your_username@$1 -p 22222
}
我添加到服务器的.bashrc
文件中的行:
alias jn-remote="jupyter-notebook --ip='*' --no-browser --port=8889"
现在,上述 5 个步骤变成了:
server-connect server_wan_ip
tmux new -s session-name
jn-remote
- 打开新终端并键入
jn-connect server_wan_ip
- 导航至
localhost:8888/tree
就是这样!现在,你可以在咖啡店里一边用笔记本电脑放松,一边运行你正在构建的那些疯狂的神经网络。祝你好运!
如果你喜欢我在这里写的东西,一定要看看我的 个人博客 ,那里有我在媒体上没有的文章。
原载于 2017 年 8 月 10 日bobbywlindsey.com。
伦科砖尺寸优化
大家好!
我在 Quantroom 研究金融时间序列。我们致力于股票和密码市场的算法策略问题。今天,我将概述一项关于如何使用 Renko 图对金融时间序列进行降噪的研究。本文的目的是回答这个问题**“是否有比众所周知的方法更好的方法来确定最佳砖块尺寸?”**。
什么是伦科图表?
伦科图表是一种只关注价格变动的图表类型,不包括时间和成交量。伦科图表没有显示每个价格变动。您应该在创建 Renko 图表之前设置这些参数:
- 选择多大尺寸的图表来代表价格变动的幅度?如果砖块尺寸较小,图表会有更多的移动,但是这个图表会更嘈杂。
- 什么类型的价格将用于构建图表(如开盘价、收盘价等)。)?此外,应该选择一个时间框架,它可以是天,小时,分钟和滴答。分笔成交点数据更准确,因为没有遗漏移动。
Renko charts built on different brick size
连科海图制作的基本原理:
- 只有当价格变动超过指定的阈值水平时,才会生成新的砖块。
- 砖块大小总是一样的。例如,如果尺寸是 10 点,价格增加了 20,那么将画 2 块砖。如果价格上涨,砖块将为绿色(浅色),如果价格下跌,砖块将为红色(深色)。
- 将所选价格变量的下一个值与前一个砖块的最大值和最小值进行比较。新矩形总是显示在前一个矩形的右侧。
- 如果价格超过前一个砖块的顶部,超出砖块大小或更多,则绘制相应数量的绿色(浅色)矩形,使新砖块的下边界与前一个砖块的上边界相对应。
- 如果价格比前一个砖块的底部低了砖块大小或更多,则绘制相应数量的红色(黑色)矩形,新砖块的上边界与前一个砖块的下边界相对应。
图表分析师 Ranga 的这篇文章介绍了 Renko 图表。
在本文的下一部分,将使用我实现的 pyrenko 模块进行分析。
确定砖块尺寸的现有方法
- 传统。这种方法使用预定义的砖块大小绝对值。
- ATR 。这种方法使用平均真实范围(ATR)指标生成的值。ATR 用于过滤掉金融工具的正常噪音或波动。ATR 方法“自动”确定好的砖块尺寸。它计算出常规蜡烛图中的 ATR 值,然后将该值作为砖块大小。
使用算术平均值公式计算第一个 ATR 值:
质量评估和评分功能
这将是一个很好的衡量伦科图表的质量。让我们假设一个简单的策略,使用这些趋势跟随规则:当当前砖块是绿色(亮的)时,你的位置应该是“长的”。如果砖块的颜色已经改变,则改变到“短”位置。使用此逻辑,我们有以下参数:
- 余额是正负交易的总和。如果当前砖块与前一个砖块方向相同,则平衡值应增加+1。如果方向已经改变,平衡值应减少-2。正值就好。价值越大越好。
- sign_changes 是趋势被改变了多少次的数字。价值越低越好。
- price_ratio 是多个原始价格条与多个 renko 砖块的比率。大于 1 的值是好的。价值越大越好。
得分函数试图将这些参数整合成一个单一值。正值就好。价值越大越好。
如果 sign_changes 等于 0,则在计算前应设置为 1。
让我们尝试在 3D 空间中模拟和可视化这个得分函数。球体的大小对应于一个分数值。红色球体的分数等于-1 值。
导入模块和包:
Imported modules and packages
生成、计算并可视化得分函数的结果:
Simulating and visualizing of score function
得分值乘以常数,以获得更明确的球体尺寸。
Score function 3D visalization
本研究的关键思想是测试假设,即我们可以使用得分函数优化来获得比当前方法( ATR 方法)更好的砖块大小。给定的结果将通过统计学方法进行显著性检验。
实验
实验由三部分组成。
Experiment pipeline
数据准备
- 从维基百科获取股票列表(标准普尔 500 指数)。
- 过去 3 年每天的收市价(高、低、收盘)。
- 删除数据中缺少值的股票。
该部分的代码块:
Downloading and cleaning the stocks
由于这部分数据集中包含了 470 只股票。
砖块尺寸优化和 Renko 图表评估
该部分负责 Renko 图表评估。最佳砖块尺寸在包含 70% 天的列车组上确定。使用得分函数对剩余 30% 天进行 Renko 图评估。
Train test split method
这两种操作(优化和评估)是针对两种方法( ATR 和得分函数优化)执行的。在 ATR 情况下,序列的最后一个 ATR 值被认为是最佳砖块尺寸。
在得分函数优化的情况下,最佳砖块尺寸是给出得分函数的最大值。
Score(brick_size) plot
这种方法使用基于 Brent 方法的一维函数最小化。带负号的评分函数要用,因为是逆问题。
此代码包含应优化的功能,以及评分/优化流程:
Optimization process
Brent 的方法是一种结合二分法、割线法和逆二次插值法的求根算法。它具有二分法的可靠性,但它可以像一些不太可靠的方法一样快。如果可能的话,该算法尝试使用潜在的快速收敛割线方法或反二次插值,但是如果必要的话,它退回到更健壮的二分法。边界点可以作为训练集上的最低和最高 ATR 值给出,这将是一个很好的初始近似值。更多关于布伦特方法的信息这里。
Brent’s method visualization
Brent’s method algorithm
让我们通过两种方法的得分值来得到股票排序列表。分数值是在测试集上计算的。
画出得分最好的股票的 Renko 图(AVY 股票为 ATR ,AFL 股票为得分函数优化)。
Renko charts of highest score stocks
结果可视化的代码块:
Result visualization
结果分析
该散点图展示了价格比率如何对应于余额:
Scatter plots
Visualization of how price_ratio corresponds to balance
我们可以得出结论,得分函数优化方法更好地压缩了数据,因为价格比率有更大的趋势。
画一个柱状图,显示测试集上有多少股票的阳性/中性/阴性结果:阳性:得分>0;中性:得分= 0;负:分数< 0。
计算和可视化结果的代码:
Positive / Neutral / Negative histogram
Histogram of result distribution for two approaches
频率有一些差异,但分布的形状是相似的。让我们展示两种方法的分数直方图,以及它们的差异分布:
Score histograms
Score histogram for two approaches
Score difference histogram
将好估计一个分数的置信区间差。这将清楚地表明哪种方法平均起来会给出更好的分数。
检验样本来自正态分布的零假设。 p 值为 1.085e-11 ,非常低,说明样本来自非正态分布:
Test on normal distribution
在非正态分布上计算置信区间是不可接受的。
我们可以使用 bootstrapping 得到一个置信区间。Bootstrapping 是一种实用的计算机方法,用于通过基于可用样本的蒙特卡罗方法来研究基于多代样本的统计分布。允许您快速轻松地评估各种统计数据(置信区间、方差、相关性等)。)对于复杂的模型。
Boostrapping alogorithm
引导示例如下所示。该样本服从正态分布, p 值为 0.9816 。
重采样的代码块:
Bootstrapping
Bootstrapped sample of score difference
几乎所有的平均值都大于 0 。t 检验的 p 值为 0.0(零假设:score_diff = 0.0) ,我们拒绝零假设。这些计算证实,对于所提出的方法,得分函数优化和 ATR 方法之间的平均得分差异更大。
这是方法差异的一个特殊例子(UNH 股票)。
Renko charts of UNH for two approaches
结论
- 形式化了评估已建 Renko 图质量的得分函数。
- 描述了一个分数优化的过程。
- 所提出的方法比经典的 ATR 获得了更好的质量。这种优势在统计学上是显著的。
- pyrenko 是本分析中演示的一个模块,任何研究人员都可以使用。
- 使用 Renko 演示了完整的降噪过程。包括代码。
- 理论上,平衡参数乘以 brick_size 可以解释为测试集上的利润。这个简单的趋势跟踪策略是进一步研究的良好基础。为了更准确地估算利润,必须包括交易成本(经纪人费用、差价、滑点等)。).
- 发展的方法可用于策略,如配对交易,趋势跟踪,支持和阻力等。经过处理的无噪声图表变得易于理解,趋势线更加清晰。
如果你在股票分析中使用伦科图表或者打算使用,请告诉我。此外,有趣的是,您使用什么方法来确定砖块大小?
更新
下一章研究这里。
最诚挚的问候,
谢尔盖
刮租:我如何用 R 省钱
了解我如何使用 R 和网络抓取来对抗房租上涨并获胜。
(TD;博士:收到房地产公司的信,增加我的周租金。增加的原因没有证据支持。利用 R 寻找支持房地产索赔的证据。与权力斗争并取得胜利!)
围过来,围过来。来听一个关于一个人战胜当权者的故事。我难以置信地读到,他竭尽全力避免支付每周 5 美元的房租上涨,理由是没有实证证据证明这是合理的。
(严重上注:这是关于 R 中的网页抓取)
“…根据当前的市场状况…”
我目前公寓的 12 个月租约即将到期。正当我想知道我的房地产经纪人给我一份为期 12 个月的新租约的年度电子邮件什么时候会到的时候,我收到了这个:
您目前以每周 500 美元的价格租赁您的房产,租约将于 2017 年 11 月 18 日到期。我们最近完成了对您的物业的租金审核,并建议业主根据当前的市场情况,您的物业租金应每周增加 5 美元。
渴求专一,我的思维超速运转:什么市场条件?他们是如何定义它们的?5 美元太少了——什么样的市场条件变化能证明每周增加 5 美元是合理的呢?
一年前,我的房租每周涨了 20 美元,再涨 5 美元对我来说似乎没有意义。我也感觉到了一种我不喜欢的力量不平衡。一方面,我们有房地产经纪人,他可以访问房地产价格和报告的数据库。另一方面,我们有一个租户,他不能访问同样多的信息。这种信息不对称传统上会使承租人处于弱势地位,因此更有可能接受房地产经纪人的建议。
不幸的是,对我的房地产经纪人来说,我有点疯狂。
我住在一套两居室的公寓里,有一个停车位和一个卫生间。我想寻找具有类似配置的公寓的数据。
数据在哪里?
新南威尔士州政府的家庭和社区服务——“出租桌”
我知道新南威尔士州政府每季度都会发布新出租房屋和公寓的报告。报告中有一个标签显示了一居室和两居室公寓周租金分布的第一个四分位数、中间值和第三个四分位数。
当然,这对我来说不够精确。我知道,如果我没有停车位,我的租金很可能会更便宜。我也知道如果我有两个浴室,我的房租会更贵。所以我继续我的探索。
给我一些’英寸’刮
在谷歌搜索了一番后,我发现了房价。看看这张截图:
它有我需要的所有信息:
- 每周租金,
- 公寓出租的月份
- 就卧室、浴室和停车位数量而言的公寓配置
这个网站另一个吸引人的地方是循环友好的 URL。这是第一页的 URL:
https://www . auhouseprice . com/rent/list/NSW/2131/Ashfield/1/?排序=日期&类型=公寓&bmin = 2&bmax = 2
以下是第二页的 URL:
https://www . auhouseprice . com/rent/list/NSW/2131/Ashfield/2/?排序=日期&类型=公寓&bmin = 2&bmax = 2
有什么变化?
“阿什菲尔德”后面的数字!
现在猜猜前 50 个 URL 可能是什么。很简单,对吧?
哈德利万岁:R 的 rvest 包
rvest 是 R royalty,Hadley Wickham 的一个网络抓取 R 包。像大多数 Hadley 的包一样,rvest 以其直观的语法易于使用。该软件包是为与 magritter 的管道操作员(dplyr 的用户将熟悉该操作员)合作而构建的,允许我们创建优雅的数据管理管道。
开始使用 rvest 很容易:
- 找到您想要刮除的页面
- 获取该页面的 url
- 使用 rvest**read _ html()**函数将页面读入 R
- 使用 html_node() 或 html_nodes() 函数访问包含所需数据的 CSS 选择器(更多关于找到相关选择器和函数间差异的信息,见下文)。
- 使用 html_text() 函数访问包含在前面步骤中提取的 CSS 选择器中的文本。
- 使用 regex 提取上一步中访问的 CSS 选择器文本中的相关文本。
我们如何找出哪个 CSS 选择器包含了我们想要的数据?
带有 SelectorGadget 的 CSS 选择器
SelectorGadget 是谷歌 Chrome 的一个扩展,你只需点击它就可以快速发现哪个 CSS 选择器包含了你的目标数据。你不再需要在浏览器的开发工具中挖掘 HTML。这是一个巨大的时间节省。
安装它…现在!
让我们去战斗吧
我们现在已经有了使用 r 从网站收集数据的所有必要成分。我最终想要创建的输出是公寓租赁月份的每周租金时间序列。我想确保我的抓取工作符合预期,所以我想提取公寓的地址,以便我可以根据 Chrome 中的网页样本直观地检查我的数据。
让我们建立一个原型,刮第一页。
library(rvest)first_page <- read_html('https://www.auhouseprices.com/rent/list/NSW/2131/Ashfield/1/?sort=date&type=apartment&bmin=2&bmax=2')
目标:地址
进入 Chrome,点击右上角的 SelectorGadget 图标。点击其中一个地址,您应该会看到类似这样的内容出现在浏览器的右下角。
这是包含地址数据的 CSS 选择器。为了访问这个选择器中包含的数据,我们可以将页面通过管道传输到 html_nodes() ,指定 CSS 选择器名称作为它的参数。为了访问其中包含的文本,我们可以将这个结果通过管道传输到 html_text() 。
让我们来看看它的输出:
first_page %>%
html_nodes('h4') %>%
html_text() ## [1] "2/93 Alt Street Ashfield 2131"
## [2] "9/23 Orpington Street Ashfield 2131"
## [3] "9/60 Bland Street Ashfield 2131"
## [4] "4/122 Frederick Street Ashfield 2131"
## [5] "3/13 Frederick Street Ashfield 2131"
## [6] "Address available on request Ashfield 2131"
## [7] "19/12 Webbs Avenue Ashfield 2131"
## [8] "132 Frederick Street Ashfield 2131"
## [9] "17/106 Elizabeth Street Ashfield 2131"
## [10] "106/168 Liverpool Road Ashfield 2131"
## [11] "401/11-13 Hercules Street Ashfield 2131"
## [12] "105/168 Liverpool Road Ashfield 2131"
## [13] " Search Filter and Sorting
我们不希望元素 13(“搜索过滤和排序”)出现在我们的地址向量中,所以我们将其排除。
addresses <- first_page %>%
html_nodes('h4') %>%
html_text() %>%
.[which(. != ' Search Filter and Sorting ')]
目标:租赁的周租金和月租金
点击每周租金和公寓出租的月份给我们提出了一个挑战。包含我们要寻找的数据的选择器(“li”)由一大堆其他数据共享。看一下突出显示的内容:
让我们来看看从“li”选择器中可以提取的前几个元素:
first_page %>%
html_nodes('li') %>%
html_text() %>%
head(10)## [1] " View By State Melbourne, VIC Sydney, NSW Brisbane, QLD Adelaide, SA Perth, WA Canberra, ACT Darwin, NT Hobart, TAS "
## [2] "Melbourne, VIC"
## [3] "Sydney, NSW"
## [4] "Brisbane, QLD"
## [5] "Adelaide, SA"
## [6] "Perth, WA"
## [7] "Canberra, ACT"
## [8] "Darwin, NT"
## [9] "Hobart, TAS"
## [10] ""
我们知道我们想要提取的文本的模式。事情是这样的:
Mmm yyyy 每周租金$###
让我们使用一些 regex 和来自 stringr 包的 str_extract()函数(再次向 Hadley 致敬),在“li”选择器的元素向量中提取任何匹配这个模式的文本。注意,str_extract()为不匹配我们模式的元素返回一个与 NAs 输入长度相同的向量。最后一步,我们将过滤掉 NAs。
那些符号是什么?从正则表达式到英语的翻译
我的主张是,上述模式可以用 regex 表示如下:
^Rent.+/周。*\d{4}$
不要害怕。这看起来很疯狂,但所有这些都是在说:
- ^ — 我们应该匹配目标字符串开头的内容。
- 租金。+ —查找单词“租金”后跟一个或多个任意字符。句点是 regex 中的一个特殊字符,表示“匹配任何字符”。加号意味着“一个或多个”紧接在它前面的任何事物。
- /周 T5。* —查找“每周”,后跟零个或多个任意字符。零或更多用星号表示,它是加号的不太严格的表亲。
- \d{4} —目标字符串应以 4 位数字结尾。“\d”是 regex 中的另一个特殊字符,它表示“匹配从 0 到 9 的任何数字”。额外的斜线在那里,因为我们需要转义 r 中的反斜线,“{4}”意味着“重复紧接在前面的内容 4 次”。换句话说,匹配 4 位数。
- $ —目标字符串应该以紧跟在我之前的内容结束。在这种情况下,4 位数。
让我们来测试一下:
library(stringr)
price_month <- first_page %>%
html_nodes('li') %>%
html_text() %>%
str_extract('^Rent.+/week.*\\d{4}$') %>%
.[which(!is.na(.))]
price_month## [1] "Rent $420/week on Aug 2018" "Rent $510/week on Aug 2018"
## [3] "Rent $490/week on Aug 2018" "Rent $500/week on Aug 2018"
## [5] "Rent $550/week on Aug 2018" "Rent $730/week on Aug 2018"
## [7] "Rent $510/week on Jul 2018" "Rent $480/week on Jul 2018"
## [9] "Rent $520/week on Jul 2018" "Rent $630/week on Jul 2018"
## [11] "Rent $630/week on Jul 2018" "Rent $700/week on Jul 2018"
呜哇!我们有 12 个地址的 12 组数据。我们可以很容易地使用更多的正则表达式来提取每月和每周的租金。我将向你展示我是如何做到的,但是试着像我上面做的那样分解它,所有那些符号会显得不那么令人生畏。首先,提取月份…
str_extract(price_month, '[A-Z][a-z]{2} \\d{4}$') %>%
head(5)## [1] "Aug 2018" "Aug 2018" "Aug 2018" "Aug 2018" "Aug 2018"
…然后是每周租金:
str_extract(price_month, '(?<=Rent \\$).*(?=/week)') %>%
head(5)## [1] "420" "510" "490" "500" "550"
目标:属性配置
我们开始想要分析与我的公寓相似的公寓。也就是说,我们想要分析有 2 间卧室、1 间浴室和 1 个停车位的公寓。查看搜索结果可以发现,我们需要考虑两种情况:
- 大多数房产至少有一间浴室和一个停车位,所以我们有 3 个数字——卧室数量、浴室数量和停车位数量。
- 有些酒店没有停车位。所以我们有两个数字——卧室的数量,后面是浴室的数量。
我想捕捉这两种模式,这样我就有 12 套公寓配置,它们可以很容易地与 12 个地址、月和周租金组合在一起。一旦它们被组合成一个数据框,我就可以很容易地过滤掉那些不符合我的目标公寓配置的公寓。
尝试将下面的正则表达式翻译成简单的英语:
first_page %>%
html_nodes('li') %>%
html_text() %>%
str_extract(' \\d \\d (\\d )*$') %>%
str_trim() %>%
.[which(!is.na(.))]## [1] "2 1 1" "2 1 1" "2 1 1" "2 1 1" "2 1 1" "2 2 1" "2 1 1" "2 1 1"
## [9] "2 2 1" "2 2 1" "2 2 1" "2 2 1"
像 Voltron 这样的表单:创建我们的最终数据集
那么,我们学到了什么?
- 我们知道前 n 页的 URL 是什么。
- 我们知道如何从这些页面中提取感兴趣的数据。
在分析我们的数据之前,我们需要做的就是编写一个循环,遍历公寓的 n 个页面,同时将每个页面的数据追加到某个主数据集。然后,我们将这个主数据集子集用于匹配我们期望的公寓配置的公寓。描述这个过程不是本文的重点,所以我将在本文的最后提供我的最终代码。
亲爱的房地产经纪人…
两室一卫一车位公寓的周租金在几个月内变化很大。
导致这种情况的一些可能原因如下:
- 新公寓的租金比旧公寓贵——快速浏览一些更贵公寓的照片可以发现,它们位于火车站附近新建的公寓里。
- 离火车站和购物区较近的公寓比离这些较远的公寓租金更贵。
我的公寓很旧了,离火车站大约 10 分钟的路程。这绝不是例外,所以我觉得一个“典型”的价格最能描述我公寓的“真实”周租金。所以我尝试了一些平滑的方法。
我个人喜欢通过 ggplot 的 geom_smooth()使用黄土。
然而,我不想向我的房地产经纪人解释黄土是如何工作的。所以我决定采用季度租金中值。不是取个平均值那么简单。但我认为,考虑到异常值,中位数是合适的,如果有人问我对统计数据的选择,这很容易解释。
所以我写了一封邮件:
1.去年,租金每周上涨 20 美元,这似乎超过了当时的市场价格(更多信息见下文)。
2.我自己对数据进行了审查,发现我们目前支付的租金是合理的:
*我使用 webscraping 收集了 2016 年 1 月至 2017 年 8 月在阿什菲尔德新租的 346 套“两室一卫一车位”公寓的数据。租金从旧公寓每周约 400 美元到全新公寓每周 600 多美元不等。
*自 2017 年 1 月以来,租金中位数似乎一直徘徊在 500 美元以上或略低于 500 美元的水平(请参见下图)。事实上,这一时期每周租金的中位数是 495 美元。
*我已将此与最新的新南威尔士州房屋租赁和销售报告进行了交叉核对。阿什菲尔德一套两居室公寓上个季度的租金中值是 500 美元。中位数略高于我的数字是有道理的,因为新南威尔士州的住房数据将包括拥有不止一个浴室或不止一个停车位的公寓。
*去年我们的租金提高到每周 500 美元时,中位数价格徘徊在每周 480 美元左右。我已经将此与新南威尔士州 12 月份的房屋租赁和销售报告进行了交叉核对,并可以确认这是准确的。
故事的寓意:数据是强大的
这封邮件我一直没有收到回复。相反,我收到了一份未来 12 个月每周租金相同的合同!
数据是强大的,所以要学会如何使用它。去存点钱吧,伙计们!
贾斯廷
原载于 2018 年 9 月 1 日【https://embracingtherandom.com】。
用语境化的单词向量代替你的单词嵌入
“high-rise buildings” by Micaela Parente on Unsplash
受 Mikolov 等人(2013)和 Pennington 等人(2014)的影响,单词嵌入成为初始化 NLP 项目的基本步骤。之后又引入了很多嵌入如LDA 2 vec(Moody Christopher,2016)字符嵌入,doc2vec 等等。今天,我们有了新的嵌入,即语境化的单词嵌入。这种想法是相似的,但他们实现了相同的目标,即使用更好的单词表示来解决 NLP 任务。
看完这篇帖子,你会明白:
- 语境化的词向量设计
- 体系结构
- 履行
- 拿走
语境化的词向量设计
“white sand beach under white sky” by Itchy Feet on Unsplash
受 CNN 的启发,McCAnn 等人专注于训练编码器,并将其转换为其他任务,以便可以利用更好的单词表示。不使用 skip-gram (Mikolov 等人,2013 年)或矩阵分解(Pennington 等人,2014 年),而是利用机器翻译来构建上下文化的词向量(CoVe)。
假设机器翻译(MT)足够通用以捕获单词的“含义”,我们建立一个编码器和解码器架构来训练 MT 的模型。之后,我们将编码器层“转移”到其他 NLP 任务(如分类问题和问题回答问题)中转移单词向量。
McCann B., Bradbury J., Xiong C., Socher R. (2017)
图 a 显示了如何为机器翻译训练模型。给出单词向量(例如 GloVe ),以便我们可以从模型中获得上下文向量(CoVe)。
体系结构
McCann B., Bradbury J., Xiong C., Socher R. (2017)
图 b 显示了重用结果 a 中的编码器并将其应用于其他 NLP 问题。
McCann B., Bradbury J., Xiong C., Socher R. (2017)
如图 b 所示,“特定任务模型”的输入是单词向量(例如 GloVe 或 word2vec)和编码器(即来自 MT 的结果)。因此,McCann 等人引入了上述公式来获得新词嵌入(串联 GloVe(w)和 CoVe(w))。
实现
在此之前,您需要安装相应的库(从 CoVe github 复制):
git clone https://github.com/salesforce/cove.git # use ssh: git@github.com:salesforce/cove.git
cd cove
pip install -r requirements.txt
python setup.py develop
# On CPU
python test/example.py --device -1
# On GPU
python test/example.py
如果您在“pip install-r requirements . txt”上遇到问题,您可以用以下命令替换它
conda install -c pytorch pytorch
pip install -e git+[https://github.com/jekbradbury/revtok.git#egg=revtok](https://github.com/jekbradbury/revtok.git#egg=revtok)
pip install [https://github.com/pytorch/text/archive/master.zip](https://github.com/pytorch/text/archive/master.zip)
如果用 Keras (Tensorflow),可以按照这个笔记本建 CoVe。但是,在原来的笔记本上有一些问题,你可以看看我修改的版本作为参考。问题在于原始凹穴(pytorch 将层名称从“rnn”更新为“rnn1”)。预训练模型(下载 Keras_CoVe.h5)也可用。
另一方面,你也可以使用预先转换的 Keras 版本。
# Init CoVe Model
cove_model = keras.models.load_model(cove_file)# Init GloVe Model
glove_model = GloVeEmbeddings() glove_model.load_model(dest_dir=word_embeddings_dir, process=False)# Encode sentence by GloVe
x_embs = glove_model.encode(tokens)# Encode GloVe vector by CoVe
x_embs = cove_model.predict(x_embs)
拿走
要访问所有代码,可以访问这个 github repo。
- CoVe 需要标签数据来获得上下文单词向量。
- 用手套建造洞穴
- CoVe 无法解决 OOV 问题它建议使用零向量来表示未知单词。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
放大图片作者:Michael b …在翻译中学习:语境化的词向量。2017.http://papers . nips . cc/paper/7209-learned-in-translation-contextualized-word-vectors . pdf
py torch 的小海湾(原文)
神经网络的表示能力
我们知道神经网络及其在从数据科学到计算机视觉等多个领域的无数成就。众所周知,他们擅长解决涉及概括的复杂任务。从数学上来说,它们非常擅长于逼近任何复杂函数的行为。让我们直观地理解这种近似的概念,而不是预测误差最小化的向前和向后传播方法。假设您了解前向和后向传播的一些基本知识,前向和后向传播旨在借助梯度和网络中的误差传播来近似函数的行为。让我们用另一种视觉解释来理解神经网络的近似能力。涉及基础数学和图形分析。
从数学上讲,我们将着眼于给定神经网络对于所提供的要近似的函数的表示能力。
表示能力与神经网络将适当的标签分配给特定实例并为该类创建良好定义的精确决策边界的能力相关。在本文中,我们将探索一种视觉方法来学习更多关于神经网络的近似行为,这与神经网络的表示能力直接相关。
旅程
这都是从 MP 神经元开始的,这是一个非常简化的神经元模型。对于一个给定的函数,只要所有输入的总和大于阈值,神经元就会触发,否则就不会触发。非常原始的开始。为了检验它的表示能力,让我们看一个几何解释。首先用 2 个输入进行二维分析,以近似 or 函数,然后再用 3 个输入进行三维分析。
For separation in a 2-D coordinate system a line is required. The neuron will fire for points right to the line. Hence, a separation boundary created.
For separation in 3-D coordinate system a plane is required. Neuron will fire for all points above the plane.
因此,麦卡洛克皮茨神经元可以用来表示任何线性可分的布尔函数
。此外,我们可以看到一个严格的划分规则,而不是一个渐进的决策边界,任何略高于分离边界的内容都称为 1 ,略低于分离边界的内容称为 0 。神经元触发类似阶跃函数的行为。使用感知器可以获得更大的灵活性,感知器的每个输入都有权重,但仍然存在严格的界限。但是,上述机制不适用于非线性可分函数。一个非常简单的例子是 XOR,想象一下在二维平面上为这个函数画一条分隔线。不会有了!与 XOR 非常相似,大多数数据在本质上都是线性不可分的。
因此,需要像当前神经网络这样的高级计算模型来为这些功能创建分离的边界。只是看到一个基本的插图,其中有一个隐藏层和一些预定义的权重,复制异或函数。
Conditions for implementation of XOR: w1<w0, w2≥w0, w3≥w0, w4<w0
**记住:**任何输入为 n 的布尔函数都可以用一个感知器网络来表示,这个网络包含一个带有 2^n 感知器的隐藏层和一个包含 1 个感知器的输出层。这是一个充分条件,不是必要条件。
通过我们对单隐层网络的阶跃函数近似分析。它有局限性,其苛刻的判断标准相当于一个阶跃函数。让我们深入研究具有 s 形非线性近似函数的多层深度网络。
今日故事
s 形神经元的表达能力要高得多。具有单个隐藏层的多层神经元网络可以用来以任何期望的精度逼近任何连续函数。
数学上有一个保证,对于任意一个函数 f(x): R(n) → R(m),我们总能找到一个隐层/s 的神经网络,它的输出 g(x)满足| g(x)—f(x)|< Θ
The above claim is 性质上相当大的。因为这意味着我们可以用一个给定的神经网络来逼近任何函数。在数学术语中,通用逼近定理陈述了在激活函数的温和假设下,具有包含有限数量神经元的单个隐藏层的自动编码器网络可以逼近 R(n) 的紧致子集上的连续函数。因此,该定理指出,当给定适当的参数时,简单的神经网络可以代表多种功能。然而,它没有触及这些参数的算法收敛性。收敛部分与前向和后向传播算法有关。让我们来理解对上述定理的直观解释,它作为神经网络中学习行为的基本基础。
Geometric Interpretation of Function Approximations. Classical mathematical approach in Numerical Approximation.
最终游戏:Sigmoids 塔
继续上述用神经网络逼近函数的讨论。看看下面的图表,自己决定吧。一个函数可以用几个塔函数叠加**来近似。**该过程将形成一个形状,该形状相当于给定函数被近似,其中有一些微小的近似误差。现在,通用逼近定理的上述解释告诉我们,我们用于逼近的塔的数量越多,逼近行为越好。因此,在 s 形激活中调整参数,目的是创建这样的近似塔。按照这种解释,理论上对神经网络的准确性没有限制。
Clearly, more the number of towers better the approximation & lesser the approximation error.
让我们更深入地研究这个解释过程。所有这些“塔”功能都是相似的,只是在 x 轴上的高度和位置不同。现在,我们必须看看这些塔是如何用 sigmoid 激活函数创建的。
Our aim is to figure out the black-box Tower Maker for tower construction.
典型逻辑 sigmoid 激活函数方程如下所示。
w: represents weights | b: represents bias
随着 w 的增加,函数变得更加陡峭,就像阶跃函数一样。 b 的正值越大,曲线从原始曲线向左移动。
因此,通过改变这些值,我们可以创建不同版本的 sigmoids,我们可以将它们相互叠加,以获得类似塔的结构。为了在二维坐标系中创建塔,减去具有两个不同偏差值的曲线。
Left curve is having more positive value of bias b. Hence, with multiple such towers above random curve can be approximated or represented.
我们可以将这种操作扩展到神经网络的隐藏层,以构建模拟这种曲线减法行为的神经网络。因此,神经网络可以用权重和偏差的参数值来表示任何这样的函数,我们用我们的前向和后向传播算法连续确定这些参数值,直到达到收敛标准。
Now, the above illustrated random curve of a function can be approximated by superimposing such towers.
个案研究
考虑具有多个输入的场景。假设我们正试图决定是否会在海底的特定位置找到石油。此外,假设我们的决定基于两个因素:盐度(x1)和压力(x2)。给我们一些数据,似乎 y(oil|no-oil)是 x1 和 x2 的复变函数。我们想要一个神经网络来近似这个函数。
Illustration above plots the above scenario. Clearly, we need 3-D towers which approximates the distribution function.
在我们的理解中,我们需要在三维坐标系中制作这样的三维封闭塔。如果我们进行上述在三维空间中具有不同偏差的两个 sigmoids 相减的类似方法。我们将得到下面的等价曲线。
We still didn’t get a closed tower.
但是,我们可以看到,如果我们采取另一个水平垂直塔电流合成曲线以上。将这两个水平垂直的开放塔叠加起来,我们可以得到封闭塔。
我们可以通过另一个组合 sigmoid 激活函数来传递上述输出,以获得最佳近似的适当塔。
We can now approximate any function by summing up many such
towers
在多个这样的塔的帮助下,可以重建上述案例研究中的复杂分布函数。这里,让我们看一个神经网络来代表上述程序。
我们刚刚看到的说明性证明告诉我们,我们可以有一个具有两个隐藏层的神经网络,它可以通过一些塔来近似上述函数。这意味着我们可以有一个神经网络,它可以像上面案例研究中提到的那样准确地分离这种分布。对神经网络的精确度没有理论上的限制。
我们感兴趣的是把蓝点和红点分开。对于单个 s 形神经元,显然会存在误差。但是,有了两个隐藏层,我们可以用一组塔来近似上述函数。我们可以有一个神经网络,可以准确地将蓝点和红点分开!!
承认
近似的可视化方法是非常独特和有趣的,这就是为什么我觉得有必要进行这次讨论。我只是重组了 neuralnetworksanddeeplearning.com 已经存在的解释。描述性插图借用自深度学习课程 CS7015。感谢 Mitesh M. Khapra 教授和他的助教们的精彩课程!!
可再生研究:星际采矿
Troop movements in StarCraft
2009 年,我发表了一篇关于使用不同分类算法预测《星际争霸:繁殖战争》建造顺序的论文。我把 T2 的数据集 T3 提供给其他研究人员测试,一些 T4 的学术项目 T5 已经使用了这个数据集。然而,我从来没有为实验提供源代码,最终丢失了它,类似于暴雪和最初的星际争霸的源代码。自从转行到游戏行业,我开始倡导我的同事建立可重复的研究。这意味着编写输出结果的代码,删除手动步骤,并使用可以在不同机器和平台上重现的环境。
自从宣布星际争霸重制版和谷歌的 DeepMind 应用于星际争霸 2 以来,人们对星际争霸人工智能的研究又有了新的兴趣。自从我第一次发表这项研究以来,近十年过去了,我很好奇我是否可以重现这个实验,看看最近的技术,如 XGBoost 是否会优于我之前测试的分类算法。
初始设置 我对这些实验的初始设置是 Java 代码和 Weka 库的混合。我首先使用交互式 Weka GUI 测试了不同的分类器,然后当我想要运行实验时,就切换到使用 Weka API。我的 Java 脚本会运行实验并将结果输出到文本文件中,在制作图表时,我会手动将这些文本文件复制到 excel 中。我在我的 Windows 笔记本电脑和大学的 Unix 服务器上都进行了实验。
Protoss vs. Terran Build Order Prediction
我想重现的关键实验是预测对手在游戏中不同模拟时间的建造顺序。我的论文中的这个实验的输出如上所示。随着不同的算法获得更多的信息,它们在识别对手的建造顺序方面变得更好。这 1000 多个回放被标记为 6 个不同的构建顺序,我标记构建顺序的方法在本文中有更详细的介绍。
新脚本 我的以可重复的方式运行这个实验的新方法是使用 R Markdown ,这是一种可以嵌入 R 代码和可视化的 Markdown 语言。这种方法的目标是在运行实验时消除所有手动步骤。markdown 脚本从 github 下载必要的数据文件,运行实验,并将结果呈现为 pdf 文档或 html 文件。脚本在这里可用,结果在 pdf 和 html 格式可用。该脚本的输出之一如下图所示。
Reproduced Experiment for Protoss vs Terran Build Order prediction
该脚本直接从 Github 加载神族对人族建造命令的数据帧。这消除了在本地复制实验文件的需要。
df <- read.csv("https://github.com/bgweber/StarCraftMining/
raw/master/data/scmPvT_Protoss_Mid.csv")
实验从 12 分钟的游戏时间开始,然后后退以模拟游戏过程中不同的时间步长。我使用这种方法来避免多次重新加载数据框。下面的片段显示了数据帧( df )如何被过滤到特定的比赛时间(帧)。
for (i in colnames(df)) {
if (i != 'label') {
index <- df[i] > frame
df[i][index] <- 0
}
}
我应用了以下包中的分类器:最近邻( class )、决策树( rpart )、神经网络( nnet )和 xgboost( xgboost )。
predict <- knn(train, test, train$label, use.all = FALSE)
reg <- nnet::multinom(label ~ ., data=train, trace = FALSE)
model<- rpart(factor(label) ~ ., data = train)
bst <- xgboost(data = trainM, label = train$label, ... )
并使用 ggplot2 绘制结果,生成上图:
ggplot(data=melt(results, id="minutes"), aes(x=minutes, y=value,
colour=variable)) + geom_line() + ...
结果显示,xgboost 在 10 分钟的游戏时间内,以 96%对 94%的准确率,确实优于论文中性能最好的算法 LogitBoost 。然而,在早期游戏中最近邻方法优于其他分类器的最初发现仍然存在。
该脚本还生成了第二个图表,这是游戏开始 8 分钟时不同特性的重要性。这是一种我在原始论文中没有包括的分析,但在这里包括是有趣的,因为它显示了球员在侦察对手时应该注意什么。基于训练好的模型,特征的重要性随着时间而变化。下面的可视化是使用 xgboost 函数 xgb.importance 和 xgb.plot.importance 生成的。
Feature importance at 8 minutes game time identified by xgboost
新环境 我在我的 Windows 笔记本电脑上写了 R Markdown 脚本进行测试。为了使实验在不同的机器和环境中可重复,我使用了 Docker 。我从 CentOS 映像开始,安装 R,设置库和其他依赖项,如 pandoc,然后运行脚本,输出一个带有可视化效果的 html 文件。我使用 Amazon Linux 实例在 AWS 上构建了一个 EC2 实例,并运行了下面的命令。以下部分突出显示了一些命令:
# install and start docker
sudo yum -y install docker
sudo service docker start# get the centos image, and start it in interactive mode
sudo docker pull centos
sudo docker run -t -i centos /bin/bash# install R, which requires updating the repo
yum -y install R# install required R packages
R -e "install.packages('caTools', repos='[http://cran.us.r-project.org'](http://cran.us.r-project.org'))"
...# download the RMD file
wget [https://github.com/bgweber/StarCraftMining/SC_Data_Mining.Rmd](https://github.com/bgweber/StarCraftMining/raw/master/SC_Data_Mining.Rmd)# run the script!
Rscript -e "rmarkdown::render('SC_Data_Mining.Rmd')"
对于这个例子,我在交互模式下运行容器。如果我想在将来持久化运行实验的环境,我将创建并应用一个 docker 文件,并将结果图像保存到 docker 注册表中。这将确保对 R 库或其他依赖项的更改不会影响实验环境。
结论 如果我今天要重写这篇研究论文,我会推荐使用让实验可重复的工具。使用 R Markdown 和 Docker 是帮助实现这个目标的一种方法。
数据科学教学研究
我写这篇文章是作为 2018 年春天在斯坦福大学参加 Hadley Wickham 应用数据科学课程阅读的一部分。
介绍
随着数据科学技能变得越来越重要,数据科学的教学也变得越来越有价值。在数据科学的背景下,我认为教学不是在白板上交谈或给工作表评分的传统过程,而是创造环境和设计体验的过程,这种过程可以为学生带来可衡量的学习。
就定义而言,我对培养学生从数据中提取价值的能力感兴趣(我称之为数据科学)。我感兴趣的学生是任何有算术背景的人,不需要额外的培训,比如说,代数,但不一定有编程或任何级别的严肃统计的背景。
美国统计协会建议
美国统计协会(ASA)已经认识到,随着形势的变化,有必要对培训进行调整。2005 年,他们首次提出了关于介绍性统计未来方向的建议,并在 2016 年再次更新了这些建议(ASA 2016)。他们的目标是在大学教授统计学导论,但其中包含的智慧也适用于任何环境下的数据科学教学。以下是他们的建议(第 3 页):
- 教授统计思维。
- 注重概念理解。
- 将真实数据与上下文和目的相结合。
- 培养主动学习。
- 利用技术探索概念和分析数据。
- 使用评估来改进和评估学生的学习。
这些建议中的大部分只是一般的好教学。例如,最近有大量的教育研究指出了主动学习的显著的可测量的益处(C. E. Wieman 2014Koedinger 等人 2015)。还值得指出的是,一些学者认为这些建议指向正确的方向,但仅仅这样还不够(G. Cobb 2015)。
在任何情况下,ASA 建议的关键是批判性思维或决策。Holmes,Wieman 和 Bonn (2015)将批判性思维定义为“基于数据做出决策的能力,及其固有的不确定性和可变性”(第 1 页)。ASA 没有就如何培养学生的批判性思维提供任何明确的指导,但 Holmes,Wieman 和 Bonn (2015)提供了非常简单的建议:“发展这种能力的关键因素是反复练习根据数据做出决定,并对这些决定进行反馈”(第 1 页)。
数据科学教学中尚未解决的问题
ASA 的建议和教育研究提供了一些显而易见的建议,如让学生在用技术分析真实数据的同时主动学习;当引入新思想时,注重概念理解,而不是死记硬背;并通过评估来衡量学生的学习。那么,教学数据科学的困难或未解决的部分是什么?我认为有三个:第一,建立一个有利于学习的社会环境或文化;第二,选择技术和设计学习活动,要求学生做出决定;第三,测量或评估学习。
1)创造文化
建立一个让学生自由地展示他们自己的知识状态并同情地互相帮助学习的环境是非常困难的。增长思维模式的想法首先由卡罗尔·德韦克提出(德韦克和 Sumoreads 2017)。Jo Boaler 特别在数学课堂的背景下讨论了成长思维模式,并恰当地将其称为“数学思维模式”(Boaler 2016)。他们的研究指出了学生相信他们可以通过实践提高的重要性。或许更有趣的是,他们提供了如何培养成长心态的建议,比如赞扬努力而不是技能(Khan 2014)。
我喜欢“数据科学思维”的想法建立这样一种心态尤其重要的是让学生进行批判性思考,并作为一个群体做出决定。为了有效地做到这一点,学生们需要在社交上彼此特别自在。人类可能是害羞的动物。创造环境来克服这种趋势,让学生们彼此深入交流,分享想法,并富有成效地挑战彼此的想法是极其困难的。
我见过的实现这个目标的最接近魔术的方法是即兴表演。从我的经验来看,学生们可以害羞和不自信地进入一个房间,几个小时后通过一起即兴表演,彼此之间完全舒服了。《第二城市课堂即兴表演指南》一书详细介绍了课堂即兴表演的好处以及具体的活动建议(McKnight 和 Scruggs 2008)。这些技术可以很容易地适应数据科学环境,例如,让学生作为一个小组表演一个函数做什么,让学生在遇到错误时热情地大喊“耶”,或者要求学生在头脑风暴如何解决数据科学问题时以“是的,并且…”开始句子。这些想法可能会让一些人觉得很傻,但实际上这是最基本的要素。
教师经常忽略有目的地建设文化。在我看来,没有比这更大的错误了。投资课堂文化,尤其是在开始阶段,会带来巨大的回报。如果一个老师没有明确地构建文化,课堂的文化很可能会变得类似于课堂之外的“真实世界”的文化,这对于来自往往在分析圈子中被边缘化的背景的学生来说尤其有害。从本质上说,建设文化既是一个公平和有效性的问题(P. Cobb 和 Hodge 2011)。
2)选择技术和设计学习活动(要求学生做出决定)
学习技术的选择归结为管理一门课程的能量。如果精力花在学习技术的细节上,那么用于其他主题的精力就会减少。然而,认识到一些学习技术比其他技术对学生来说更有价值也很重要。例如,使用 R(相对于特定用途的学习小程序)可能会为课程带来更高的成本,但在课程结束后对学生也有更大的潜在价值。
在使用激励视频、真实数据和免费软件学习统计数据时,Harraway (2012)提倡使用 GenStat 软件进行教学(GTL ),这是专业软件 GenStat 14 的淡化版本。GTL 旨在占据电子表格和高级数据分析软件之间的中间地带,完全由菜单驱动,专注于基本统计需求的易用性,如转换数据、模型拟合、假设检验和引导。创作者通过在几个教室试用该软件,然后观察和调查结果来衡量该软件的有效性——例如,在 41 名学生中,只有 6 名学生认为 GTL 很难使用。GTL 也有与其特色直接相关的学习活动和视频。
Harraway (2012)承认 R 是 GTL 的最大竞争对手,但不断强调不必要的复杂性和因需要编程和语法而导致的挫折感。我发现这是这篇论文提出的最有趣的问题。使用专业软件,消除初学者的复杂性,设计有目的的学习活动似乎是一个好主意,但我很难接受基于菜单是必需的甚至是可取的功能这一论点。我之前认为,对于所有学生来说,与基于语法的程序进行互动是一个很好的练习,并且通过良好的课程设计和教学,可以使这种互动变得不那么痛苦。无论如何,为学习者特别设计的轻量级软件的基本点是有趣的。
在 FiveThirtyEight R Package:统计学和数据科学入门课程的“驯服数据”原则中,Kim、Ismay 和 Chunn (2018)没有描述如何使软件变得更简单,而是倡导以一种要求学生专注于重要障碍的方式驯服数据。例如,首先以整齐的格式提供数据,这样学生就不必担心数据的整形。他们将这一建议付诸行动,提供了一个记录良好的 R 包,其中包含来自数据驱动的新闻网站 FiveThirtyEight 的数据集。
他们的基本原则是,学生需要学习数据科学的“整个游戏”,而不是一次只学习一个孤立的部分,但通过将学生抛入深渊来这样做是适得其反的,因为学生经常会在低收益概念或他们尚未准备好的概念上打转。因此,解决方案是基于有目的地策划的数据来设计学习体验,让学生体验数据科学的整个游戏,并在正确的时间遇到正确的障碍(例如,富有成效的斗争)。我认为这正是数据科学教师应该持有的正确心态。非常困难的部分是设计数据集和这种目的水平的学习体验。提供的 R 包是一个好的开始。
关于数据科学教学技术的第三篇论文是使用 R 和 Shiny 的统计数据 Web 应用教学工具(Potter 等人,2016 年)。他们指出,小程序可以成为强大的教学工具,尤其是帮助学生建立直觉。然而,构建小程序需要专业技术知识和大量的时间。Shiny 大大简化了这个过程。这篇论文附带了一个网站,展示了各种令人印象深刻的小程序。
相对于课程中使用的主要软件,小程序似乎有些不重要,但我实际上认为教师为他们的教室设计闪亮的应用程序可能非常有价值,特别是如果与深思熟虑的驯服数据练习相结合。想象一下,一个学生处理一个平淡无奇的数据分析,但是在这个过程中遇到了令人毛骨悚然的统计概念,有一个专门为数据分析设计的小程序可以帮助学生建立统计直觉。这可能非常强大。
总之,我在关于数据科学的技术使用和活动设计的文献中看到的最大差距是没有足够重视实际要求学生做出决定。不要问学生某人准时上班的概率有多大,而是问他们建议这个人什么时候离开。不要问学生治疗效果如何,如果有不同的效果,问他们会把药物给谁,有一百万美元的固定预算。
然后对过程和决策给出反馈。例如:
你的团队把药给了年轻男性而不是年长女性,因为你没有正确解释选择偏差。10 名年轻男子被治愈,但机会成本是 1000 名老年妇女的生命。您应该在回归中控制邮政编码,而不是州。也许您忽略了这一点,因为您在清理数据时没有将地理变量放在一起(参见第一个脚本的第 22 行)。”
想象一下这与通常的反馈有多么不同:
“你对异质效应的估计似乎是错误的,也许是因为你没有正确解释选择偏差。”
我的观点是,高质量数据科学活动的重要部分是提出专注于决策和设计活动的问题,以便学生遇到重要的障碍,而学生没有准备好面对的障碍则通过仔细的数据整理被离散地消除。老师还需要深入理解数据的每一个细节,以便他们能够快速识别学生的位置,并引导他们朝着正确的方向前进。真实世界的数据当然是首选,但如果这需要使用感觉真实的模拟数据,我认为这也没问题。
3)测量/评估学习
数据科学是关于决策的,而决策是很难衡量的。机器可分级的格式似乎并不奏效,而且替代方案非常耗时且主观。此外,理想的数据科学学习成果通常是长期的,与学生对数据科学的关系和实际掌握技能一样重要。考虑到这一点,也许课程调查和收集学生信心和情绪的数据与传统的教育评估一样有价值(Wirth and Perkins 2005)。
总之,在有效测量和评估数据科学学习的道路上,我们还有很多山要爬。Maurer 和 Lock (2016)提供了一个有趣的起点,他们将爱荷华州立大学的学生随机分配到基于模拟或传统的推理课程中,并比较学生在针对特定学习目标的问题上的前后测试收获。类似的例子见于 C. Wieman 和 Holmes (2015 年)。一个有希望的未来方向是考虑项目评估,它从更广阔的角度来衡量。Moore 和 Kaplan (2015)通过评估佐治亚大学本科统计学专业提供了一个例子。
文献学
- 阿萨。2016."统计教育评估和指导指南-学院报告."http://www . amstat . org/asa/files/pdf/GAISE/GAISE college _ full . pdf。
- Boaler,J. 2016。“数学思维。”加利福尼亚州旧金山:乔西-巴斯。
- 科布乔治。2015.“单纯的革新太少也太迟了:我们需要从头开始重新思考我们的本科课程。”美国统计学家 69④。泰勒和弗朗西斯:266–82。
- 科布,保罗,林恩廖霍奇。2011.“数学课堂中的文化、身份和公平.”《数学教育研究之旅:保罗·科布作品中的洞见》, Anna Sfard,Koeno Gravemeijer 和 Erna Yackel 编辑,179–95 页。多德雷赫特:荷兰施普林格。
- 德韦克,卡罗尔 s,和 Sumoreads。2017.卡罗尔 s .德韦克的心态总结:关键要点与分析。创建空间独立发布平台。
- 约翰·哈罗维,2012 年。"使用激励视频、真实数据和免费软件学习统计学."统计教育中的技术创新 6 (1)。https://escholarship.org/uc/item/1fn7k2x3。
- N. G .福尔摩斯卡尔·E·威曼和波恩地方检察官。2015.“教授批判性思维。”美国国家科学院院刊 112(36):11199–204。
- 可汗萨尔。2014."学习神话:为什么我永远不会告诉我的儿子他很聪明."可汗学院。2014.https://www . khanacademy . org/talks-and-visitors/conversations-with-sal/a/the-learning-myth-why-ill-never-tell-my-son-hes-smart。
- 金、艾伯特·y、切斯特·伊斯梅和詹妮弗·楚恩。2018." FiveThirtyEight R 包:统计学和数据科学入门课程的“驯服数据”原则."统计教育中的技术创新 11 (1)。【https://escholarship.org/uc/item/0rx1231m】T4。
- Koedinger,Kenneth R .,Jihee Kim,Julianna 祝新贾,Elizabeth A. McLaughlin 和 Norman L. Bier。2015."学习不是一项观赏性运动:从 MOOC 中学习,做比看更好."第二届(2015 年)ACM 学习会议论文集,第 111-20 页。L@S '15。美国纽约州纽约市:ACM。
- 毛雷尔,卡斯滕和丹尼斯·洛克。2016."在一个设计的教育实验中,基于模拟和传统推理课程的学习结果的比较."统计教育中的技术创新 9 (1)。https://escholarship.org/uc/item/0wm523b0。
- 麦克奈特,凯瑟琳 s 和玛丽斯克鲁格斯。2008.第二城市课堂即兴表演指南:利用即兴表演教授技能和促进学习。约翰·威利父子公司。
- 摩尔、艾莉森·阿曼达和詹妮弗·j·卡普兰。2015."本科统计学专业的项目评估."美国统计学家 69④。泰勒和弗朗西斯:417–24。
- 波特、盖尔、黄谷悦、欧文·阿尔卡拉斯、彼得·池等人。2016." Web 应用统计教学工具使用 R 和 Shiny . "统计教育中的技术创新 9 (1)。https://escholarship.org/uc/item/00d4q8cp。
- 斯特恩丹。2017.“自学数据科学:我用来在 Jet.com 获得分析工作的学习途径”,2017 年。https://medium . freecodecamp . org/a-path-for-you-learn-analytics-and-data-skills-BD 48 ccde 7325。
- 斯塔滕,萨维纳·范德。2017.“离开我的风投工作,去学习数据科学和机器学习。”2017.https://towards data science . com/leaving-my-VC-job-to-learn-about-data-science-and-machine-learning-4 DBC 15427 fc 5。
- 卡尔·威曼,2014 年。"科学教学方法的大规模比较传达了明确的信息."美国国家科学院学报 111(23):8319–20。
- 威曼、卡尔和 N. G .霍姆斯。2015."测量物理入门实验室对学习的影响."arXiv[物理学博士]。arXiv。http://arxiv.org/abs/1507.00264。
- 沃思,卡尔 r,和德克斯特帕金斯。2005."知识调查:不可或缺的课程设计和评估工具."教与学的学术创新。serc.carleton.edu。http://serc . carleton . edu/files/garnet/knowledge _ surveys _ indepensabl _ 1313423391 . pdf。
剩余块 ResNet 的构建块
理解一个剩余块是相当容易的。在传统的神经网络中,每一层都反馈到下一层。在有剩余块的网络中,每一层都馈入下一层,并直接馈入大约 2-3 跳之外的层。就是这样。但是,理解为什么首先需要它,为什么它如此重要,以及它看起来与其他一些最先进的架构有多么相似,这是我们要关注的地方。关于残差块为什么如此棒,以及它们如何&为什么是可以使神经网络在广泛的任务中表现出最先进性能的关键思想之一,有不止一种解释。在深入细节之前,这里有一张残余岩块的实际样子的图片。
Single Residual Block. (img src)
我们知道神经网络是通用的函数逼近器,并且精度随着层数的增加而增加。但是导致精度提高的增加的层数是有限的。因此,如果神经网络是通用函数逼近器,那么它们应该能够学习任何简单或复杂的函数。但事实证明,由于一些问题,如消失梯度和维数灾难,如果我们有足够深的网络,它可能无法学习像身份函数这样的简单函数。这显然是不可取的。
此外,如果我们不断增加层数,我们会发现精度会在某一点饱和,最终会下降。并且,这通常不是由于过度配合造成的。因此,看起来较浅的网络比较深的网络学习得更好,这是非常违背直觉的。但这是在实践中看到的,通常被称为退化问题。
没有根导致退化问题和深度神经网络无法学习身份函数,让我们开始考虑一些可能的解决方案。在退化问题中,我们知道较浅的网络比添加了几层的较深的网络表现得更好。那么,为什么不跳过这些额外的层,至少匹配浅层子网的精度。但是,如何跳过层呢?
可以使用跳过连接或剩余连接跳过几层的训练。这就是我们在上图中看到的。事实上,如果你仔细观察,我们可以只依靠跳过连接直接学习一个恒等式函数。这就是为什么跳过连接也被称为标识快捷连接的确切原因。所有问题的一个解决方案!
但为什么称之为残余呢?残渣在哪里?是时候让我们内心的数学家浮出水面了。让我们考虑一个神经网络块,它的输入是 x,,我们想知道真实的分布 H(x) 。让我们将这两者之间的差(或残差)表示为
*R(x)* = Output — Input = *H(x)* — *x*
重新排列,我们得到,
*H(x)* = *R(x)* + *x*
我们的残差块总体上试图学习真实输出, H(x)。如果你仔细观察上面的图像,你会意识到,既然我们有一个来自 x 的身份连接,那么这些层实际上是在试图学习剩余的, R(x) 。总而言之,传统网络中的各层正在学习真实输出( H(x) ),而残差网络中的各层正在学习残差( R(x) )。因此得名:残块。
还观察到,学习输出和输入的残差比只学习输入更容易。作为一个额外的优势,我们的网络现在可以通过简单地将残差设置为零来学习身份函数。如果你真正理解反向传播,以及随着层数的增加,梯度消失的问题变得有多严重,那么你可以清楚地看到,由于这些跳跃连接,我们可以将更大的梯度传播到初始层,这些层也可以像最终层一样快速地学习,使我们能够训练更深的网络。下图显示了如何为最佳梯度流排列剩余块和标识连接。已经观察到,批量标准化的预激活通常给出最好的结果(即,下图中最右边的剩余块给出最有希望的结果)。
Types of Residual Block. (img src)
除了上面已经讨论过的解释之外,还有更多对剩余块和结果的解释。在训练 ResNets 时,我们或者训练残差块中的层,或者使用跳过连接来跳过这些层的训练。因此,基于误差在网络中如何反向流动,网络的不同部分将以不同的速率针对不同的训练数据点进行训练。这可以被认为是在数据集上训练不同模型的集合,并获得尽可能好的准确性。
跳过一些剩余块层中的训练也可以从乐观的角度来看。通常,我们不知道神经网络所需的最佳层数(或残差块),这可能取决于数据集的复杂性。不是将层数作为一个重要的超参数来调整,而是通过在我们的网络中增加跳过连接,我们允许网络跳过对那些无用的和不增加整体精度的层的训练。在某种程度上,跳跃连接使我们的神经网络动态地在训练过程中优化调整层数。
下图显示了残差块的多种解释。
Different interpretations of Residual Block. (img src)
让我们稍微了解一下跳跃连接的历史。跳过层间连接的想法最初是在高速公路网络中提出的。高速公路网络与控制通过它们的信息量的门有跳跃连接,这些门可以被训练成有选择地打开。在 LSTM 网络中也可以看到这种想法,它控制着网络所看到的过去数据点的信息流量。这些门的工作方式类似于控制来自先前看到的数据点的内存流。下图显示了同样的想法。
Similar to LSTM Block. (img src)
剩余块基本上是高速公路网络的特例,其跳跃连接中没有任何门。实质上,残余块允许内存(或信息)从初始层流向最后一层。尽管在它们的跳跃连接中没有门,剩余网络在实践中表现得和任何其他公路网络一样好。在结束本文之前,下面是所有剩余块的收集如何完成到 ResNet 中的图像。
ResNet architectures. (img src)
如果您有兴趣了解更多关于 ResNet 及其不同变体的信息,请查看这篇文章。
剩余网络
在之前的帖子中,我们看到了深度卷积神经网络的 LeNet-5 、 AlexNet 、 VGG16 的实现。同样,我们可以在理论上建立自己的超过 100 层的深度神经网络,但在现实中,它们很难训练。何、、任和在他们的研究图像识别的深度残差学习中引入了残差网络(ResNets)的概念。ResNets 允许更深的网络有效地训练。
非常深度的神经网络有什么问题?
在训练神经网络的每次迭代期间,所有权重接收与误差函数相对于当前权重的偏导数成比例的更新。如果梯度非常小,那么权重将不能有效地改变,并且它可能完全停止神经网络的进一步训练。这种现象被称为消失梯度。更具体地说,我们可以说,由于非常缓慢的梯度下降,数据正在通过深度神经网络的各层消失。[1]
微软研究发现,将深度网络分成三层块,并将每个块的输入直接传递到下一个块,以及该块的剩余输出减去重新引入的块的输入,有助于消除这种信号消失问题。不需要额外的参数或改变学习算法[1]。换句话说,ResNets 将一个非常深的平面神经网络分解为通过跳过或快捷连接连接的小块网络,以形成一个更大的网络。
ResNets Vs Plain Neural Network
ResNet 中使用两种主要类型的块,主要取决于输入/输出维度是相同还是不同。
a-身份块
标识块是 ResNets 中使用的标准块,对应于输入激活(比如 a[l])与输出激活(比如 a[l+2])具有相同维数的情况。下面是一个标识块的例子,上面的路径是“快捷路径”,下面的路径是“主路径”。
ResNets Identity block
Identity block implementation using keras
b 卷积块
当输入和输出维度不匹配时,我们在捷径路径中添加一个卷积层。这种排列称为卷积块。
ResNets convolutional block
Convolutional block implementation using keras
构建完整的 ResNet 模型(50 层)
现在你已经有了构建一个非常深的 ResNet 所必需的模块。下图详细描述了该神经网络的体系结构。图中的“ID BLOCK”代表“身份块”,而“ID BLOCK x3”意味着您应该将 3 个身份块堆叠在一起。
50 layers ResNets Architecture
上述 ResNet-50 型号的详细信息如下:
- 零填充:用(3,3)填充输入
- 阶段 1:2D 卷积具有 64 个形状为(7,7)的滤波器,并使用(2,2)的步长。它的名字叫“conv1”。BatchNorm 应用于输入的通道轴。最大池使用(3,3)窗口和(2,2)步距。
- 阶段 2:卷积块使用三组大小为 64×64×256 的滤波器,f=3,s=1,块是“a”。这两个单位块使用三组大小为 64×64×256 的滤波器,f=3,块是“b”和“c”。
- 阶段 3:卷积块使用三组大小为 128×128×512 的滤波器,f=3,s=2,块为“a”。3 个单位块使用三组大小为 128×128×512 的滤波器,f=3,块为“b”、“c”和“d”。
- 阶段 4:卷积块使用三组大小为 256×256×1024 的滤波器,f=3,s=2,块为“a”。这 5 个单位块使用三组大小为 256×256×1024 的滤波器,f=3,块是“b”、“c”、“d”、“e”和“f”。
- 阶段 5:卷积块使用三组大小为 512×512×2048 的滤波器,f=3,s=2,块为“a”。这两个单位块使用三组大小为 256×256×2048 的滤波器,f=3,块是“b”和“c”。
- 2D 平均池使用形状为(2,2)的窗口,其名称为“avg_pool”。
- 展平没有任何超参数或名称。
- 全连接(密集)层使用 softmax 激活将其输入减少到类的数量。它的名字应该是’ fc’ + str(类)。
from keras import layers from keras.layers import Input, Add, Dense, Activation, ZeroPadding2D, BatchNormalization, Flatten, Conv2D from keras.layers import AveragePooling2D, MaxPooling2D, GlobalMaxPooling2D from keras.models import Modelfrom keras.initializers import glorot_uniforminput_shape = (64, 64, 3)
classes = 6# Define the input as a tensor with shape input_shape
X_input = Input(input_shape)# Zero-Padding
X = ZeroPadding2D((3, 3))(X_input)# Stage 1 X = Conv2D(64, (7, 7), strides = (2, 2), name = ‘conv1’,)(X) X = BatchNormalization(axis = 3, name = ‘bn_conv1’)(X) X = Activation(‘relu’)(X)X = MaxPooling2D((3, 3), strides=(2, 2))(X)# Stage 2 X = convolutional_block(X, f = 3, filters = [64, 64, 256], stage = 2, block=’a’, s = 1) X = identity_block(X, 3, [64, 64, 256], stage=2, block=’b’)X = identity_block(X, 3, [64, 64, 256], stage=2, block=’c’)# Stage 3 X = convolutional_block(X, f = 3, filters = [128, 128, 512], stage = 3, block=’a’, s = 2) X = identity_block(X, 3, [128, 128, 512], stage=3, block=’b’) X = identity_block(X, 3, [128, 128, 512], stage=3, block=’c’)X = identity_block(X, 3, [128, 128, 512], stage=3, block=’d’)# Stage 4 X = convolutional_block(X, f = 3, filters = [256, 256, 1024], stage = 4, block=’a’, s = 2) X = identity_block(X, 3, [256, 256, 1024], stage=4, block=’b’) X = identity_block(X, 3, [256, 256, 1024], stage=4, block=’c’) X = identity_block(X, 3, [256, 256, 1024], stage=4, block=’d’) X = identity_block(X, 3, [256, 256, 1024], stage=4, block=’e’)X = identity_block(X, 3, [256, 256, 1024], stage=4, block=’f’)# Stage 5 X = convolutional_block(X, f = 3, filters = [512, 512, 2048], stage = 5, block=’a’, s = 2) X = identity_block(X, 3, [512, 512, 2048], stage=5, block=’b’)X = identity_block(X, 3, [512, 512, 2048], stage=5, block=’c’)# AVGPOOL
X = AveragePooling2D((2,2), name=’avg_pool’)(X)# output layer X = Flatten()(X)X = Dense(classes, activation=’softmax’, name=’fc’ + str(classes))(X)# Create model
model = Model(inputs = X_input, outputs = X, name=’ResNet50′)#Compile the model
model.compile(optimizer=’adam’, loss=’categorical_crossentropy’, metrics=[‘accuracy’])
摘要
- 非常深的神经网络(普通网络)实现起来不实际,因为它们由于消失梯度而难以训练。
- 跳跃连接有助于解决消失梯度问题。它们还使得 ResNet 块很容易学习标识函数。
- 有两种主要类型的 ResNets 块:身份块和卷积块。
- 通过将这些块堆叠在一起,构建非常深的剩余网络。
参考
- https://en.wikipedia.org/wiki/Vanishing_gradient_problem
- 吴恩达卷积神经网络(Coursera)
- 何,,,,任,—深度残差学习在图像识别中的应用(2015)
- Francois Chollet 的 GitHub 资源库:https://GitHub . com/fchollet/deep-learning-models/blob/master/resnet 50 . py
PyTorch 在交通标志分类中的应用
德国交通标志识别基准数据集可能是与自动驾驶汽车相关的最流行的图像分类。自动驾驶汽车需要检测和分类交通标志,以理解应用于一段道路的交通规则。也许,这个数据集太小,不够完整,不能用于实际应用。然而,它是计算机视觉算法的一个很好的基准。
资料组
数据集由两部分组成:训练集和测试集。训练集包含 39209 幅交通标志图像,分为 43 类,如停车标志、自行车穿越和限速 30 公里/小时
Examples of German Traffic Sign Recognition Dataset images
数据集非常不平衡。例如,有 1800 个“速度限制(50 公里/小时)”标志的实例,但只有 168 个“向左转弯危险”标志的实例。
测试集有 12630 个标记图像。这些图像被用于 2011 年 IJCNN 竞赛的评估。
你可以从官网下载数据集。
方法
我尝试使用在 ImageNet 数据集上预先训练的 ResNet34 卷积神经网络进行迁移学习。
我在 fast.ai 最新版《程序员深度学习》课程中学到的解决计算机视觉问题的通用方法。我去年在旧金山大学参加了那个课程的离线版本。课程使用了 fastai ,一个基于 PyTorch 构建的深度学习库。它为训练深度学习模型提供了易于使用的构建模块。
我花了大部分时间优化超参数和调整图像增强。
密码
我在 GitHub 上发布了我的代码。您可以下载一个 Jupyter 笔记本,它包含了从下载数据集到基于未标记的测试集创建提交文件的所有步骤。训练 CNN 模型的代码大多基于 fast.ai 课程的 CNN 课程。
让我们来看看训练和评估模型的步骤。
准备
准备环境。我必须安装 fastai 库及其所有依赖项。
下载数据集,解包。将训练集(39209 个图像)拆分为训练集和验证集,并将文件移动到正确的文件夹中。我用 80%的样本进行训练,20%的样本进行验证。
小心分裂。该数据集包含每个物理交通标志的 30 张照片。根据文件名区分不同的系列是很容易的。如果您只是随机拆分数据集,那么将会有信息从验证集泄漏到训练集。
我一开始就犯了这个错误。我随机分割数据集,得到了超过 99.6%的惊人的验证准确率。当测试准确率只有 87%时,我很惊讶:测试准确率和验证准确率之间的巨大差异是验证集设计不良或过度适应验证集的标志。
正确的方法是找到图像系列,并将每个系列完全放入训练集或验证集中,确保它不会分成两部分。要了解更多关于创建好的验证集的信息,请阅读的这篇文章,作者雷切尔·托马斯。
探索性分析
浏览数据集。检查班级的分布,看看每个班级的一些图片示例。
图像有不同的大小。看看尺寸的直方图。它将让您了解 CNN 的输入维度应该是多少。
培养
加载在 ImageNet 数据集上预先训练的 ResNet34 模型。删除最后一层,并在顶部添加一个新的 softmax 层。
我的一般训练方法是:从一个小的模型输入(我从 32x32 的图像尺寸开始)和一个短的训练程序(总共 7 个时期)开始,以优化训练速度。你需要快速迭代。理想情况下,实验不应该超过几分钟。
此外,优化批量大小。在 GPU 内存允许的情况下,尽量增大批量大小。较大的批量有助于减少培训时间。但是,通过实验,我发现太大的批量(例如,1024 个样本或更多)会导致较低的验证准确性。我猜模型很早就开始过度拟合了。我最后得到了一个批量 256。
只有在你找到一组像样的超参数后,才切换到更大的图像和更长的细粒度训练。最后我用了 96x96 的图像,训练了 19 个纪元。
图像增强
设置图像增强。这是一种帮助模型更好地概括的技术。你在训练集中添加了很多人为的例子。这些例子是基于已经存在的例子,但是你稍微改变了它们:旋转几度,改变照明,放大,等等。
Examples of augmented images
我使用了以下变换的组合:旋转最大 20 度,光照变化最大 80%,缩放最大 20%。
灯光增强非常重要。在项目的早期阶段,我看到非常暗的图像有最不正确的预测。在照明增强方面的进取性将验证准确性提高了 3%以上。通过直接改变 R、G 和 B 通道的值来改变照明。详见 RandomLighting 类。
我尝试过并拒绝的其他东西:直方图均衡化以提高对比度,随机模糊,填充。
学习率
使用这里描述的简单算法为训练搜索一个好的开始学习率。
微调最后一层
冻结除最后一层以外的所有层。以该学习速率训练一个时期的模型。以我为例,学习率是 0.01。这里的目标是为最后一层获得合理的权重。如果我们不这样做,稍后训练一个未冻结的模型会导致更低的层混乱,因为梯度会更大。我尝试了这两个选项,训练一个时期的最后一层在验证准确性方面有大约 1%的提高。我还使用了重量衰减来做一个小小的改进。
微调整个模型
解冻所有层。训练三个时代。
然后使用带热重启的随机梯度下降(SGDR) 训练几个时期。
我尝试使用区别性微调,为模型的不同部分设置不同的学习率。在这种情况下,我们希望模型的第一层比最后一层训练得少。第一层比其他层更通用。当在 ImageNet 数据集上训练时,这些层学到了对我们的任务非常有用的模式,我们不想失去这些知识。另一方面,最后一层是非常特定于任务的,我们希望在我们的任务中重新训练它们。不幸的是,它对改进度量没有帮助。如果对所有层应用较大的学习率,模型的训练效果会更好。我猜这是因为交通标志与狗、猫和飞机非常不同,因此较低层的信息不像在其他计算机视觉应用中那样有用。
验证集上最佳模型的准确率为 99.0302%。
误差分析
除了像混淆矩阵这样的常用工具,您还可以通过检查一些极端情况来分析错误:最不正确的预测、最正确的预测、最不确定的预测。
要查找每个类最不正确的预测,必须对验证集进行推理,并选择正确类的预测概率最小的示例。
Most incorrect images
这些图像看起来太模糊太亮。
类似地,您可以找到将最高概率分配给正确类(“最正确”)的示例,以及正确类的概率接近 1/num_classes(“最不确定”)的示例。
此分析的结果有助于您调整图像增强参数,可能还有模型的一些超参数。
在完整训练集上重新运行训练
在之前的所有步骤中,我们将 80%的训练集用于训练,20%用于验证。现在,由于我们发现了好的超参数,我们不再需要验证集,可以将这 20%的图像添加到训练集中,以进一步改进模型。
在这里,我只是使用相同的参数重新运行所有的训练步骤,但是使用所有 32909 个训练图像进行训练。
在测试集上测试
测试集(12630 幅图像)旨在测试最终模型的性能。我们没有在前面的步骤中查看测试集,以避免过度适应测试集。现在,我们可以在测试集上评估模型。我在测试集上获得了 99.2953%的准确率。相当不错!我们能进一步改进它吗?
测试时间增加
测试时间增强(TTA)通常有助于进一步提高精确度。诀窍是创建输入图像的几个增强版本,对每个版本进行预测,然后平均结果。这背后的直觉是,模型在分类一些图像时可能是错误的,但是稍微改变图像可以帮助模型更好地分类它。这就像如果一个人想对一个物体进行分类,他们从不同的角度看它,稍微改变一下照明,把它移到离眼睛更近的地方,直到他们能找到最有信心识别这个物体的最佳视角。
的确,TTA 帮我把准确率从 99.2953%提高到了 99.6120%。它将误差减少了 45%(从 0.7047%减少到 0.388%)。
有多好?
测试集上的准确率为 99.6120% 。我们来对比几个基准。
最先进的是由 Mrinal Haloi 基于《T2》的 CNN。99.81%.错误率比我好两倍。
2011 年 IJCNN 竞赛排行榜上的前几名:
- Á·阿尔瓦罗阿科斯-加西亚等人制作的带 3 个空间转换器的 CNN
- CNN 委员会由 Dan Cireş an 等人提出 99.46%
- 用于物体识别的基于颜色斑点的 COSFIRE 过滤器作者:巴里斯·格瑟。98.97%
如果我的模特参加比赛,她会获得第二名。总的来说,几天的工作还不错。
接下来阅读:
学习率是用于训练深度神经网络的最重要的超参数之一。
towardsdatascience.com](/estimating-optimal-learning-rate-for-a-deep-neural-network-ce32f2556ce0) [## NVIDIA Jetson TX2 入门
Jetson TX2 是 NVIDIA 的一款高能效嵌入式人工智能计算设备。这是一台小型计算机,有一个信用卡那么大…
medium.com](https://medium.com/@surmenok/getting-started-with-nvidia-jetson-tx2-5952a2d8d7ae) [## Fast.ai:我从第 1-3 课中学到了什么
Fast.ai 是一个非常棒的深度学习课程,适合那些喜欢通过做来学习的人。与其他课程不同,在这里您将…
hackernoon.com](https://hackernoon.com/fast-ai-what-i-learned-from-lessons-1-3-b10f9958e3ff)
回顾:带有身份映射的预激活 ResNet 已达到 1000 多个图层(图像分类)
预激活 ResNet:卷积前的批量 Norm 和 ReLU
在这个故事中,我们回顾了微软改进的 ResNet [1]。通过身份映射,深度学习架构可以达到 1000 层以上,不会增加错误。
在 ResNet [2]的上一版本中,当 ResNet 从 101 层到 1202 层时,虽然 ResNet-1202 仍然可以收敛,但是错误率从 6.43%下降到 7.93%(这个结果可以在[2]中看到)。并且在[2]中被陈述为开放问题而没有任何解释。
下图显示了使用标识映射的 ResNet 的结果。在层数达到 1001 的情况下,先前的 ResNet [2]仅获得 7.61%的误差,而对于 CIFAR-10 数据集,具有身份映射[1]的新 ResNet 可以获得 4.92%的误差。
(a) Previous ResNet [2] (7.61%) (b) New ResNet with Identity Mapping [1] (4.92%) for CIFAR-10 Dataset
但是为什么保持快捷连接路径干净(如图将 ReLU 层从快捷连接路径移动到 conv 层路径)会更好?本文对此进行了很好的解释。一系列的消融研究证实了这种身份映射的重要性。
结果是比 Inception-v3【3】还要好。(如果有兴趣,也请阅读我的 Inception-v3 评测。)这么好的成绩,发表在我写这个故事的时候 2016 ECCV 论文上1000 多篇引用。( Sik-Ho Tsang @中)
涵盖哪些内容
- 身份映射重要性的解释
- 消融研究
- 与最先进方法的比较
1。身份映射重要性的解释
前馈、反向传播和梯度更新似乎使深度学习成为一个秘密。我觉得这里的解释非常好。
1.1 前馈
在具有身份映射的 ResNet 中,在没有任何 conv 层 BN 和 ReLU 的情况下,保持从输入到输出的快捷连接路径的干净是至关重要的。
xl 是 l 层的输入,F(。)是代表 conv 层 BN 和 ReLU 的函数。那么我们可以这样表述:
One Particular Layer
L layers from l-th layer
我们可以看到输入信号 xl 仍然保持在这里!
1.2 反向传播
在反向传播过程中,我们可以得到分解成两个附加项的梯度:
Gradient which decomposed into two additive terms
在毯子里面,无论网络有多深,我们总能在左边的项得到“1”。右项不能总是-1,这使得梯度为零。因此,这个渐变并没有消失!!
1.2 违反身份映射时的反向传播
另一方面,如果左边的项不等于 1 呢:
One Particular Layer
L layers from l-th layer
Gradient which decomposed into two additive terms
同样,梯度的左项是λ的乘积。
如果 λ > 1 ,左项将呈指数大,出现梯度爆炸问题。我们应该记得,当梯度爆炸时,损失无法收敛。
如果 λ < 1 ,左项将呈指数小,出现梯度消失问题。我们不能用大值更新梯度,损耗停留在平稳状态,最终以大损耗收敛。
因此,这就是为什么我们需要保持从输入到输出的捷径连接路径没有任何 conv 层,BN 和 ReLU。
2。消融研究
2.1 各种快捷连接方式
**110 层 ResNet (54 个两层剩余单元)**与各种类型的快捷连接在 CIFAR-10 数据集上测试如下:
Performance of Various Types of Shortcut Connections
原文:即[2]中 ResNet 的上一版本,误差 6.61%。
常数缩放 : λ=0.5,存在上述梯度消失问题,仔细选择偏置 bg 后,误差为 12.35%。
排他门控&仅快捷门控:两者都试图增加快捷路径的复杂性,同时仍然保持路径等于“1”。但是两者都不能得到更好的结果。
1×1 Conv 快捷方式:类似于之前 ResNet [2]中的选项 C。在以前的 ResNet 中,发现使用选项 c 更好。但现在发现,当有许多剩余单元(太深)时,情况并非如此。
辍学捷径:实际上是统计执行λ=0.5。
2.2 激活的各种用法
通过在 BN 和 ReLU 的位置附近玩耍,获得以下结果:
Performance of Various Usages of Activation
添加后之前的 ResNet & BN:两者都不能在违反身份映射的快捷连接上保持干净。
加法前的 ReLU:ReLU 后的残差函数必须是非负的,使得正向传播的信号是单调递增的,而残差函数最好也是负值。
ReLU-only 预激活 : ReLU 不配合 BN 使用,不能很好的享受 BN 的好处。
全预激活:快捷路径干净,ReLU 配合 BN 使用,成为最佳设置。
2.3 预激活的双重优势
2.3.1 优化的简易性
Previous ResNet structure (Baseline) vs Pre-activation Unit
由于 ReLU 层的错误位置,使用先前的 ResNet 结构(基线)在太深(1001)时具有更差的结果。当网络从 110 到 1001 越来越深的时候,使用预激活单元总能得到一个比较好的结果。
2.3.2 减少过拟合
Training Error vs Iterations
预激活单元处于正则化状态,即收敛时的训练损失略高,但测试误差较低。
3.与最先进方法的比较
3.1 西法尔-10 和西法尔-100
CIFAR-10 & CIFAR-100 Results
对于 CIFAR-10,使用具有建议预激活单元的ResNet-1001(4.62%),甚至优于使用以前版本 ResNet 的 ResNet-1202 (7.93%) ,少 200 层。
对于 CIFAR-100,使用 ResNet-1001 和建议的预激活单元(22.71%),甚至优于使用 ResNet 早期版本的 ResNet-1001 (27.82%) 。
对于 CIFAR-10 和 CIFAR-100 来说,带有建议预激活单元的 ResNet-1001 并不比 ResNet-164 有更大的误差,但是以前的 ResNet [2]有。
在 CIFAR-10 上,ResNet-1001 用 2 个 GPU 训练大约需要 27 个小时。
3.2 ILSVRC
ILSVRC Image Classification Results
仅在规模上有所增强,ILSVRC 2015 的获胜者 ResNet-152 (5.5%)上一版本由于 ReLU 位置错误,在往更深处走时,比 ResNet-200 (6.0%) 上一版本性能差**。**
并且所提出的具有预激活的 ResNet-200(5.3%)具有比先前的 ResNet-200 (6.0%)更好的结果。
随着规模和纵横比的增加,提议的预激活 ResNet-200(4.8%)优于谷歌的 Inception-v33。
同时,谷歌也有一个 Inception-ResNet-v2,它有 4.9%的误差,有了预激活单元,误差有望进一步降低。
在 ILSVRC 上,ResNet-200 在 8 个 GPU 上训练大约需要 3 周时间。
在回顾了 ResNet 和带有身份映射的 ResNet,以及 Inception-v1、Inception-v2 和 Inception-v3 之后,我还将回顾 Inception-v4。敬请关注!
参考
- 【2016 ECCV】【带有身份映射的 ResNet】
深度剩余网络中的身份映射 - 【2016 CVPR】【ResNet】
用于图像识别的深度残差学习 - 【2016 CVPR】【盗梦空间-v3】
重新思考计算机视觉的盗梦空间架构