2018年openAI公司搞了一个比赛retro contest,该比赛目的是为了在自家的库retro上测试迁移强化学习的性能,虽然这个比赛已经结束多年但是现在了解一些也是有一定益处的。

比赛细节介绍,原网址:

https://contest.openai.com/2018-1/details/#get-roms

===========================================================

比赛游戏的训练集:

You are free to train your agent however you'd like, but we recommend using Sonic 1, 2, and 3 & Knuckles, which are available on Steam here:

刺猬索尼克1、刺猬索尼克2、刺猬索尼克3   (这三个游戏需要在steam上购买并下载,具体参看:如何使用Python环境下的2D经典游戏仿真器(openai推出的)retro库运行游戏"刺猬索尼克" (SonicTheHedgehog-Genesis)    )

训练集(上面上个游戏中分别取不同游戏的不同状态作为训练的起始状态):

验证集(上面上个游戏中分别取不同游戏的不同状态作为训练的起始状态):

============================================================

比赛的评价环境:

硬件环境:

6 E5-2690v3 cores, 56GB of RAM, and a single K80 GPU

训练时间:

12 hours of time you should average ~43ms per timestep to get to 1 million timesteps within the limit

一个step的耗时为43毫秒。

The environment runs at ~1000 frames per second for a single core with random agent, meaning 1ms per frame, or 4ms per timestep, leaving you 39ms for your processing.

由于在测试时也进行训练同时测试时动作选择也是需要计算的,而一个不需要计算和训练的random agent一秒钟大约会和环境交互1000次(1000帧),如果训练的话这1000帧画面就是1000/4=250 timestep,也就是4毫秒一个timestep,由此可以估算出不进行动作选择计算和训练的random agent一个timestep耗时4ms,那么进行动作选择计算和训练的时间大致为43-4=39毫秒。

这里面有个容易搞不懂的地方,那就是为什么1000帧画面是250个timestep,中间的这个4倍是哪里来的。这里起始有个frameskip的操作,就是agent给出一个动作后起始是连续用这个动作进行4次交互的而不是一次,那么4次交互的画面我们只选择第一个画面,这样的话一共和环境交互了1000个frame,而这最后我们是只抽取其中的250个frame作为训练,而这250个frame再单步滑动的4个frame组成一个timestep,因此1000个frame最后形成了250个timestep。

The environment is stochastic in that it has sticky frameskip. While normal frameskip always repeats an action n times, sticky frameskip occasionally repeats an action n+1 times. When this happens, the following action is repeated one fewer times, since it is delayed by an extra frame. For the contest, sticky frameskip repeats an action an extra time with probability 0.25.

frameskip操作本身进行动作重复选择时可以加入概率随机性,具体参看(Revisiting the Arcade Learning Environment: Evaluation Protocols and Open Problems for General Agents):https://arxiv.org/pdf/1709.06009.pdf

Your agent is allowed to learn (adjust its weights, use a replay buffer, etc) during test time, although a separate copy of the agent will be run on each test level.

每次测试都进行训练,但是每次测试时使用的agent都是完全独立的,也就是说每次的测试agent都是训练agent的完全拷贝。

In addition you are limited to 4,500 timesteps per episode, corresponding to 18,000 frames or 5 minutes of real time at 60 fps.

不论是训练还是测试的时候对每一个回合的长度进行限制,每个回合最多timestep为4500, 也就是和环境交互18000个frame。对episode长度进行限制以防止有的episode进入无法终止的情况。

====================================================

The reward your agent receives is proportional to its progress to the predefined horizontal offset within each level, positive for getting closer, negative for getting further away. If you reach the offset, the sum of your rewards will be 9000. In addition there is a time bonus that starts at 1000 and decreases learning to 0 at the end of the time limit, so beating the level as quickly as possible is rewarded.

奖励函数的设定,奖励函数和水平位移相关,agent距离设定的位移越近reward越大,距离越远reward越小。

关于对游戏中的奖励函数设定和游戏终止条件的判断是很复杂的,尤其是在 “刺猬索尼克”这样的游戏中,奖励函数的设定对游戏性能有较大的影响。

查看contest.json内容:

路径:~/anaconda3/envs/baselines/lib/python3.7/site-packages/retro/data/stable/SonicTheHedgehog-Genesis

