Q = defaultdict(lambda: np.zeros(env.action_space.n))语句解析
前言:
再看蒙特卡洛搜索树的代码时,看到了一个Q的初始化定义语句如上形式,一时间没看明白。搜了一下每个部分的含义之后,才知道整句话到底实现了什么功能。
首先后面的部分是非常简单的,env.action_space.n
直接是一个动作数目,假设是n,np.zeros()
函数也简单,直接创建一个初始值为0的n维数组.
理解default_dict和lambda的作用
难以理解的是那个default_dict
和lambda
,首先解释一下这个default_dict的函数作用。
在默认的dict数据类型中,如果字典里面没有新加入的key,调用dict[key]
就会报错,在表格类型的强化中,如果我们对于新遇到的state,给它加到我们的Q-table中,则要先判断这个state是否在Q-table中,如果不在,则需要
Q_table = dict()
new_state = 'new'
new_state_value = 1.0
if new_state not in Q_table.keys():
Q_table.update({new_state: new_state_value})
整个的实现就比较不优雅.
而default_dict
就可以自带判断和默认值,Q_table定义的时候,就只需要设定一个default_dict
,遇到新的key时,就能自己判断,如果没有,则更新一个新的元素,value为默认值。
这时候必须得搜一下default_dict
的函数定义,只要把default_dict
挂到百度上,就能找到很多中文解析,我贴一个博客园的,质量一般会好点。
https://www.cnblogs.com/dancesir/p/8142775.html
defaultdict类除了接受类型名称作为初始化函数的参数之外,还可以使用任何不带参数的可调用函数,到时该函数的返回结果作为默认值,这样使得默认值的取值更加灵活。下面用一个例子来说明,如何用自定义的不带参数的函数zero()作为defaultdict类的初始化函数的参数:
这里面就涉及到另外一个问题,就是这个可调用函数,什么叫可调用函数,通俗来讲即定义一个函数,但是不加括号,就是可调用函数~
defaultdict(1)
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: first argument must be callable or None
那么我们是否可以定义一个简单的 函数:
from collections import defaultdict
def call_func():
return 1
Q = defaultdict(lambda: call_func)
Q['new_state'] = 12
print(Q)
把这行代码运行一下,就会发现,可以实现上面说的那个功能,本身Q啥也没有,但是直接给new_state,也能直接添加。
但是这个功能仍然需要好几行代码,因此原作者还加了一个花里胡哨的lambda的匿名函数操作。
lambda函数的通俗理解:
lambda就是一个匿名函数的作用。
操作示例如下:
lambda x: 2*x
一个lambda
,一个:
,是必须的,冒号前面是函数的输入,冒号后面是函数的输出表达式。
上面的表达式等价替换为下面的函数:
def func(x):
return 2 * x
联系方式:
ps: 欢迎做强化的同学加群一起学习:
深度强化学习-DRL:799378128
Mujoco建模:818977608
欢迎玩其他物理引擎的同学一起玩耍~
欢迎关注知乎帐号:未入门的炼丹学徒
CSDN帐号:https://blog.csdn.net/hehedadaq
极简spinup+HER+PER代码实现:https://github.com/kaixindelele/DRLib