2017年1月27日,星期五

强化学习和语言支持

指定从经验中学习的程序的正确方法是什么?现有的通用编程语言旨在简化任何软件的规范。所以我们可以只使用这些编程语言进行强化学习,对吗?有点。

抽象很重要

用高性能服务进行类比可能会有所帮助。有关高性能投放的早期影响力页面(Dan Kegel的C10K问题)概述了几种I / O策略。我已经尝试了很多。一种策略是事件驱动的编程,其中核心事件循环监视事件的文件描述符,然后分派处理程序。这种样式可产生高性能的服务器,但难以编程且对程序员错误敏感。除了故障隔离问题(如果所有事件都在相同的地址空间中运行)之外,这种风格还很容易受到任何事件处理程序执行时间过长(例如,隐藏的阻塞I / O调用,计算密集型操作等)的影响。 。相反,基于线程的编程允许您假装您是唯一正在运行的处理程序。它的计算效率较低,并且仍然存在故障隔离问题,但推理起来更容易。 (随后,我开始进入Erlang,因为它本质上是试图烘焙带有错误隔离功能的用户空间线程到语言中,这甚至更好。)

我不知道现在高性能服务中的最新技术,我对这个游戏有些不了解。要点是,并非所有编程语言都具有相同的创造力,因为它们给程序员带来了不同的认知负担,并在运行时产生了不同的计算负担。我可以通过两种方式(协作调度与抢先式调度)之一使用现有的语言(当时为C ++),也可以使用旨在减轻折衷的另一种语言(Erlang)。

具有自动信用分配的命令式规范

如前所述,我们现在要指定的程序与过去指定的程序之间的差异是,我们希望我们的程序能够从经验中学习。与高性能服务一样,我们希望平衡程序员的认知负担与运行时施加的计算负担(也可能是运行时施加的统计负担;计算负担对应于诸如时间或空间之类的资源,而统计负担对应于数据资源)。

在当前范围内“AI summer”,一个流行的想法是 自动区分。完整的AD意味着基本上可以使用任何语言构造来定义函数,并且提供了用于计算函数相对于输入的梯度的计算“for free.”配备有正在计算(亚)可微函数的AD的语言可以从经验中学习,逐渐接近损失函数的局部最优值。深度学习工具包通过一些框架(例如, 链条机)在指定正向计算时积极追求允许任意语言构造的想法。

随着推理变得越来越复杂,使用任意语言构造的能力变得越来越重要。简单的推论(例如分类或排名)很容易推断,但除此之外,它很快成为以下方面的主要缺陷来源:1)指定如何使用机器学习模型的输出来合成完整的系统,以及2)指定如何运行该完整系统获得的数据将用于更新模型。

在结构化预测领域中,该问题显而易见。“结构化预测”当然是一个有点荒谬的名词“非线性系统分析”;在这两种情况下,最初都解决了该问题的一个简单版本(分别是分类和线性系统分析),然后为其他所有问题创建了一个总括术语。尽管如此,Hal Daume对结构化预测有一个很好的定义,它在一个示例上进行了多个预测,并且经历了(在决策中)共同损失。 (他也有一个 ku句版 这个定义。)

由于结构化预测中的推理很复杂,因此对于结构化预测本质上是重新定义了命令性规范和自动信用分配的思想。该技术概述于 Chang等人撰写的Arxiv论文。等,但是Chainer的粉丝会认出这是“define-by-run”用于结构化预测。 (请注意,这里的优化策略不是梯度下降,至少不是在正向计算上,而是策略梯度方法之类的东西,它会通过正向计算做出的预测转化为离散的信用分配问题。)

查看情景RL的一种方法是使用强盗反馈进行结构化预测:类似于监督学习,完全观察到结构化预测,因为可以计算给定特定输入的任何决策序列的损失。在强化学习中,您会获得强盗反馈,即,您仅了解与实际采取的决策顺序相关的损失。虽然这不是查看情节性RL的唯一方法,但它确实有助于与上一段中提到的论文的某些思想联系起来。

一个激励人的例子

这是一个希望可以澄清问题的示例。假设我们要构建一个交互式的问答系统,在该系统中用户提出问题,然后该系统可以有选择地向用户提出(澄清)问题或提供答案。我们可以将其视为一个偶然的RL问题,其中用户陈述是观察值,系统问题是动作,系统答案是更多动作,并且情节在我们提供答案后就结束了。

我想做的是指定类似此伪python的计算:
def interactive_qa_episode():
   q  = get_user_question()
  Qapairs = []
  sysaction = get_next_system_action(uq, Qapairs)
  while (sysaction.is_question):
    ua = get_user_answer(sysaction.utterance)
    Qapairs.append((sysaction,ua))
    sysaction = get_next_system_action(uq, Qapairs)
  deliverAnswer(sysaction.utterance)
很清楚这里发生了什么:我们得到一个用户问题,有条件地提出问题,然后给出答案。在机器学习出现之前,这种系统的实现者会尝试填写上述未指定的功能:特别是, get_next_system_action 手动指定很棘手。我们要做的是改为学习此功能。