contest.json

{
"done": {
"script": "lua:contest_done"
},
"reward": {
"script": "lua:contest_reward"
},
"scripts": [
"script.lua"
]
}

可以看到游戏终结的判断函数为lua脚本script.lua中设定的contest_done函数,reward函数则是script.lua中的contest_reward函数:

script.lua

level_max_x = {
-- Green Hill Zone
["zone=0,act=0"] = 0x2560,
["zone=0,act=1"] = 0x1F60,
["zone=0,act=2"] = 0x292A, -- Marble Zone
["zone=2,act=0"] = 0x1860,
["zone=2,act=1"] = 0x1860,
["zone=2,act=2"] = 0x1720, -- Spring Yard Zone
["zone=4,act=0"] = 0x2360,
["zone=4,act=1"] = 0x2960,
["zone=4,act=2"] = 0x2B83, -- Labyrinth Zone
["zone=1,act=0"] = 0x1A50,
["zone=1,act=1"] = 0x1150,
["zone=1,act=2"] = 0x1CC4, -- Star Light Zone
["zone=3,act=0"] = 0x2060,
["zone=3,act=1"] = 0x2060,
["zone=3,act=2"] = 0x1F48, -- Scrap Brain Zone
["zone=5,act=0"] = 0x2260,
["zone=5,act=1"] = 0x1EE0,
-- ["zone=5,act=2"] = 000000, -- does not have a max x
} function level_key()
return string.format("zone=%d,act=%d", data.zone, data.act)
end function clip(v, min, max)
if v < min then
return min
elseif v > max then
return max
else
return v
end
end data.prev_lives = 3 function contest_done()
if data.lives < data.prev_lives then
return true
end
data.prev_lives = data.lives if calc_progress(data) >= 1 then
return true
end return false
end data.offset_x = nil
end_x = nil function calc_progress(data)
if data.offset_x == nil then
data.offset_x = -data.x
end_x = level_max_x[level_key()] - data.x
end local cur_x = clip(data.x + data.offset_x, 0, end_x)
return cur_x / end_x
end data.prev_progress = 0
frame_limit = 18000 function contest_reward()
local progress = calc_progress(data)
local reward = (progress - data.prev_progress) * 9000
data.prev_progress = progress -- bonus for beating level quickly
if progress >= 1 then
reward = reward + (1 - clip(scenario.frame / frame_limit, 0, 1)) * 1000
end
return reward
end data.xpos_last_x = nil function xpos_done()
if data.lives < data.prev_lives then
return true
end
data.prev_lives = data.lives if scenario.frame >= frame_limit then
return true
end return data.x > level_max_x[level_key()]
end function xpos_rew()
if data.xpos_last_x == nil then
data.xpos_last_x = data.x
end
local result = data.x - data.xpos_last_x
data.xpos_last_x = data.x
return result
end

其中,level_max_x中给出不同游戏状态开始的游戏中最终的终点x轴的距离(如:0x2560 则是变量地址,该地址的变量则是游戏终点的x轴上位置)

level_max_x = {
-- Green Hill Zone
["zone=0,act=0"] = 0x2560,
["zone=0,act=1"] = 0x1F60,
["zone=0,act=2"] = 0x292A, -- Marble Zone
["zone=2,act=0"] = 0x1860,
["zone=2,act=1"] = 0x1860,
["zone=2,act=2"] = 0x1720, -- Spring Yard Zone
["zone=4,act=0"] = 0x2360,
["zone=4,act=1"] = 0x2960,
["zone=4,act=2"] = 0x2B83, -- Labyrinth Zone
["zone=1,act=0"] = 0x1A50,
["zone=1,act=1"] = 0x1150,
["zone=1,act=2"] = 0x1CC4, -- Star Light Zone
["zone=3,act=0"] = 0x2060,
["zone=3,act=1"] = 0x2060,
["zone=3,act=2"] = 0x1F48, -- Scrap Brain Zone
["zone=5,act=0"] = 0x2260,
["zone=5,act=1"] = 0x1EE0,
-- ["zone=5,act=2"] = 000000, -- does not have a max x
}

