Memory augmented policy optimization for program synthesis and semantic parsing论文阅读

Abstract

MAPO方法可以看成是前一篇neural symbolic machine的优化,利用一些pesudo-gold-program减少策略估计的方差。MAPO算法可以应用在一些deterministic environment的环境和离散动作的强化学习环境中,比如结构预测。neural symbolic machine就属于结构型预测。key idea:memory buffer保存一些high reward的trajectories,expected return objective则是一部分是在memory buffer里的expectation,另一部分是memory buffer外的expectation,简单来说就是将expected return objective分成了两部分。
为了设计算法,论文提出了三种technology实现:1) 内存权重的裁剪,使得训练更加平滑快速。2)系统性的探索技术,能够发现high-reward的trajectory。2)使用分布式的技术从memory buffer和memory buffer外面抽取样例加快训练。
主要实验有两个,WikiTableQuestions和WikiSQL数据集。都是属于结构性预测的一类。

Introduce

在前面的neural symbolic machine中,使用on-policy中的的reinforce learning的学习方法,这样通常会导致不稳定的学习曲线和不稳定的采样,有时候甚至比随机采样还要差。 也就是说之前使用的policy gradient存在一些问题,1.policy gradient estimate会有很大的方差,每次抽取出来的program可能会变化很大。2.由于强化学习在刚刚开始训练的时候存在冷启动的问题。3.随机采样是很没有效率的做法。事实上,在强化学习中,只有生成正确的program才会生成high-reward。而且,很多已经sample到的high-reward trajectory用过一次后就会被丢失。high-reward trajectory出现很罕见,但是出现之后使用过又会被丢弃。 其实文章要解决的问题,是重新利用high-reward trajectory,之所以reinforce不能重新利用trajectory是因为reinforce的更新是通过程序的概率做的更新,而更新之后的model对于previous的trajectory的概率已经变化了,所有只能用一次。类似的idea强化学习有用过,PPO就是利用一个新的model抽取high-reward trajectory,这个时候trajectory的偏差就会很小,但是会产生模型之间的bias。所有MAPO主要解决之前high-reward trajectory不能重用的问题,相对以前提出的PPO,这篇文章的MAPO是没有bias,也就算model之间的偏差这篇文章不存在。

Problem