使用装饰器来实现这一点将是很好的。首先,要学习,我们需要知道做的更好还是更坏的想法,因此假设给出答案后,可以通过某种方法来确定用户对会话的满意程度(即,ceterus perebus,应随所提问题的数量单调减少) ,以鼓励权宜之计):
@episodicRL
def interactive_qa_episode():
   q  = get_user_question()
  Qapairs = []
  sysaction = get_next_system_action(uq, Qapairs)
  while (sysaction.is_question):
    ua = get_user_answer(sysaction.utterance)
    Qapairs.append((sysaction,ua))
    sysaction = get_next_system_action(uq, Qapairs)
# this next line is the only change  至  the original function
   奖励  = deliverAnswer(sysaction.utterance) 
太容易了!伪代码是如此高效。我们甚至可以想象更新 奖励 装饰者多次跟踪奖励增量以改善信用分配。

现在开始进行一些魔术性元编程,并将其转换为使用RL算法训练的模型(例如,诸如q-learning之类的值迭代方法或诸如 强盗)。还是呢?我们仍然没有说要学习哪些功能以及哪些是手工指定的。默认值是手动指定的,因此我们将修饰一个功能。
@learnedFunction
def get_next_system_action(uq, Qapairs):
  ...
现在我们陷入一些棘手的问题。我们最终需要根据参数化模型(例如神经网络)来指定此功能;我们将不得不说从诸如 q Qapairs;我们将不得不说如何将模型的输出映射到实际决策上。为了保持前进,我们假设存在一组固定的系统问题和系统答案。
action_table = [ ... ] # list containing action mapping
@learnedFunction
def get_next_system_action(uq, Qapairs):
  not_allowed_action_ids = [ sysa.action_id for (sysa, _) in Qapairs ]
  action_id = categorical_choice(uq:  q ,
                                 Qapairs: Qapairs,
                                 not_allowed_action_ids: not_allowed_action_ids,
                                 tag: 'nextsystemaction')
  return action_table[action_id]
categorical_choice 是从一组可能性中进行强制选择的表示。对于小型动作空间,可以将其直接实现为每个动作的输出,但是对于大型动作空间,可以通过具有信息检索样式级联管道的动作嵌入来实现。

很好吗?好吧,仍然存在一些问题。
  • 用于选择的最佳模型结构(即策略类)需要程序员指定一些规范,例如卷积文本网络与迭代注意力体系结构。理想情况下,此规范不同于推理规范,因此可以尝试许多建模思想。这就是tag参数的目的,是将其与学习参数的单独说明结合在一起。 (如果未提供,则可以在编译期间生成合理的默认标记。)
  • 如所示 以前的帖子,引导就是一切。所以最初的实现 get_next_system_action 需要提供。也许这可以简化为提供基础模型的初始设置,但是可能不取决于初始化方案。注意,如果初始化是通过模拟或从历史数据中脱离策略学习完成的,则可以通过简化I / O功能的模型来支持这些初始化 get_user_questionget_user_answer。另一个常见的情况是,将未学习的功能作为参考策略,学习的功能应与之竞争。
我不能和Chainer一起做吗? 有点。当然,如果您使用特定的RL算法。例如,q学习可将强化学习减少到回归,因此,如果您对该内联进行编码,您将获得Chainer可以处理的东西。但是,目标是在不泄漏学习算法细节的情况下指定推论,因此我宁愿不对该内联代码进行编码。另一种方法是编译 链条机,类似于c ++早期的cfront。

但最终,我希望有一个不同的编译策略。不仅仅是实现学习算法,还有更多的风险:存在所有提到的问题 我以前的帖子 这使我确信,实施应该能够利用强化学习服务。

2017年1月21日,星期六

强化学习即服务

在过去的6个月中,我一直在将强化学习整合到实际产品中,因此,我对可能是常见问题的认识正在逐渐提高。特别是,我现在对强化学习即服务的想法很感兴趣,其中 决策服务 来自MSR-NY的数据就是一个早期的例子(目前仅限于上下文强盗,但结合了关键的系统见解)。

服务,不是算法 监督学习本质上是观察性的:已经收集了一些数据,然后在其上运行算法。 (在线监督学习不一定能以这种方式工作,但是在收集数据后出于计算的原因,大多数使用在线技术。)相反,反事实学习很难做到观察。经济学,政治学和流行病学等各种领域都试图使用观察数据得出反事实结论,主要是因为这是唯一可用的数据(以可承受的成本)。但是,在测试新药时,该标准是进行对照实验,因为通过控制数据收集,可以更有把握地得出更复杂的结论。

类似地,强化学习最好完成“in the loop”,并控制用于学习的数据收集算法。因此,由于必需的状态管理,增强学习算法的纯库实现是不自然的。例如,奖励是在采取行动之后发生的,并且这些奖励最终需要相互关联才能学习。 (我的第一份工作之一是在一家名为Overture的赞助搜索公司中,维护搜索单击联接是十几名工程师的全职工作:请注意,这只是单例会议的立即联接!)