由于我们游戏的开始状态的x轴位置不为0,所以我们要记录我们游戏状态开始时的x轴位置坐标,这里设定为data.offset_x,由于游戏开始时的agent在x轴上的位置为data.x,所以我们设定data.offset_x= -data.x,   由下面的函数  calc_progress可以看到我们对data.offset_x的设置只进行一次,即游戏开始的状态,以后则不对data.offset_x进行修改。

我们将游戏开始时的位置( -data.offset_x )作为距离规整后的0点,距离规整后的终点位置则为  level_max_x[level_key()] +data.offset_x=level_max_x[level_key()] - data.x

于是,在以后的位置计算中agent的位置则为data.x + data.offset_x, 游戏起始点位置为0,终点位置为end_x 。

agent在游戏起始点和终点之间的位置比例为: cur_x / end_x ,该数值大于等于0小于等于1。

同时需要对游戏中agent的位置进行clip,因为游戏中的agent位置可能会小于游戏起始点也可能大于游戏终止点。

function calc_progress(data)
if data.offset_x == nil then
data.offset_x = -data.x
end_x = level_max_x[level_key()] - data.x
end local cur_x = clip(data.x + data.offset_x, 0, end_x)
return cur_x / end_x
end

我们得到了游戏中agent的位置在起始点和终点之间的比值就可以进入奖励函数的核心部分:

data.prev_progress = 0
frame_limit = 18000 function contest_reward()
local progress = calc_progress(data)
local reward = (progress - data.prev_progress) * 9000
data.prev_progress = progress -- bonus for beating level quickly
if progress >= 1 then
reward = reward + (1 - clip(scenario.frame / frame_limit, 0, 1)) * 1000
end
return reward
end

分析上面代码,data.prev_progress指的是前一个时刻agent在0和end_x之间的比例,progress表示当前时刻agent在0和end_x之间的比例,当前时刻由于agent移动所带来的reward奖励为local reward = (progress - data.prev_progress) * 9000,假设agent从游戏开始到游戏终止时到达end_x位置,那么每一步的该部分奖励和为所有步的(progress - data.prev_progress) * 9000之和,等于最后到达end_x时的progress与游戏开始时的data.prev_progress之差,等于数值1,也就是说如果agent从游戏开始的x轴位置运动到游戏终点位置x_end那么最终所有步获得的该部分奖励之和为9000。

奖励函数的第二部分:

frame_limit = 18000
    if progress >= 1 then
reward = reward + (1 - clip(scenario.frame / frame_limit, 0, 1)) * 1000
end

奖励的第二部分可以视为对游戏时长的惩罚,如果游戏当前状态的frame数在0到18000之间那么我们按照比例给以奖励,如果游戏运行的frame数超过18000那么则不进行奖励。

游戏终止的判断条件:

function xpos_done()
if data.lives < data.prev_lives then
return true
end
data.prev_lives = data.lives if scenario.frame >= frame_limit then
return true
end return data.x > level_max_x[level_key()]
end

每一步都判断游戏lives变量是否变化,如果有则说明游戏回合结束。

    if data.lives < data.prev_lives then
return true
end

如果游戏帧超过设定则设定为游戏回合终止。对游戏的时长上限进行设定。

    if scenario.frame >= frame_limit then
return true
end

对游戏中agent的x轴最大值设定上限,如果agent的x轴位置大于设定的游戏最大x轴位置则判定为回合结束。

data.x > level_max_x[level_key()]