实验要解决的问题是将一些自然语言处理的文本映射成程序program。在无监督条件下,我们不会提供正确的program,只会提供正确答案。 R ( a ′ ∣ x , y ) R(a' | x, y) R(ax,y)会执行program和correct answer对比。大多数RL的工作是考虑如何在training dataset取得最大的reward,而这里的问题contextual program synthesis要考虑的是model的泛化能力。

Optimization of Expected Return via Policy Gradients

在这个问题中,我们要做的是为每一个问题生成program,一个带参数 θ \theta θ的model会给程序a一个概率 π θ ( a ∣ x ) \pi_\theta(a|x) πθ(ax)。由于program的预测是一个一个语句预测,所以 π θ ( a ∣ x ) = ∏ i = t ∣ a ∣ π θ ( a t ∣ a < t , x ) \pi_\theta(a|x) = \prod_{i = t}^{|a|} \pi_{\theta}(a_t | a_{<t}, x) πθ(ax)=i=taπθ(ata<t,x),这样的形式可以用RNN做预测。

b就是gradient estimate的方差。

MAPO

首先问题的设定要求action是可数的,并且同一个程序, R ( a ) R(a) R(a)得到的结果是相同的。为了减少gradient estimate的方差,保存这些high-reward 的trajectory,引入一个memory buffer,将一些high-reward的program存储下来。

以往的工作:

第一项是reinforce,第二项是maximization likelihood。第二项是存在偏差的,如果trajectory不是目标的trajectory,但是又是偶然取得了high-reward的trajectory,然后利用极大似然估计是有问题的。有些program是偶然得到正确的答案,使用这些program优化会带来bia。
MAPO做出的改进的,不再单单利用memory buffer的trajectory,并且利用了memory buffer外的trajectory。

an expectation over the trajectories inside the memory buffer, and a separate expectation over the trajectories outside the buffer



只是把 π B \pi_B πB提出了而已, π B \pi_B πB也是memory weight。

Memory Weight Clipping

policy gradient一开始会遇到冷启动的问题,在还没有训练的时候model会分配很小的概率给一些high-reward trajectory,这些trajectory很容易被忽略的。所以自然想要让model pay more attention to high-reward trajectory。

要想让model能充分利用high-reward trajectory,提高 π B \pi_B πB的概率即可,所以设定了一个 α \alpha α,规定 π B \pi_B πB至少要等于 α \alpha α,给在memory buffer中一定的权重。在刚开始训练的时候, π B \pi_B πB是会不断衰减到 α \alpha α的,因为memory buffer中几乎没有trajectory,而且会有很多偶然得到high-reward的trajectory,但是这样可以加快训练。当训练到一定程度,policy启动后,就没有什么bia了, π B \pi_B πB也会回升。

Systematic Exploration

这项技术是为了提高采样效率。

其实就是不重复抽取相同的序列。

Distributed Sampling


在计算第一项的时候,如果数量非常多会导致计算的负担,可以对memory buffer采样.

MAPO


使用多个actor采样,在MAPO实验中是12个。每一个question都会带有两个内存,第一个是存储high-reward的buffer,第二个是存储所有被采样出来的buffer,用于exproration。有一说一这内存蛮大的。对于每一个actor每一个问题,使用Systematic Exploration得到action,根据是否在内存中确定权重。接下来learner学习即可。

Experiment

实验部分只是简单看了一下,没有什么特别突出的,因为这个算法好像更注重sementic parser的任务。

Conclusion

这篇文章的model能够发在neuralPS上有点疑惑。因为neuralPS的文章一般都是篇理论多,AAAI偏应用多。这篇文章的idea中使用额外的actor抽取experience是PPO提出的方法,memory buffer也不是她提出的,很多领域都会用memory buffer存储,而创新的地方是在于优化的时候使用了memory buffer里和memory buffer外的experience来更新,所以model上本身做的优化很少。论文最后证明的他们的bia是要更小的,这算一个贡献。然后实验也超越了SOTA。model上的创新不多,所以实验,理论占的贡献要更多一些。其实他选择这么一个任务也是想突出他对bia的处理,因为sementic paser task其中一个难点就是多元化,对于一种结果可以有多种解释,而这些解释中有很多是偶然得到的,但实际上是错误的。而如果在Atri的有些环境中他的优化效果可能还不如PPO这些,因为游戏环境中是不存在bias的,只要能拿分的trajectory都是对的。所以MOPA适合一些有bias的任务,比如MWP任务,LBF这篇论文的baseline就是MOPA。

Code

neural-symbolic-machines有一份pytorch实现的代码https://github.com/pcyin/pytorch_neural_symbolic_machines.git
这份代码是用pytorch实现,加入了taBert,并使用MAPO做为优化。
运行脚本在table下的experiment.py文件。

OMP_NUM_THREADS=1 python -m \
  table.experiments \
  train \
  seed 0 \
  --cuda \
  --work-dir=runs/demo_run \
  --config=data/config/config.vanilla_bert.json

使用参数可以运行。OMP_NUM_THREADS是设置运行程序的线程数,python -m将py文件当成是脚本运行,后面的都是参数。python table/experiment.py和python -m table.experiment没有什么区别,主要是影响sys.path这个参数,也就是运行目录可能有变化。

这个命令一开始我是跑不起来的,后来看了一下代码,发现卡在了args = docopt(__doc__)这个位置,docopt可以通过文档的方式对参数进行定义,定义在experiment.py前面

"""
Pytorch implementation of neural symbolic machines

Usage:
    experiments.py train --work-dir=<dir> --config=<file> [options]
    experiments.py test --model=<file> --test-file=<file> [options]

Options:
    -h --help                               show this screen.
    --cuda                                  use GPU
    --work-dir=<dir>                        work directory
    --config=<file>                         path to config file
    --extra-config=<str>                    Extra configuration [default: {}]
    --seed=<int>                            seed [default: 0]
    --eval-batch-size=<int>                 batch size for evaluation [default: 32]
    --eval-beam-size=<int>                  beam size for evaluation [default: 5]
    --save-decode-to=<file>                 save decoding results to file [default: None]
"""

必须要按照usage的用法才能跑起来,所有参数位置需要调整

OMP_NUM_THREADS=1 python -m \
  table.experiments \
  train \
  --work-dir=runs/demo_run \
  --config=data/config/config.vanilla_bert.json \
  --seed 0 \
  --cuda \

这样才能跑起。
table experiment.py文件有可执行主函数。里面的main()函数就是执行函数。

def main():
    multiprocessing.set_start_method('spawn', force=True)

    args = docopt(__doc__)

    if args['train']:
        distributed_train(args)
    elif args['test']:
        test(args)

当experiment后面的参数是train的时候,则训练,否则就是测试。multiprocessing则是设置进程启动方式。当参数是train的时候进入distributed_train(args)函数进行训练。

distributed_train()
    seed = int(args['--seed'])
    config_file = args['--config']
    use_cuda = args['--cuda']

    print(f'load config file [{config_file}]', file=sys.stderr)
    config = json.load(open(config_file))

    inject_default_values(config)

config是输入的bert文件,cuda是否使用GPU,如果bert文件没有输入,则inject_default则会使用默认的bert文件。下面就是回去工作目录。工作目录将会存储训练完成的模型,这个模型将会用于测试。后面还有一个主要参数

    actor_use_table_bert_proxy = config.get('actor_use_table_bert_proxy', False)

如果不加这个参数,那么每一个actor会自己构造一个bert使用,加入这个参数可以使得所有的actor公用一个bert,增加memory的利用率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值