当前位置: 首页 > 编程日记 > 正文

基于模型的强化学习比无模型的强化学习更好?错!

作者 | Carles Gelada and Jacob Buckman

编辑 | DeepRL

来源 | 深度强化学习实验室(ID:Deep-RL)

【导读】许多研究人员认为,基于模型的强化学习(MBRL)比无模型的强化学习(MFRL)具有更高的样本效率。但是,从根本上讲,这种说法是错误的。更细微的分析表明,使用神经网络时,MBRL方法可能比MFRL方法具有更高的采样效率,但仅适用于某些任务。此外,而基于模型的RL仅仅是开始。另一类算法,即基于同态的强化学习(HBRL),可能具有在诸如视觉干扰等具有高水平无关信息的任务上进一步提高样本效率的潜力。在这篇文章中,我们为这些想法提供了直观的证明。
  • Equivalence Between Model-based and Model-free RL
“基于模型的方法比没有模型的方法更具样本效率。”近年来,这种经常重复的格言在几乎所有基于模型的RL论文(包括Jacob论文)中都引起关注。如此常识,没有人甚至不介意在旁边加上引文,陈述的真实性是不言而喻的。很明显,但是这是错误的。实际上,在很多情况下,两种方法的采样效率是相同的。
在比较两种方法在给定转换数据集时学习的值函数时,可以看出MBRL和MFRL之间的等效性。无模型方法是通过TD学习直接学习此值函数。相反,基于模型的方法是通过学习转换模型然后展开来隐式地学习此值函数。折扣奖励的总和为我们带来了价值。给定相同的转换数据集,这两种方法中的每一种都将计算出真实值函数的近似值。当数据丰富时,两种方法都将给出接近完美的近似值。算法的采样效率是指随着越来越多的数据可用,逼近误差降低的速度。
这两种算法在表面上看起来非常不同,因此期望误差以不同的速率减小。但是,正如Parr 2008中所证明的那样,在表格和线性设置中,这两种方法不仅具有相同的比率,而且实际上产生了完全相同的值函数!这两种方法是等效的。基于模型的方法并没有使它更有效地采样的基础。
但是,即使知道了这种等效性,许多研究人员仍然有很强的直觉,即学习环境模型会更好。我们同意!让我们尝试进一步探索这种直觉,以便我们更好地了解它可能存在或可能不存在的地方。
  • The Simpler, the Sample-efficient-er


首先,我们要强调一个基本原则,该原则是这篇文章中争论的核心,对任何训练过神经网络的人来说都是熟悉的。在几乎所有任务上,训练神经网络达到良好性能所需的数据量或多或少与任务的难度成正比,这是通过与“正确答案”相对应的函数的复杂性来衡量的 。训练神经网络以预测所有输入的恒定输出仅需要几个数据点;在实现了MNIST的准确分类;ImageNET需要数百万。
  • A Motivating Example: City Navigation


考虑在城市中导航的任务,我们将其视为RL问题。在每个情节的开始处,都会生成一个地图,并采样特工和目标的初始位置。状态空间是城市网格的自上而下的像素表示。为了获得奖励,必须通过选择向上,向下,向左或向右操作从起点到目标点。让我们考虑使用无模型技术和基于模型的技术来解决此MDP的需要。
对于无模型方法,我们尝试学习值函数:从状态空间直接映射到每个动作的值的神经网络。但是,这将是相当困难的学习。这个城市就像迷宫一样,添加(或删除)一条小捷径,甚至离特工或目标不远,都会大大改变特工的预期回报。因此,两个相似的状态可能具有截然不同的值。换句话说,值函数是状态的高度复杂函数。由于该值函数并不简单,因此需要大量数据才能通过神经网络对其进行近似。
基于模型的方法更直观地接近于人类如何理解任务。在第二种方法中,我们训练了一个神经网络来近似环境的回报和转变。一旦了解了近似模型,就可以通过计划来提取最佳策略(即使用该模型从不同操作中推出期货,并采取预期收益最高的操作)。从一般化的角度来看,在此任务上使用基于模型的方法的好处显而易见。简单的动态变化(即,除非存在隔离墙,否则将主体沿动作的方向移动)会为过渡和奖励模型带来简单的学习目标。由于我们正在学习一个简单的函数,因此不需要太多的数据即可获得良好的性能,因此采样效率更高。