openAI的比赛retro contest的一些细节设置(Detail)的更多相关文章

  1. Hololens 硬件细节 Hardware Detail

    微软HoloLens是世界第一款完全无线缆的全息计算机.通过在新方式上赋予用户的全息体验,HoloLens重新定义了个人计算(Personal Computing).为了将3D全息图形固定到你周围的真 ...

  2. yii2细节设置

    1.设置默认的跳转登陆页面.默认的登陆成功页 在项目的(backend/frontend的config中的main.php中的user组件中),添加loginUrl=>'admin/login' ...

  3. C#中关于WebBrowser的一些细节设置

    在winform中有一个控件可以显示html的内容,该控件就是webbrowser,设置它的DocumenText属性为HTML的内容即可. 在使用WebBrowser做UI的时候,我们有时不希望里面 ...

  4. sublime text 的小细节设置,让你的代码更优美

    这些属性都可以在 首选项>设置-默认 里修改下面也会介绍几个比较常用的几个插件 字体大小: "font_size": 17 高亮编辑中的一行 "highlight_ ...

  5. HoloLens开发手记-硬件细节 Hardware Detail

    微软HoloLens是世界第一款完全无线缆的全息计算机.通过在新方式上赋予用户的全息体验,HoloLens重新定义了个人计算(Personal Computing).为了将3D全息图形固定到你周围的真 ...

  6. ubuntu16.04细节设置

    1.查看无线网卡名称 $ iwconfig ------------------ lo no wireless extensions. eth1 no wireless extensions. eth ...

  7. 面对最菜TI战队,OpenAI在Dota2上输的毫无还手之力

    作者:Tony Peng 去年,OpenAI 的 1v1 AI 击败了世界顶尖选手 Dendi,OpenAI CTO Greg Brockman 承诺:明年,我们会带着 5v5 的 AI bot 重回 ...

  8. LaTeX的一些宏包及细节知识

    文章来源:LaTeX的一些宏包及细节知识http://blog.chinaunix.net/uid-20289887-id-1710422.html ps:我的机器上软件并不能直接运行通,下面“代码” ...

  9. hdu4431 Mahjong

    Mahjong Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  10. it工程师常用英文自我介绍常用用语

      Good morning ! It is really my honor to have this opportunity for an interview, I hope i can make ...

随机推荐

  1. MyBatis 的好处是什么?

    a.MyBatis 把 sql 语句从 Java 源程序中独立出来,放在单独的 XML 文件中编写,给程序的维护带来了很大便利. b.MyBatis 封装了底层 JDBC API 的调用细节,并能自动 ...

  2. 项目管理--PMBOK 读书笔记(7)【项目成本管理】

    1.成本术语: 2.三点估算(PERT): 平均估算值=(最可能持续时间*4+最乐观+最悲观)/6 标准差=(最乐观-最悲观)/6 68.26%.95.46%.99.73% 3.估算成本的工具:质量成 ...

  3. 调用支付JSAPI缺少参数:total_fee解决方法

    1.https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7 调用支付JSAPI缺少参数:total_fee 1.请检查预支付会话标识p ...

  4. Linux高级命令

    重定向 重定向也称为输出重定向,用于将命令的输出保存到目标文件. 使用方法:> 文件名 或 >> 文件名.前者会覆盖文件内容,后者会追加内容到文件. 查看文件内容命令 cat: 显示 ...

  5. 11-CSS定位

    01 CSS定位概念理解 01 标准流布局概念的理解 02 position属性 02 相对定位 依然在标准流中 应用场景: 在不影响其它元素的情况下,对当前元素进行微调 <!DOCTYPE h ...

  6. STM32 CubeMX 学习:001-GPIO的使用

    背景 在上一讲STM32 CubeMX 学习:搭建开发环境中,我们已经利用CubeMx搭建了可编译的工程. 今天就开始来介绍STM32 GPIO的有关知识,以及如何驱动它. HOST-OS : Win ...

  7. day02模板与配置

    一.WXML模板语法 1.1 数据绑定 绑定内容 跟vue差不多,在页面的js文件定义到data里面 然后通过插值语法用在wxml中即可 绑定属性 直接写上插值语法,没有: 三元运算 生成一个十以内的 ...

  8. 记一次 .NET某酒业业务系统 崩溃分析

    一:背景 1. 讲故事 前些天有位朋友找到我,说他的程序每次关闭时就会自动崩溃,一直找不到原因让我帮忙看一下怎么回事,这位朋友应该是第二次找我了,分析了下 dump 还是挺经典的,拿出来给大家分享一下 ...

  9. 【算法】在vue3的ts代码中分组group聚合源数据列表

    有一个IList<any>()对象列表, 示例数据为[{id:'1',fieldName:'field1',value:'1'},{id:'1',fieldName:'field2',va ...

  10. 咬文嚼图式的介绍二叉树、B树/B-树

    前言 因为本人天资愚钝,所以总喜欢将抽象化的事务具象化表达.对于各类眼花缭乱的树,只需要认知到它们只是一种数据结构,类似数组,切片,列表,映射等这些耳熟能详的词汇.对于一个数据结构而言,无非就是增删改 ...