(纯手打原创(基本思想如有雷同实属巧合),转载请注明。)
记一次本人在进行科研项目的过程中踩过的坑。本人在做基于pytorch的强化学习时(当然该情况不仅限于强化学习;另外我用到的强化学习方法是基于AC结构的DDPG算法),遇到过Actor网络的loss没什么变化,输出的action的值始终在0附近的情况,也就是说我的网络根本没学到什么东西。很奇怪,于是在网上搜寻导致该问题的原因以及解决方法(CSDN里就有很多优质的回答),我目前脑海中记得的有以下三种解决办法:
- 调参。调整可能会影响到网络更新的参数,比如学习率等。
- 换激活函数。网上有很多博客提到,如果激活函数是ReLU的话,在误差反向传播的过程中可能会造成神经元的“死掉”,因为ReLU在负半轴的导数为0,根据链式法则,有一个0的存在结果就为0了。可以采用ReLU大家族中的其他成员,比如RReLU、Leaky Relu等。
- 换优化器。网上有很多博客提到,可能是优化器的效果不好导致的,所以各类好用的优化器都试试,比如SGD、Adam等。
但是,以上方法可能对别的小伙伴有用,对我来说,我也试过但都没有用(不是说以上的方法不对或者不好,只是针对我的这个情况是没有用的)。这个坑可能对别人来说并不常见,但是毕竟我踩过了,也算是对这种问题贡献了另外一种可能的原因和解决方法,具体如下:
问题原因:
- tensor转为numpy类型时会造成网络信息的丢失。我的Actor网络是根据系统状态state输出动作action并与系统环境进行交互,但是因为系统环境中用到了一些numpy的方法,为了防止出错,我于是将tensor类型的action转为numpy类型来同环境进行交互。虽然转换后的action的数值不变,但是其不再包含有Actor网络的参数信息了。
- numpy再重新转为tensor类型时,转换后的tensor也只是数值相同的普通的tensor,并不是包含了网络参数信息的tensor。我在向经验池中存储样本时,存储的action为numpy类型的action。虽然在更新网络参数的时候,我又将action转换为tensor类型,以便和状态state一起输入到Critic网络中计算Q值以此来更新Actor网络参数,但是该tensor类型的action不再包含Actor网络的参数信息,它只是一个普通的tensor。因此在误差反向传播中,由于误差所带来的参数更新并不会作用到Actor网络的参数上,就会导致Actor网络的参数一直没有更新,即Loss不下降,从而Actor网络的输出action始终在0附近。
解决方法:
很简单。对于我这个问题,我在向经验池中存储action的时候,只需存储之前的未转换成numpy类型的就可以了;或者在更新网络参数的时候,再让状态state输入到Actor网络中得到包含Actor网络参数信息的tensor类型的action,再拿它计算Q值。
因此,总结一下就是,在进行网络参数更新时,你在计算Loss的过程中所涉及到的tensor类型的变量必须包含你想要更新的网络的参数信息,然后误差反向传播时才会更新该网络的参数。否则的话,该网络的Loss不会下降,输出值也不对,因为你的tensor只是普通的tensor,不会让网络的参数进行更新。
版权声明:本文为qq_36340016原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。