So What Changed?


为什么这个论点成立,而不是成为上述等同论的牺牲品?关键是神经网络。Parr(2008)描述的等效项仅存在于表格和线性设置中。当真值函数和真动力学都是状态空间的线性函数时,很明显,两者都不比另一个更简单!但是,当我们的状态空间是高维的并且我们的函数类是神经网络时,我们选择学习的函数的复杂性会对成功获取多少样本产生重大影响。样本效率的任何收益或损失都与泛化行为密切相关。
此外,这种解释使我们了解了当我们转向基于模型的强化学习时,我们期望在样本效率方面提高哪些任务。简而言之,在具有简单动态特性但复杂的最佳策略的任务中,对动态特性的了解比对最佳策略进行强行强制更为有效。但至关重要的是,请注意,并非所有任务都如此!考虑对城市导航示例的修改,该示例通过GPS导航方向扩大了观察空间。这是最佳策略比动态过程更简单的任务示例;因此,一项无模型学习的任务将更加高效。
可以很直观地看出,某些MDP更易于解决基于模型或不基于模型的问题,但是要严格理解这一区别,还有很多工作要做。Dong等人已经开始将该概念形式化,证明存在许多MDP,其策略和Q功能比动态过程更复杂。希望将来的工作将继续在这些思想的基础上进行,最终画出如何表征差异的清晰画面。
  • Modeling in a More Realistic Setting


但是基于模型的模型与没有模型的模型只是一部分。上面的导航任务适合模型学习,因为它的动态过程简单明了。但是在现实世界中,事情通常并不那么干净。考虑相同迷宫任务的一种变体,但是渲染得更真实,就像输入像素是由相机提供的一样:
尽管任务从根本上没有改变,但是在这种环境下学习动力学模型要困难得多。由于状态空间由像素表示,因此对下一个状态的预测要求我们预测屏幕上每个像素如何响应我们的动作而变化。我们需要逐个像素地预测烟雾如何从烟囱中漂浮出来,阴影如何在地面上流动,无论体育场中的足球队是否得分。即使我们可以学习这样的模型(对于有限容量的神经网络来说,这也不是一件容易的事),我们也需要大量的数据才能很好地概括。现实世界非常复杂,因此任何尝试使用神经网络对现实世界进行建模的算法都将遭受极其差的采样效率的困扰。
  • Homomorphism-Based RL(同态)


增加视觉复杂性大大增加了问题难度的想法似乎并不能反映人类的经验。视觉上在导航问题上添加树木和汽车并没有改变您对问题的看法,也没有改变您提出解决方案的能力。即使不知道烟雾和阴影的精确运动,人类仍然可以使用任务模型。我们了解重要的事物,并且了解重要事物的动态。
换句话说,人类有能力直观地将视觉上嘈杂的现实城市网格缩小为等效的简化版本。更一般而言,对于几乎所有任务,人们都可以将凌乱的高维现实世界状态投影为干净的低维表示形式。至关重要的是,这些表示仅包含原始状态的与任务相关的功能,并丢弃所有无用的复杂性。完全没有任何噪音,冗余等。在这些表示所定义的潜在空间中,动力学再次变得非常简单,我们可以轻松,高效地进行计划。
我们将此想法称为基于同态的RL(HBRL)。这代表了我们可以设计强化学习算法的第三个范式。“同态”这个名称源于对所学表示空间的数学解释,它是简化的MDP,与环境MDP是同态的(等效形式)。在具有复杂的价值函数和状态动态,但具有简单的基础任务动态的任务中,我们应该期望基于同态的RL将是最高效的样本学习方法。
当然,正如我们在前面对MFRL与MBRL的讨论中所看到的那样,HBRL并不总是最好的解决方案。例如,如果我们尝试解决一个非常简单的环境(例如之前的简化城市任务),则HBRL通常比MBRL需要更多的数据,因为该算法将需要许多数据点,只是为了认识到最佳的潜在空间就是状态空间本身。当然,即使在现实的城市环境中,GPS方向仍将导致无模型学习比任何其他方法更有效地进行采样。
但是,当涉及到现实世界中的任务时,从直观上看,它们中的绝大多数将类似于现实中的城市任务。现实世界是一个视觉复杂的地方,很少给出“分步说明”。因此,我们认为,基于潜在模型的RL的进步可能会大大加速现实环境中的样本有效学习。

  • Homomorphism-Based RL vs. Latent-Space Modeling


