Policy Evaluation的收敛性是怎么一回事

2023-11-27 04:59

本文主要是介绍Policy Evaluation的收敛性是怎么一回事,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

完美的学习算法

昨天和同学在群里讨论DRL里bad case的问题。突然有同学提出观点:“bad case其实并不存在,因为一些算法已经理论证明了具有唯一极值点,再加上一些平滑技巧指导优化器,就必然可以收敛。”

当听到这个观点时,我是一时语塞。因为当前深度学习研究的最大问题就是,花了很大资源训练的千万参数神经网络根本不work,一切都白白浪费。因此才有NAS之类方法尝试根据一些训练初期的动力学性质调整结构,找出合适的超参数,但也是效果平平。如果真有一个这么完美的学习算法,那岂不是任何问题都能解决了?但根据我掌握的常识,这是不可能的。且不说学术界根本就没有这种工作。收敛性显然与网络结构和优化器有关,怎么会在无视这些设置的情况下证明出一个forall的结果呢?

我问他这个问题。他说:“根据证明,任务规模只与收敛速度有关,与是否收敛无关。只要接一个足够强的神经网络,就能……”

其实说到这我大概就知道他说的那个“证明”是怎么回事了。不过为了确认一下,我还是把他说的那篇“证明文章”要了过来,一看发现果然是那种车轱辘证明。

压缩映射与线性收敛速度

这篇“证明文章”是DRL的知名工作soft actor-critic。所谓收敛证明在16页paper里占了一页。其实粗读就可以看出,文章中的“收敛证明”是针对“tabular setting”,即离散形式。对于连续形式,文中指出需要使用神经网络对Policy Evaluation进行逼近,后面就转进到神经网络的实现细节上了。而Policy Evaluation能否收敛就决定了整个算法能否收敛,此处Policy Evaluation使用神经网络逼近,核心就转到了神经网络能否收敛。可神经网络一个任务一个样,它能不能收敛才是最核心的问题,然而文章并没有涉及。事实上,现在地球上没有学者能解答这个问题。

说到这,可能有同学在想:如果能保证离散情况下收敛就已经能解决很多问题了。可是你有没有想过,所谓“离散收敛连续不收敛”,里面的gap在哪里?在连续情形下不成立,离散情况下就会那么完美吗?当然不可能。

根据我的理解,SAC论文中收敛性的证明过程实际与传统策略迭代收敛的证明类似,只是它补充了他们工作带来的改动(最大熵项等)不影响原先证明的成立。所以我直接使用传统策略迭代收敛证明来说明问题——很多年前读到这个证明时我还是个中学生,当时就是一眼一过:哦,它能收敛。然后就没再管了。可是现在再去看就不禁会想到问题,就像那位同学说的一样,这个证明过程是压根不考虑任务的,只是基于强化学习的假设,(你要做的这个任务的)状态划分符合马尔可夫过程,然后直接给出证明:在这个马尔科夫链上迭代,策略估计必然收敛。然后基于策略估计收敛推出算法整体收敛。实际上做过强化学习的同学都会有感觉,策略估计是非常关键的一步,也是非常容易出错的一步(动不动就训不动了)。它在压根不考虑任务的情况下,轻飘飘地就给出了收敛的结论,而且是“线性速度收敛”,这么好的事,它到底是怎么做的?它证明的“收敛”和我们说的是一回事吗?

对于策略估计的证明有一点复杂。我们尽量聚焦于需要关注的两个关键点:

1. 贝尔曼方程是个压缩映射

2. 如果是压缩映射,服从压缩映射定理,以线性速度收敛到唯一不动点

这个证明网上的解释有很多,但大多不直观。我用一个我的直观理解来不太严格地解释这两点。对于第一点,原证明过程为:

第一步中,a 与 a' 分别为 V1 与 V2 下的最优动作。第二步中,将后项放到前项的 max_a 中,相当于选择了一个在 V2 下更不好的动作。因此后项价值变小,整体变大,引入了不等号。把这个过程反过来思考就可以理解,应用贝尔曼算子后值会被压缩的关键原因就在于更优的动作会被更频繁选择(更优的策略会被更频繁应用),也就是Exploitation。实际做过强化学习的都知道,只有Exploitation不可能那么完美。

那该证明中是怎么处理Exploration的呢?这是在另一个部分,证明策略提升的过程:

q_{\pi}(s,a)=\sum_{s',r}p(s',r|s,a)[r+\gamma v_{\pi}(s')]

\pi(a|s)=argmax(q_{\pi}(s,a))

说白了就是遍历每个状态,然后又在每个状态下,遍历每个动作,分别计算被遍历到的状态下每个动作对应的价值 q_{\pi}(s,a),取使得价值最大的动作作为当前状态的最新策略——说到这你就知道为啥他这“证明”不用考虑任务而且只能用于离散情况了。因为他就是暴力把所有情况都看了一遍,连续的你就没法都看一遍了啊;P

再看看压缩映射定理中的所谓线性收敛速度:

f^n(x)-x^*=f^n(x)-f(x^*)<k(f^{n-1}(x)-x^*)<k^n(x-x^*)

这个就很好理解了。寻找不动点的迭代过程是在函数 f 的定义域上的(可以理解为状态空间或者策略空间)。这个所谓“线性收敛速度”给出的是一个上界,这个“线性复杂度”的n(式中的k^n(x-x^*))实际等同于定义域大小,即问题规模,虽然说起来是线性,但计算出这个组合数的过程是个指数!贴着这个上界实现的“强化学习算法”说白了和把“所有组合都试一遍就能找到最大最小值”没啥区别,所以这个上界对于大部分问题都没有实际意义。

相信大家都记得很多年前AI攻破国际象棋后,很多下围棋的人说计算机永远不可能攻破围棋,因为围棋的状态数比全宇宙粒子数都多。他们把状态数等同于问题难度,就和这个式子中的所谓“线性上界”没区别。但我们真的需要遍历每个状态吗?使用专门设计的算法,alphago只探测了状态空间的很小一部分,就成为了世界第一。这也是强化学习的核心:如何设计算法更高效地探测状态空间、更新策略。可能我们设计的算法不是线性复杂度,但我们的算法却比这个上界更快,因为二者的n根本就是不一样的!我们关心复杂度的目的是让它最后跑起来更快,而并非是那个式子表面上是个什么形状。这也是为什么我说前段时间很多OIer在空间刷屏的近似多项式最大流算法并不会对OI有什么改变(笑),因为里面用的技巧过于复杂,即使实现出来真实速度大概也不会快于当前主流方法。我们关心的“收敛性”,也是我们设计的这个探测算法是否能够收敛,而不是在考虑“把所有情况都看一遍”这个傻方法。如果有人看了这个看起来很高深的证明,就感觉所有强化学习算法都能收敛、所有强化学习算法都是线性复杂度,只能说他根本没搞清楚自己在干嘛。

数学家的炼丹

虽然那位同学不是数学工作者,我也不是数学工作者。但很多数学工作者也犯过类似的错误。相信大家都看过“计算机的终点是数学”这种说法,然后对搞数学的人很迷信。但真学数学的人就一定明白自己在干嘛吗?我看不是。不管是什么领域,真正懂的人都是很少的。我和很多学数学比较入魔的同学交流过类似神经网络的优化问题,但我非常坏,没告诉他我说的是神经网络,很多人就被我骗了,斩钉截铁地给我一个高深的手法:加这个约束,加那个平滑,然后根据某个高深的理论,就肯定能收敛。可是为什么机器学习界从来没有这种完美的方法,是因为搞计算机的对这些数学理论都一窍不通吗?其实道理很简单,任何东西都不是free的。只要加了约束,就必然会限制表达能力,限制了表达能力,就会影响梯度分布——就算待优化的流形再平滑,但大部分区域梯度都是0,在实际数据上没法work,又有什么用呢?他们之所以会犯这种错误,其实也是不明白自己在干嘛——我不说“神经网络”这个名词,光凭符号描述,他们就根本不知道面前的这个复杂系统到底是什么样的,从来没实现过自己的算法,不借助计算机的力量去看一看、试一试,只会用纸笔和脑子,这样是没法摸到复杂系统的形状的。这也是为什么那位同学能那么坚定地说出“存在完美学习算法”这种匪夷所思的结论——因为他也一样,压根没试过这些算法,没观察过训练过程,自己一想当然,就张冠李戴了。

还有一些同学是只能看到自己眼前的一点东西,搞一些真空中的球形理论,然后鄙视搞机器学习人,说他们都是“炼丹”。可炼丹是基于一些生产环境目前用不了的trick把效果提了几个点,你搞的是基于一些不现实的假设搞出的一些不知道什么时候才能用上的理论,谁又比谁高多少呢?在我看来,这些一瓶不满半瓶晃的数学学生搞的就是数学界的“炼丹”,和工业界胡写代码满嘴设计模式,机器学习界乱搭模型炼丹的计算机学生没什么区别。

我认识的一些同学,CMO获奖之后去了姚班,从此戴上了痛苦面具——自己数学那么好,搞数学不就完了,学这些计算机的东西干嘛?相信很多喜爱数学的同学都有这种想法。可是我觉得学习很重要的一点就是对知识要谦虚,永远保持好奇。很多人看了很多书和论文,记住了一些表面知识和吓人的术语,可是却没有深刻的理解它们后面的涵义。这时候编程其实是一个认识到自己错误的很好工具,因为你能用满嘴的术语骗过身边的同学,却骗不过计算机。即使是纯数学的理论,也可以用coq等定理证明器辅助学习。但你要是动手能力不高,遇到编程这类一点点困难就往后缩,长此以往,就很难学会真正的知识了。

我相信,在现在,一个不会写程序的“数学家”,成就永远无法超过计算机科学家。因为面对实际的复杂问题,很多东西不借助计算机的帮助,是根本无法看到的。认为数学不需要计算机、甚至鄙视计算机的人,其实只是被书本知识打倒,然后就臣服于它,可却没想到,从此被一叶障目,看不到背后更大的世界。

这篇关于Policy Evaluation的收敛性是怎么一回事的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/427073

相关文章

[职场] 护理专业简历怎么写 #经验分享#微信

护理专业简历怎么写   很多想成为一名护理方面的从业者,但是又不知道应该怎么制作一份简历,现在这里分享了一份护理方面的简历模板供大家参考。   蓝山山   年龄:24   号码:12345678910   地址:上海市 邮箱:jianli@jianli.com   教育背景   时间:2011-09到2015-06   学校:蓝山大学   专业:护理学   学历:本科

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

电脑不小心删除的文件怎么恢复?4个必备恢复方法!

“刚刚在对电脑里的某些垃圾文件进行清理时,我一不小心误删了比较重要的数据。这些误删的数据还有机会恢复吗?希望大家帮帮我,非常感谢!” 在这个数字化飞速发展的时代,电脑早已成为我们日常生活和工作中不可或缺的一部分。然而,就像生活中的小插曲一样,有时我们可能会在不经意间犯下一些小错误,比如不小心删除了重要的文件。 当那份文件消失在眼前,仿佛被时间吞噬,我们不禁会心生焦虑。但别担心,就像每个问题

ABAP怎么把传入的参数刷新到内表里面呢?

1.在执行相关的功能操作之前,优先执行这一段代码,把输入的数据更新入内表里面 DATA: lo_guid TYPE REF TO cl_gui_alv_grid.CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'IMPORTINGe_grid = lo_guid.CALL METHOD lo_guid->check_changed_data.CALL M

电子盖章怎么做_电子盖章软件

使用e-章宝(易友EU3000智能盖章软件)进行电子盖章的步骤如下: 一、准备阶段 软件获取: 访问e-章宝(易友EU3000智能盖章软件)的官方网站或相关渠道,下载并安装软件。账户注册与登录: 首次使用需注册账户,并根据指引完成注册流程。注册完成后,使用用户名和密码登录软件。 二、电子盖章操作 文档导入: 在e-章宝软件中,点击“添加”按钮,导入待盖章的PDF文件。支持批量导入多个文件,

说一说三大运营商的流量类型,看完就知道该怎么选运营商了!

说一说三大运营商的流量类型,看完就知道该怎么选运营商了?目前三大运营商的流量类型大致分为通用流量和定向流量,比如: 中国电信:通用流量+定向流量 电信推出的套餐通常由通用流量+定向流量所组成,通用流量比较多,一般都在100G以上,而且电信套餐长期套餐较多,大多无合约期,自主激活的卡也是最多的,适合没有通话需求的朋友办理。 中国移动:通用流量+定向流量 移动推出的套餐通常由通用流量+定向

js小题:通过字符串执行同名变量怎么做

在JavaScript中,你不能直接使用一个字符串来直接引用一个变量,因为JavaScript是一种静态类型语言(尽管它的类型在运行时可以变化),变量的名字在编译时就被确定了。但是,有几种方法可以实现类似的功能: 使用对象(或Map)来存储变量: 你可以使用一个对象来存储你的变量,然后使用字符串作为键来访问这些变量。 let myVars = { 'var1': 'Hello', 'var

vue怎么处理跨域

Vue.js 本身并不直接解决跨域问题,因为跨域问题主要是浏览器基于同源策略(Same-origin policy)的一种安全限制。然而,在Vue.js项目中,我们可以采取一些策略来绕过或处理跨域问题。 解决跨域问题的常用方法: 代理服务器:在开发环境中,我们可以配置一个代理服务器来转发API请求,从而绕过浏览器的同源策略。Vue CLI 提供了内置的代理功能,可以在 vue.config.j

又看见定时器了,怎么这么想写了~~

1.scheduleUpdate(); 与virtual void update(float dt);   联合使用,就是每隔一段时间就调用一次update,实际上是每一帧都调用一次updata方法,scheduleUpdate();方法相当于开启了定时器。 2.schedule的作用和scheduleUpdate差不多,只是这个其实更好用一些,这个可以只是指定调用的方法,系统默认每一帧都调用一

今天又有了别的收获。青云怎么这么厉害呢- -。。感觉无论付出多么大的努力,和他差不多就行~~

1.第一个收获就是一个宏这个宏第一个参数是函数的类型,第二个是名字,第三个其实就是setRow(),getRow(),两个方法,为的就是让我们得到对象。嘿嘿,收获不小~~ 2.比如我们定义了一个宏#define WC (6) 我们调用一个方法,suShi->m_imgIndex=rand()%WC  ;表示取0-WC-1的整数值。。 3.为了更好的适配各种环境在applicatio