MAML-RL Pytorch 代码解读 (4) – maml_rl/policies/categorical_mlp.py
文章目录
基本介绍
在网上看到的元学习 MAML 的代码大多是跟图像相关的,强化学习这边的代码比较少。
因为自己的思路跟 MAML-RL 相关,所以打算读一些源码。
MAML 的原始代码是基于 tensorflow 的,在 Github 上找到了基于 Pytorch 源码包,学习这个包。
源码链接
https://github.com/dragen1860/MAML-Pytorch-RL
文件路径
./maml_rl/policies/categorical_mlp.py
import
包
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.distributions import Categorical
from collections import OrderedDict
from maml_rl.policies.policy import Policy, weight_init
CategoricalMLPPolicy()
类
class CategoricalMLPPolicy(Policy):
#### 基于多层感知机的策略网络,输出离散的动作值,适用于表格化的强化学习以及离散动作的游戏中。这个类是基于第二份文件的Policy()类,能访问到Policy()类的策略更新函数。
"""
Policy network based on a multi-layer perceptron (MLP), with a
`Categorical` distribution output. This policy network can be used on tasks
with discrete action spaces (eg. `TabularMDPEnv`). The code is adapted from
https://github.com/cbfinn/maml_rl/blob/9c8e2ebd741cb0c7b8bf2d040c4caeeb8e06cc95/sandbox/rocky/tf/policies/maml_minimal_categorical_mlp_policy.py
"""
def __init__(self, input_size, output_size, hidden_sizes=(), nonlinearity=F.relu):
#### 将父类的 input_size 和 output_size 继承到这个类上。
super(CategoricalMLPPolicy, self).__init__(input_size=input_size, output_size=output_size)
#### hidden_sizes隐藏层神经元的行列数,存进来的是只有两个元素的元组;当元组里面的元素是一个的时候,也可以;nonlinearity非线性激活函数;num_layers相当于神经元原本层数再加一层,从后面可知加的这一层是输入层;
self.hidden_sizes = hidden_sizes
self.nonlinearity = nonlinearity
self.num_layers = len(hidden_sizes) + 1
#### 元组加法实际上就是元组的融合。a = (1,) b = (2,3,4,) a + b = (1,2,3,4,)。那么layer_sizes输出的就是输入层、隐藏层的每一层和输出层的大小。
layer_sizes = (input_size,) + hidden_sizes + (output_size,)
#### 加了输入层之后,第一层(序号0)就是输入层,那么中间层就是从序号1开始的层。这个循环的作用是为每个隐藏层具体化线性网络。当i=1时,输入维度是输入层(序号0)的维度,输出的是自己的隐藏层(序号1)的维度。当i=2时,输入维度是隐藏层(序号1)的维度,输出的是自己的隐藏层(序号2)的维度。以此类推。
for i in range(1, self.num_layers + 1):
self.add_module('layer{0}'.format(i),
nn.Linear(layer_sizes[i - 1], layer_sizes[i]))
#### 最后self.apply(weight_init)的含义可能是将policy.py文件函数引进过来(不理解,待定)。
self.apply(weight_init)
def forward(self, input, params=None):
#### 如果参数不存在,就从父类中有顺序地继承网络和名字
if params is None:
params = OrderedDict(self.named_parameters())
#### 先将输出设定成输入值
output = input
#### 让输入经过隐藏层神经元和激活函数
for i in range(1, self.num_layers):
output = F.linear(output,
weight=params['layer{0}.weight'.format(i)],
bias=params['layer{0}.bias'.format(i)])
output = self.nonlinearity(output)
#### 用网络的最后一层输出每个离散动作发生的概率
logits = F.linear(output,
weight=params['layer{0}.weight'.format(self.num_layers)],
bias=params['layer{0}.bias'.format(self.num_layers)])
#### 按照传入的logits在相应的位置处进行取样,取样返回的是该位置的整数索引。
return Categorical(logits=logits)