如果您一直在关注深度强化学习的最新趋势,那么“学习等效但简化的潜在空间模型”的想法可能对您来说似乎很熟悉。实际上,从表面上看,诸如World Models(Ha等人)和PlaNet(Hafner等人)的最新著作似乎与我们对基于同态的RL的上述定义相符。但是,有一个关键的区别。
HBRL背后的核心思想是,状态的良好表示不需要包含与任务无关的信息。如果我们强迫潜在空间对状态空间的任意信息进行编码(例如,通过最大程度地减少重建损失),则在状态空间复杂的环境中会遇到困难(与MBRL所遇到的困难基本相同)。前面提到的方法都包括状态重建或下一状态预测损失,因此它们的最佳特征是使用潜变量而不是HBRL进行MBRL。

Previous Work on Homomorphic MDPs


在过去的几十年中,有几本著作探索了这些想法。MDP同态和状态抽象都提出了良好的数学基础,及考虑信息与任务相关意味着什么。这些研究方向导致了基于通过聚合学习状态表示的表格RL算法。
但是,此博客的大多数读者很可能从未听说过这些论文。这是因为尽管算法复杂得多,但这些方法从未显示出比简单方法有所改进。出现这种缺陷的原因:就像在表格设置中基于模型的学习和无模型的强化学习一样,这些方法也是如此。由于所有技术在根本上都是等效的,因此没有理由引入状态抽象的额外复杂性。
但是再一次,当涉及到神经网络时,情况就不同了。由于有效的概括成为提高采样效率的关键,因此在许多环境中学习状态抽象要比替代方法的采样效率高得多。具体地说,对于状态空间中具有大量与任务无关的信息的环境,例如上一节中介绍的实际城市导航任务,就是这种情况。
不幸的是,由于许多这些技术都与表格环境紧密相关,因此在使它们适应现代深度强化学习环境方面几乎没有取得任何进展。我们认为这是深度强化学习中最有前途的研究途径之一。在我们最近的ICML论文中,我们为与神经网络兼容的一类同态RL算法奠定了理论基础。我们提出了理解重要问题的问题,即学习针对MDP状态的神经嵌入函数的问题。然后,了解重要的动力学对应于学习由嵌入函数定义的潜在空间中动力学的神经模型。Carles决定将此框架称为“ DeepMDP”,但回想起来,这个名称很糟糕,我们希望我们将其命名为其他名称。
  • Latent Planning with DeepMDPs


DeepMDP由一组三个函数组成,每个函数都由一个神经网络表示:一个嵌入函数 (从状态映射到潜在表示),一个奖励函数(从映射到潜在表示) -状态和要奖励的动作,以及从潜在状态和动作映射到下一个潜在状态的转换函数(这后两个有时统称为“潜在空间模型”。)
至关重要的是,通过最小化两个目标函数来训练DeepMDP,一个目标函数用于奖励直观地,在给定状态和动作的情况下,这些函数测量实际奖励/转换函数的结果与潜在奖励/转换函数的结果之间的距离。这些目标如下所示:

What Guarantees Can We Obtain?


最小化这些目标可以获得两个有价值的属性:
  • 嵌入功能将仅丢弃状态的与任务无关的信息。
  • 潜在空间模型和实际MDP的嵌入状态遵循完全相同的动力学,这意味着过渡和收益始终完美地吻合。
从直观上清楚地知道,最小化DeepMDP目标如何满足第二个属性。本质上,我们强制嵌入和转换函数,并且状态和潜在状态具有相同的收益。换句话说,我们正在实施环境的MDP和DeepMDP之间的同构。
但是,必须满足属性(1)的情况要少得多。为了证明这一点,我们借助双仿真指标(我们前面提到的RL表示学习的数学基础之一)来分析经过训练的DeepMDP的属性。双仿真度量标准度量任何两个状态之间的“行为相似性”概念。在这些度量标准下,如果两个州拥有立即和未来奖励的相似分布,则它们之间的距离很小。仅两个视觉状态有所不同而不会影响游戏动力学的状态(例如下面的ASTEROIDS图中不同的小行星颜色),任何两个状态的模拟距离均为0。因此,我们的第一个目标可以理解为学习嵌入尊重双仿真的函数:换句话说,一个嵌入函数仅在状态之间的双仿真距离为0时才将状态折叠在一起。令人惊讶的是,我们可以在数学上保证通过最小化DeepMDP来学习的任何嵌入函数都是这种情况目标。

Global vs. Local Losses

注意,以上目标是功能;他们给我们每个状态和每个动作带来损失。MDP包含许多状态和动作,并且为了应用优化算法,我们需要将这些每个状态动作损耗编译为单个标量损耗值。在本文中,我们首先研究了在整个国家行动空间中所有损失的极小值的最小化,我们称其为全球DeepMDP损失。当使全局DeepMDP损失最小化时,必须做两件事。

  • 保证学习的嵌入函数遵守双仿真。
  • 保证DeepMDP是真实环境的准确模型。

不幸的是,实际上不可能将最小化。使用状态和动作的期望值对神经网络进行训练,该期望值是从分布中采样的。因此,我们还研究了由局部DeepMDP损失最小化提供的保证,这些保证是通过考虑状态作用分布下损失函数的期望来计算的。(之所以如此命名,是因为它们相对于所述分布“局部”地测量了损失。)就像在全局情况下一样,我们证明了当本地DeepMDP损失最小时,DeepMDP被保证是真实环境的准确模型。。
不幸的是,本地损失与双模拟指标之间没有联系。这是因为经典的双仿真本质上取决于整个状态操作空间。我们推测存在双模拟量度的局部变体,这将使我们能够充分了解DeepMDP(正在进行的工作)所学习的表示形式。

Empirical Results

由于DeepMDP与神经网络完全兼容,因此自然而然地需要在标准的深度RL基准测试中对其进行测试。到目前为止,我们仅探讨了DeepMDP的表示学习方面。为此,我们对标准Atari 2600代理程序进行了简单的修改:我们选择了Q函数神经网络的中间层作为DeepMDP潜在空间,并添加了奖励和过渡模型,这些模型是使用局部DeepMDP损失进行训练的 。在大多数Atari 2600游戏中都可以看到性能的大幅提高,这归因于尊重双仿真指标的表示形式(请参见本文的定理3)。

但是,要充分展示这种方法的潜力,仍需通过实验证明,使用模型进行规划可以以示例高效的方式成功解决具有挑战性的视觉复杂环境。这是当前工作的主题;我们有一些令人鼓舞的初步结果,希望不久后发布。
原文链接:
https://jacobbuckman.com/2019-10-25-three-paradigms-of-reinforcement-learning/