因此,包装强化学习即服务意义更大。这有助于模型更新,服务(探索)分布和数据收集的分布式协调。对于云计算提供商来说,这种情况是自然而然的。但是,实际上需要有一个离线客户端模式(例如,用于移动和IOT应用程序);此外,由于低延迟决策要求,即使在纯数据中心环境中也将利用此功能。 (更一般而言,“tiered learning”与云计算平台中使用的分层存储架构类似的架构。布伦丹·麦克马汉(Brendan McMahan)在 联合学习

引导就是一切 试图解决和解决实际问题真是令人惊讶。我现在很欣赏强化学习已经被超卖了。特别是,强化学习的样本复杂性要求非常高。 (这是花哨的说法,因为它需要收敛大量的数据。)当您在模拟环境中工作时,这不是要担心的问题,因为您拥有无限的训练数据,因此在模拟环境中我们会看到惊人的结果。

当在真实用户的实时流量上进行强化学习时,您的数据量比您想象的要少,因为您总是从测试数据的一部分入手,直到变得更好为止,您才能获得更多(第22章)。因此,实际上我花了很多时间来制定初始服务策略,不幸的是有些特质:使用正确的数据资产进行模仿学习可能很棒,但是启发式策略也很重要。我怀疑在模拟环境中通过not-smartly-initialized-RL进行初始化是另一种可能性(在对话框模拟器中效果不佳,因此我还没有利用这种策略)。

这为RL即服务创建了一些设计问题。
  • 假设有一个初始投放策略,该如何指定?在决策服务中,您传递将采取初始服务策略的操作,这对于上下文强盗来说是合适的,但是对于多步骤时期,这可能很麻烦,因为初始服务策略需要维持状态。对于服务来说,使其更易于管理很有意义。
  • 服务如何帮助我制定最初的服务政策?考虑到我到目前为止的经验,以下是制定初始服务政策的一些可能方法:
    • 任意程序(``启发式'')。有时这是冷启动的最简单方法,或者这可能是当前的``冠军''系统。
    • 模仿学习。假设合适的数据资产可用。
    • 从历史数据中进行非政策学习。如果历史政策经过适当随机化(例如,以前调用RL作为服务的穷举),那么这可能比模仿学习更好。
    • 通过仿真进行增强。在对话中这似乎不可行,但是如果有一个好的模拟器(例如,机器人和游戏引擎?),那可能很棒。此外,这将涉及平台的直接重用,即使生成的数据也是如此。

语言是编程的UI 我认为 学分分配汇编 不仅将解决如何指定初始策略的问题,而且还将为使用RL服务提供最自然的接口。我将在另一篇文章中进行探讨。

2017年1月13日,星期五

通过对抗训练生成文本

今年在GAN研讨会上有一篇非常可爱的论文, 通过对抗训练生成文本 由张,甘和卡林撰写。特别是,它们做出了一些很重要的不寻常选择。 (警告:如果您不熟悉GAN,那么这篇文章就没有多大意义了。)
  1. 他们使用卷积神经网络(CNN)作为判别器,而不是RNN。回想起来,这似乎是个不错的选择,例如张彤已经 粉碎它 使用CNN进行文本分类。 CNN比RNN容易训练,因此最终结果是强大的判别器,并且具有相对容易的优化问题。
  2. 他们在发生器中使用LSTM输出的平滑近似值,但实际上这种技巧到处都是,因此在隔离方面并不是那么出色。
  3. 他们使用纯矩匹配标准进行鞍点优化(基于小批量估算)。 GAN从逐点辨别损失开始,最近的工作通过矩匹配样式惩罚增加了这种损失,但是这里的鞍点优化是纯矩匹配。 (因此从技术上讲,鉴别器不是鉴别器。实际上,它们在文本中可互换地称为鉴别器或编码器,这解释了原因。)
  4. 他们对初始化非常聪明。特别地,鉴别器被预先训练以在两个单词互换位置的情况下区分真实句子和相同句子。 (在初始化期间,使用逐点分类损失训练鉴别器)。这很有趣,因为交换两个单词会保留输入的许多$ n $ -gram统计信息,即许多卷积滤波器将计算出完全相同的值。 (最近我很幸运地使用置换句子作为其他模型的否定词,现在我将尝试交换两个单词。)
  5. 他们更新发电机 更频繁 比区分符要高,这与标准的民间传说相反,后者说您希望区分符的移动速度比生成器快。也许这是因为CNN优化问题比LSTM容易得多。纯粹的矩匹配损耗的使用也可能是相关的。



关于神经网络论文的老抱怨是您无法复制它们。如今,复制神经网络论文通常比其他论文更容易,因为您可以将他们的代码存储在github上并运行实验。但是,我仍然很难确定所做的各种选择的相对重要性。对于上面列举的选择:最终结果对这些选择的敏感性是多少?很难说,但是我已经开始假设灵敏度很高,因为当我在复制后尝试调整结果时,通常会变得很糟糕。 (我尚未尝试复制此特定结果。)

无论如何,本文有一些很酷的想法,希望可以扩展到生成逼真的对话框。