探索的大胜利——随机网络蒸馏(Random Network Distillation)

本文介绍了一种增强强化学习探索能力的方法——随机网络蒸馏(RND)。通过两个网络的竞争,RND能够自动生成内在奖励,激励智能体探索未知环境。文章详细展示了RND的工作原理及其在经典游戏上的应用。

探索的大胜利——随机网络蒸馏(Random Network Distillation)

写在前面

本项目是之前写过的一个项目项目——好奇心驱动的强化学习中鼓励探索机制(好奇心机制也是其中一种)的另一种形式,对好奇心还不是很熟悉的童鞋可以看看。

RND 有多强?

先来看一张 benchmark,环境为雅达利的游戏——蒙特祖马的复仇

可以看到一众经典算法包括 DQN、A3C、C51、ES 都考了零蛋,情况稍微好一点的算法一般是采用先进理论的算法(比如 UBE,不确定性贝尔曼方程及探索),又或者是一些分布式的训练框架(比如Ape-X,分布式优先级采样的 DQN 框架)

但是,我们的 RND 一骑绝尘,打通了所有关卡,还找到了所有隐藏房间(当然不知道训练了多久)。

RND 简介

我们的 RND 算法到底长啥样呢?这里先摆一张正经的伪代码(用于装杯)

简单来说,其实就是两个不同随机参数的网络,一个更新(称为 predictor)一个不更新(称为 target)。

target 满足的理论前提是对于不同的原始输入(比如图像),输出也要不同,也就是一对一的映射关系。

而 predictor 的目标,就是跟上 target 的脚步,如果 predictor 能跟上 target 的脚步(两个网络的输出很相似),说明 predictor 至少接受过与 target 一样的输入(也就是这个环境已经探索过了),此时内在的奖励就变少了。

举个例子,如果整张地图是一张被 target 盖住的刮刮乐,predictor 就会随着环境输入渐渐地把整个地图都刮开。

这里的内在奖励定义为 ∣ ∣ f ^ ( x ; θ ) − f ( x ) ∣ ∣ 2 ||\hat{f}(x;\theta)-f(x)||^2 f^(x;θ)f(x)2

我们一般称带小帽子的 f ^ \hat{f} f^为预测的值, θ \theta θ是参数,对应 predictor;剩下的 f f f自然就是 target 的输出。

举个例子,如果整张地图是一张被 target 盖住的刮刮乐,predictor 就会随着环境输入渐渐地把整个地图都刮开。

这里的内在奖励定义为 ∣ ∣ f ^ ( x ; θ ) − f ( x ) ∣ ∣ 2 ||\hat{f}(x;\theta)-f(x)||^2 f^(x;θ)f(x)2

我们一般称带小帽子的 f ^ \hat{f} f^为预测的值, θ \theta θ是参数,对应 predictor;剩下的 f f f自然就是 target 的输出。

RND 怎么用

了解好奇心机制的童鞋应该都知道,生成好奇心奖励的好奇心模块就是一个挂件,可以直接外接在强化学习的核心算法上。

所以,模型更新的时候记得收集一下 next state,做成一个列表。模型更新的时候按索引计算内在奖励,加在模型总损失里面就好了。

但是,一定要记得把 target 设置成 stop_gradient=True 噢!

真 · 完全体—— RND+PPO 玩马里奥

创建游戏环境

创建可供多线程的游戏环境

%%writefile MARIO/game_env.py
from __future__ import print_function
import gym_super_mario_bros
from gym.spaces import Box
from gym import Wrapper
from nes_py.wrappers import JoypadSpace
from gym_super_mario_bros.actions import SIMPLE_MOVEMENT, COMPLEX_MOVEMENT, RIGHT_ONLY
import cv2
import numpy as np
import subprocess as sp
import multiprocessing as mp


class Monitor:
    def __init__(self, width, height, saved_path):

        self.command = ["ffmpeg", "-y", "-f", "rawvideo", "-vcodec", "rawvideo", "-s", "{}X{}".format(width, height),
                        "-pix_fmt", "rgb24", "-r", "60", "-i", "-", "-an", "-vcodec", "mpeg4", saved_path]
        try:
            '''创建子进程
            '''
            self.pipe = sp.Popen(self.command, stdin=sp.PIPE, stderr=sp.PIPE)
        except FileNotFoundError:
            pass
    '''记录
    '''
    def record(self, image_array):
        self.pipe.stdin.write(image_array.tostring())


def process_frame(frame):
    if frame is not None:
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
        frame = cv2.resize(frame, (84, 84))[None, :, :] / 255.
        return frame
    else:
        return np.zeros((1, 84, 84))


class CustomReward(Wrapper):
    def __init__(self, env=None, monitor=None):
        super(CustomReward, self).__init__(env)
        self.observation_space = Box(low=0, high=255, shape=(1, 84, 84))
        self.curr_score = 0
        if monitor:
            self.monitor = monitor
        else:
            self.monitor = None

    def step(self, action):
        state, reward, done, info = self.env.step(action)
        if self.monitor:
            self.monitor.record(state)
        state = process_frame(state)
        reward += (info["score"] - self.curr_score) / 40.
        self.curr_score = info["score"]
        if done:
            if info["flag_get"]:
                reward += 50
                reward += info["time"]
            else:
                reward -= 50
        return state, reward / 10., done, info

    def reset(self):
        self.curr_score = 0
        return process_frame(self.env.reset())


class CustomSkipFrame(Wrapper):
    def __init__(self, env, skip=4):
        super(CustomSkipFrame, self).__init__(env)
        self.observation_space = Box(low=0, high=255, shape=(skip, 84, 84))
        self.skip = skip
        self.states = np.zeros((skip, 84, 84), dtype=np.float32)

    def step(self, action):
        total_reward = 0
        last_states = []
        for i in range(self.skip):
            state, reward, done, info = self.env.step(action)
            total_reward += reward
            if i >= self.s
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值