(*本文为AI科技大本营转载文章,转载联系作者


精彩推荐



开幕倒计时12天|2019 中国大数据技术大会(BDTC)即将震撼来袭!豪华主席阵容及百位技术专家齐聚,十余场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读。6.6 折票限时特惠(立减1400元),学生票仅 599 元!


推荐阅读
  • 马斯克发首款会上火星的电动皮卡:28万起,可防弹,造型相当“赛博朋克”

  • 数据库的前世今生

  • 一位身价10亿程序员的传奇一生

  • 炸了!刚写完这段代码,就被开除了!

  • 硬核科普!携号转网的技术原理分析!

  • AutoML未来可期,工程师的明天何去何从?

  • 揭秘支撑双 11 买买买背后的硬核黑科技!

  • 假如有人把支付宝存储服务器炸了

  • 腾讯程序员失业 3 个月,靠送外卖谋生:职场半坡,生存事大!

  • 不得不看之跳槽加薪利器:2019需求最旺盛的十大IT技能

  • 你点的每个“在看”,我都认真当成了AI

相关文章:

程序员的自我修养--链接、装载与库笔记:内存

1. 程序的内存布局 现代的应用程序都运行在一个内存空间里,在32位的系统里,这个内存空间拥有4GB(2的32次方)的寻址能力。应用程序可以直接使用32位的地址进行寻址,这被称为平坦(flat)的内存模型。在平坦的内存模型中,整个内存是一…

【Away3D代码解读】(四):主要模块简介

数据模块: Away3D中最核心的数据类是Mesh类,我们先看看Mesh类的继承关系: NamedAssetBase:为对象提供id和name属性,是Away3D大部分类的基类; Object3D:3D对象基类,提供方便操作3D对象…

程序员的自我修养--链接、装载与库笔记:运行库

1. 入口函数和程序初始化 程序从main开始吗?:操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些别的代码,这些代码负责准备好main函数执行所需要的环境,并且负责调用main函数,这…

iOS下JS与OC互相调用(三)--MessageHandler

使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。 MessageHandler 是什么? WKWebView 初始化时,有一个参数叫…

北大教授张大庆:无线感知,让你变老也优雅

受访者 | 张大庆记者 | 胡巍巍出品 | CSDN(ID:CSDNnews)在国内高校中,北大的校庆日很特殊——5月4日。这一天,也是青年节。北大,是五四运动的策源地。100年来,“爱国、进步、民主、科学”的五四…

总结 20 个开发细节

2019独角兽企业重金招聘Python工程师标准>>> 1:提交到SVN的代码必须有提交备注,以便于以后查看。 2:如考虑页面缓存,可以在路径后增加随机数:url "&TimeS" Math.random();。 3:…

程序员的自我修养--链接、装载与库笔记:系统调用与API

系统调用(System Call)是应用程序(运行库也是应用程序的一部分)与操作系统内核之间的接口,它决定了应用程序是如何与内核打交道的。无论程序是直接进行系统调用,还是通过运行库,最终还是会到达系统调用这个层面上。 1. 系统调用介绍 什么是…

iOS下JS与OC互相调用(四)--JavaScriptCore

前面讲完拦截URL的方式实现JS与OC互相调用,终于到JavaScriptCore了。它是从iOS7开始加入的,用 Objective-C 把 WebKit 的 JavaScript 引擎封装了一下,提供了简单快捷的方式与JavaScript交互。 关于JavaScriptCore的使用有两篇很好的文章&…

围巾都这么黑科技了,是我见识少了

有一个永恒的话题:北方冷一点还是南方冷一点?答案是:哪里都冷!冬天最痛苦的莫过于走出空调房——刺骨的风直直的从领口处灌进去那叫一个“透心凉,心飞扬”缠了好几圈的大围巾却根本没什么保暖效果每当这时候&#xff0…

【教程】【FLEX】#004 反射机制

总结: 目前用到反射的主要有两个方法 1. getDefinitionByName //根据类名,返回对象(反射实例化对象) 2. describeType //根据对象,返回XML格式的属性,方法等信息(反射得到…

iOS下JS与OC互相调用(五)--UIWebView + WebViewJavascriptBridge

WebViewJavascriptBridge是一个有点年代的JS与OC交互的库,使用该库的著名应用还挺多的,目前这个库有7000star。我去翻看了它的第一版本已经是4年前了,在版本V4.1.4以及之前,该库只有一个类和一个js 的txt文件,所以旧版…

OpenCV代码提取:Windows上通过DShow获取Camera视频

在OpenCV 3.1中获取视频的模块在videoio(video input and output module)中,调用VideoCapture类接口,除了videoio模块外还依赖core、highgui、imgproc、imgcodecs四个模块,而OpenCV 2.4.13.6仅需要core、highgui、imgproc三个模块。3.1中的vi…

迁移学习与图神经网络“合力”模型:用DoT-GNN克服组重识别难题

作者 | Ziling Huang、Zheng Wang、Wei Hu、Chia-Wen Lin、Shin’ichi Satoh译者 | 刘畅编辑 | Jane出品 | AI科技大本营(ID:rgznai100)【导读】目前,大多数行人重识别(ReID)方法主要是从收集的单个人图像数…

struts2 select 默认选中

jsp:<s:select list"#{1:男,2:女}" name"sex"/> action:private String sex;sex属性有get/set方法。在业务方法中设置sex "2";select会默认选中。

通过Windows DShow获取设备名、支持的编解码及视频size列表实现

之前在https://blog.csdn.net/fengbingchun/article/details/102641967中介绍过通过DShow获取Camera视频的实现&#xff0c;即调用VideoCapture类。在OpenCV的VideoCapture类中并没有提供获取Camera设备列表、支持的编解码类型列表及支持的video size列表接口&#xff0c;这里基…

15篇论文全面概览BERT压缩方法

作者 | Mitchell A. Gordon译者 | 孙薇出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;模型压缩可减少受训神经网络的冗余——由于几乎没有BERT或者BERT-Large模型可用于GPU及智能手机上&#xff0c;这一点就非常有用了。另外&#xff0c;内存与推理速度的提高也能节…

iOS下JS与OC互相调用(七)--Cordova 基础

Cordova 简介 在介绍Cordova之前&#xff0c;必须先提一下PhoneGap。PhoneGap 是Nitobi软件公司2008年推出的一个框架&#xff0c;旨在弥补web 和iOS 之间的不足&#xff0c;使得web 和 iPhone SDK 之间的交互更容易。后来又加入了Android SDK 和BlackBerry SDK&#xff0c;再然…

在linux上MySQL的三种安装方式

安装MySQL的方式常见的有三种&#xff1a;方式一&#xff1a;rpm安装(1) 操作系统发行商提供的(2) MySQL官方提供的&#xff08;版本更新&#xff0c;修复了更多常见BUG&#xff09;www.mysql.com/downloads关于MySQL中rpm包类型的介绍&#xff1a;MySQL-client 客户端…

通过libjpeg-turbo实现对jpeg图像的解码

之前在https://blog.csdn.net/fengbingchun/article/details/89715416中介绍过通过libjpeg-turbo接口实现将数据编码或压缩成jpeg数据并通过FILE的fwrite接口将其直接保存成*.jpg图像&#xff0c;当时用的是libjpeg的接口&#xff0c;其实还可以使用turbojpeg api的接口即tjCom…

AI+大数据顶级技术盛会开幕在即,6.6折特惠票限时抢购

2019年12月5-7日&#xff0c;由中国计算机学会主办&#xff0c;CCF 大数据专家委员会承办&#xff0c;CSDN、中科天玑数据科技股份有限公司协办的中国大数据技术大会&#xff08;BDTC 2019&#xff09;将于北京长城饭店隆重举行。届时&#xff0c;超过百位顶尖技术专家将齐聚于…

iOS下JS与OC互相调用(八)--Cordova详解+实战

1.新建工程&#xff0c;添加Cordova 关键类 我这里用Xcode 8 新建了一个工程&#xff0c;叫 JS_OC_Cordova,然后将Cordova关键类添加进工程。 有哪些关键类呢&#xff1f; 这里添加config.xml 、Private 和 Public 两个文件夹里的所有文件。工程目录结构如下&#xff1a; 然后…

iOS多线程编程之NSOperation和NSOperationQueue的使用

使用 NSOperation的方式有两种&#xff0c; 一种是用定义好的两个子类&#xff1a; NSInvocationOperation 和 NSBlockOperation。 另一种是继承NSOperation 如果你也熟悉Java&#xff0c;NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一样&#xff0c;NSOpe…

Swift - 使用SwiftHTTP通过HTTPS进行网络请求,及证书的使用

&#xff08;本文代码已升级至Swift3&#xff09;一&#xff0c;证书的生成&#xff0c;以及服务器配置参考我前面写的这篇文章&#xff1a;Tomcat服务器配置https双向认证&#xff08;使用keytool生成证书&#xff09;文章详细介绍了HTTPS&#xff0c;SSL/TLS。还有使用key to…

Linux下通过v4l2获取视频设备名、支持的编解码及视频size列表实现

早些时候给出了在Windows下通过dshow获取视频设备信息的实现&#xff0c;包括获取视频设备名、获取每种视频设备支持的编解码格式列表、每种编解码格式支持的video size列表&#xff0c;见&#xff1a;https://blog.csdn.net/fengbingchun/article/details/102806822 下面给出…

12种主流编程语言输出“ Hello World ”,把我给难住了!

作为一名程序员&#xff0c;在初步学习编程想必都绕不开一个最为基础的入门级示例“Hello World”&#xff0c;那么&#xff0c;你真的了解各个语言“Hello World”的正确写法吗&#xff1f;在我们刚开始打开编程世界的时候&#xff0c;往往写的第一个程序都是简单的文本输出&a…

军哥lnmp一键安装包nginx支持pathinfo配置

ssh里执行&#xff1a;cat > /usr/local/nginx/conf/pathinfo.conf << EOF set $real_script_name $fastcgi_script_name; if ($fastcgi_script_name ~ "(.?\.php)(/.*)") { set $real_script_name $1; set $path_info $2; } fastcgi_param SCRIPT_FILENAM…

Effective STL 50条有效使用STL的经验笔记

Scott Meyers大师Effective三部曲&#xff1a;Effective C、More Effective C、Effective STL&#xff0c;这三本书出版已很多年&#xff0c;后来又出版了Effective Modern C。 Effective C的笔记见&#xff1a;https://blog.csdn.net/fengbingchun/article/details/102761542…

HTTPS网络加密双向验证-使用AFNetworking封装

1.首先使用OC封装请求头 #import <Foundation/Foundation.h> #import "AFNetworking.h" interface HttpsHandler : NSObject (AFHTTPSessionManager *)setHttpsMange; end 2.实现方法 (AFHTTPSessionManager *)setHttpsMange; { NSString *certFilePath […

30分钟搞定数据竞赛刷分夺冠神器LightGBM!

作者 | 梁云1991来源 | Python与算法之美&#xff08;ID:Python_Ai_Road)【导读】LightGBM可以看成是XGBoost的升级加强版本&#xff0c;2017年经微软推出后&#xff0c;便成为各种数据竞赛中刷分夺冠的神兵利器。一&#xff0c;LightGBM和XGBoost对比正如其名字中的Light所蕴含…

js模块化例子

最近在看一本书&#xff0c;里面提到js的模块化&#xff0c;觉得很有必要&#xff0c;所以记录下来 Game.js /*** This is the main class that handles the game life cycle. It initializes* other components like Board and BoardModel, listens to the DOM events and* tr…