相信大家刚开始接触PPO的奖励函数时,经常会看到一个torch.exp指数函数。一开始看这些奖励函数的时候很奇怪,为什么有的奖励函数加指数,有的奖励函数又不加指数。
我自己的理解是:奖励函数有奖励也有惩罚,重点是奖励和惩罚是两个概念,所以才有了指数函数这个东西。
奖励是鼓励智能体去探索某个方向。假如它不去探索,那也不会损失什么东西。假如探索了就给它奖励。
惩罚是禁止智能体做某件事情。假如它做了这件严令禁止的事情,那就会狠狠地惩罚它。假如它不做这件事,那属于一个常人做的事,不需要奖励也不需要惩罚。
那么torch.exp(-x)指数函数有个什么性质呢。看下图,初中的时候大家就知道,x越大,值越小,趋近于0。所以它非常适合用来做奖励,x值越大奖励越少,x值越少奖励越多,所以机器人如果朝着让x值变小的方向走,它能够获得更多奖励。
x越小,y越大。举个奖励函数的实际例子,看下面这个代码:
def _reward_orientation(self):
# 对机器人直立姿态的奖励
error = torch.sum(torch.square(self.projected_gravity[:, :2]), dim=1)
return torch.exp(-5.*error/self.cfg.rewards.tracking_sigma)
x 就是重力平面投影的误差,也就是直立姿态的偏差值。如果这个保持的很小,那么就奖励它。也就是x很小,y就变大,奖励也多,直至奖励为1。如果这个x值很大,y就很小,奖励非常少约等于0,奖励为0也没有影响,只是机器人走路姿势难看一点而已,歪着身子走来走去,不美观。属于是“加分项”。
那惩罚呢基本就是利用线性函数了。图就不放了,大家都知道线性函数。x和y是线性变化的。同样举个奖励函数的实际例子,看代码:
def _reward_torque_limits(self):
# 惩罚关节输出的扭矩约束
return torch.sum((torch.abs(self.torques) - self.torque_limits*self.cfg.rewards.soft_torque_limit).clip(min=0.), dim=1)
当关节输出扭矩比扭矩阈值小的时候,x就是0,y也是0。当关节输出扭矩比扭矩阈值大的时候,x就是两者的差值,y就是维度1上每个差值的和。怎么理解惩罚的线性含义?如果扭矩没有到我的阈值限制,那么我不会对你有任何惩罚,你该干嘛干嘛。如果你超了阈值,那不好意思,我要开始打你了,超的越多,打的越多。有的人会问那不超能不能奖励?哈哈哈哈哈,假如你有个孩子,孩子每天正常吃饭睡觉你要给他奖励吗?肯定不需要啊,如果这还奖励那不就是惯出毛病了嘛。
这样大家是不是完全能理解了。