在网上看到的元学习 MAML 的代码大多是跟图像相关的,强化学习这边的代码比较少。
因为自己的思路跟 MAML-RL 相关,所以打算读一些源码。
MAML 的原始代码是基于 tensorflow 的,在 Github 上找到了基于 Pytorch 源码包,学习这个包。
https://github.com/dragen1860/MAML-Pytorch-RL
./maml_rl/envs/bandit.py
import
包import numpy as np
import gym
from gym import spaces
from gym.utils import seeding
BernoulliBanditEnv()
类阅读这部分代码不太明白 self._task
和 task
具体指带的是什么信息。
class BernoulliBanditEnv(gym.Env):
#### 这个类的环境是伯努力分布下的多臂赌博机问题。智能体推动其中 “K” 个手臂,说了 “i” 信息,收到从伯努力分布中采样得到的具有 “pi” 信息的奖励,从[0,1]均匀分布中采样得到的pi被保证。
"""Multi-armed bandit problems with Bernoulli observations, as described
in [1].
At each time step, the agent pulls one of the `k` possible arms (actions),
say `i`, and receives a reward sampled from a Bernoulli distribution with
parameter `p_i`. The multi-armed bandit tasks are generated by sampling
the parameters `p_i` from the uniform distribution on [0, 1].
[1] Yan Duan, John Schulman, Xi Chen, Peter L. Bartlett, Ilya Sutskever,
Pieter Abbeel, "RL2: Fast Reinforcement Learning via Slow Reinforcement
Learning", 2016 (https://arxiv.org/abs/1611.02779)
"""
#### 初始类信息。当前环境继承gym.Env()类,k表示维度;那么action_space就是离散的k维度动作空间;observation_space中的状态信息就是一个数据,但是不明白这里为何high=0而不是1;_task接受task字典;_means应该就是将task字典里面的'mean'用元素全部是0.5的K维度向量赋予而成;最后设置随机数。
def __init__(self, k, task={}):
super(BernoulliBanditEnv, self).__init__()
self.k = k
self.action_space = spaces.Discrete(self.k)
self.observation_space = spaces.Box(low=0, high=0,
shape=(1,), dtype=np.float32)
self._task = task
self._means = task.get('mean', np.full((k,), 0.5, dtype=np.float32))
self.seed()
#### 跳转到源码上是numpy的,意思就是获得一组随机数。第一个self.np_random是一个与随机数相关的实例,seed是随机数种子。
def seed(self, seed=None):
self.np_random, seed = seeding.np_random(seed)
return [seed]
#### 因为元学习需要采用很多的任务,因此means得到的是num_tasks(任务数)行和self.k列的随机数矩阵作为均值,tasks对这个矩阵按行拆分成一个个字典,字典的键是"mean"值是每一行作为一个array数组。相当于初始化每个任务的均值是随机数array。
def sample_tasks(self, num_tasks):
means = self.np_random.rand(num_tasks, self.k)
tasks = [{'mean': mean} for mean in means]
return tasks
#### 因为元学习有很多的任务,需要重置任务实现切换。用_task形参task,意味着在程序运行中task的初始化可能更原本的初始化不一样。self._means用task字典的”mean“来替代。
def reset_task(self, task):
self._task = task
self._means = task['mean']
#### 这个reset实现每个任务的重置,重置成初始状态。
def reset(self):
return np.zeros(1, dtype=np.float32)
#### assert关键字的作用是检查输出的动作信息在不在动作空间内。mean的意思应该是从action中获得这个赌博机的期望?这里没搞懂。reward的意思是从概率是mean的一重二项分布中抽取奖励信息。观测信息就是一个元素是0的array。
def step(self, action):
assert self.action_space.contains(action)
mean = self._means[action]
reward = self.np_random.binomial(1, mean)
observation = np.zeros(1, dtype=np.float32)
return observation, reward, True, self._task
GaussianBanditEnv()
类class GaussianBanditEnv(gym.Env):
#### 这个类的环境是正态分布下的多臂赌博机问题。智能体推动其中 “K” 个手臂,说了 “i” 信息,收到从正态分布中采样得到的均值是 “pi” 且标准差是 ”std“ 且在任务中固定的信息的奖励,从[0,1]均匀分布中采样得到的pi被保证。
"""Multi-armed problems with Gaussian observations.
At each time step, the agent pulls one of the `k` possible arms (actions),
say `i`, and receives a reward sampled from a Normal distribution with
mean `p_i` and standard deviation `std` (fixed across all tasks). The
multi-armed bandit tasks are generated by sampling the parameters `p_i`
from the uniform distribution on [0, 1].
"""
#### 初始类信息。当前环境继承gym.Env()类,k表示维度;std表示标准差;那么action_space就是离散的k维度动作空间;observation_space中的状态信息就是一个数据,但是不明白这里为何high=0而不是1;_task接受task字典;_means应该就是将task字典里面的'mean'用元素全部是0.5的K维度向量赋予而成;最后设置随机数。
def __init__(self, k, std=1.0, task={}):
super(GaussianBanditEnv, self).__init__()
self.k = k
self.std = std
self.action_space = spaces.Discrete(self.k)
self.observation_space = spaces.Box(low=0, high=0,
shape=(1,), dtype=np.float32)
self._task = task
self._means = task.get('mean', np.full((k,), 0.5, dtype=np.float32))
self.seed()
#### 跳转到源码上是numpy的,意思就是获得一组随机数。第一个self.np_random是一个与随机数相关的实例,seed是随机数种子。
def seed(self, seed=None):
self.np_random, seed = seeding.np_random(seed)
return [seed]
#### 因为元学习需要采用很多的任务,因此means得到的是num_tasks(任务数)行和self.k列的随机数矩阵作为均值,tasks对这个矩阵按行拆分成一个个字典,字典的键是"mean"值是每一行作为一个array数组。相当于初始化每个任务的均值是随机数array。
def sample_tasks(self, num_tasks):
means = self.np_random.rand(num_tasks, self.k)
tasks = [{'mean': mean} for mean in means]
return tasks
#### 因为元学习有很多的任务,需要重置任务实现切换。用_task形参task,意味着在程序运行中task的初始化可能更原本的初始化不一样。self._means用task字典的”mean“来替代。
def reset_task(self, task):
self._task = task
self._means = task['mean']
#### 这个reset实现每个任务的重置,重置成初始状态。
def reset(self):
return np.zeros(1, dtype=np.float32)
#### assert关键字的作用是检查输出的动作信息在不在动作空间内。mean的意思应该是从action中获得这个赌博机的期望?这里没搞懂。reward的意思是从概率是mean的一重二项分布中抽取奖励信息。观测信息就是一个元素是0的array。
def step(self, action):
assert self.action_space.contains(action)
mean = self._means[action]
reward = self.np_random.normal(mean, self.std)
observation = np.zeros(1, dtype=np.float32)
return observation, reward, True, self._task