上一篇文章我们已经搞定了如何搭建一个可以运行强化学习的python环境,现在我们就跑一下代码,这里我对代码加上一些个人理解,方便基础差一些的朋友进行理解和学习。
我在这段时间对强化学习进行了学习,所以知识和代码基本来自这本:磨菇书
一、定义模型
import torch.nn as nn
import torch.nn.functional as F
class ActorSoftmax(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim=256):
super(ActorSoftmax, self).__init__()
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, hidden_dim)
self.fc3 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
probs = F.softmax(self.fc3(x), dim=1)
return probs
class Critic(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim=256):
super(Critic, self).__init__()
assert output_dim == 1 # critic must output a single value
self.fc1 = nn.Linear(input_dim, hidden_dim)
self.fc2 = nn.Linear(hidden_dim, hidden_dim)
self.fc3 = nn.Linear(hidden_dim, output_dim)
def forward(self, x):
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
value = self.fc3(x)
return value
先简单解释下神经网络模型,一般是分为三层,输入层、隐藏层以及输出层,如果系统很复杂,也可以添加隐藏层,但是一般情况下,2、3层就够用了。如果想深入了解神经网络,可以参考这篇文章:神经网络——最易懂最清晰的一篇文章
这一段代码,是定义了两个神经网络模型,一个是演员,另一个是评论家。在 ActorSoftmax 类中,通过输入状态 x 经过神经网络计算得到各个动作的概率分布,而在 Critic 类中,通过输入状态 x 经过神经网络计算得到该状态的价值(即给定状态下的预期累积奖励)。
先说演员,首先我们要初始化,但是调用初始化是需要super的,所以就有了那段函数 super(ActorSoftmax, self).__init__()。之后进入初始化,使用linear,创造线性层,可进行全连接操作(即对输入特征进行加权求和并加上偏置,得到隐藏层的输出结果。这个隐藏层的输出结果会成为下一层的输入,进而参与后续的非线性变换、特征提取等操作。)可以看出,一共三层,第一层是输入层到隐藏层,第二层是隐藏层到隐藏层,第三层是隐藏层到输出层。之后用forword定义前向传播过程。为了让网络学习更加复杂的特征和模式,需要用激活函数relu(也就是在神经网络模型的隐藏层中引入非线性,提高表达能力,一般作用在隐藏层),想要用这个函数,就需要torch.nn.functional,代码里已经命名为F了,而Softmax激活函数应用于输出层,它能够将神经网络输出的原始分数转换为概率分布(其实就是归一化处理)。
(关于激活函数,可以看这篇文章进行学习了解:常用的激活函数合集(详细版))
简单来说,就是演员这个大类里面有两个函数,init初始化了全连接层,而forward定义了前向传播,最终通过 softmax 函数得到输出,表示各动作的概率分布。
接下来说评论家,初始化和前向传播是一样的,就两点不同,一是初始化时输出维度只能是1,因为最终返还的是状态的价值(一个单一的数值)。
注意:
(1)隐藏层维度是一个需要指定的超参数,而输入维度和输出维度是根据具体问题来确定的,因此没有在模型内部直接赋值,而是作为参数在初始化模型实例时进行传入。(也就是说输入维度和输出维度在后面参数定义时会有)
(2)在归一化函数softmax中,如果没有dim=1,则默认对最后一个维度进行归一化处理,有的话,就对第二个维度进行归一化处理(每一行为一个样本,每一列为一个类别)。
(3)self 是一个标识符,指向类的实例对象本身。
(4)ActorSoftmax 类定义了两个函数:__init__ 函数用于初始化模型的结构,forward 函数用于定义前向传播过程。在类被实例化之前,这些函数是不会自动运行的。
(5)assert函数是当作断言的,即当assert后面的条件为False时,会触发异常,从而中断程序的执行。适当在代码中加入些断言,可以检查程序的逻辑性和正确性。
除了定义模型,后续还会分析定义经验回放、定义智能体、定义训练、定义环境、设置参数、开始训练这几部分,如果大家想先跑通代码看看结果,可以直接去我最上面的蘑菇书链接里找,之后我还会接着对代码进行分析。(以上分析均是个人拙见,可能有问题,欢迎讨论修改)
标签:__,dim,函数,nn,python,self,PPO,详解,hidden From: https://blog.csdn.net/weixin_70267340/article/details/137332848