1. 程式人生 > >(重磅)深度強化學習系列之(7)-----強化學習《獎勵函式》的設計和設定(reward shaping)

(重磅)深度強化學習系列之(7)-----強化學習《獎勵函式》的設計和設定(reward shaping)

概述

前面已經講了好幾篇關於強化學習的概述、演算法(DPG->DDPG),也包括對環境OpenAI gym的安裝,baseline演算法的執行和填坑,雖然講了這麼多,演算法也能夠正常執行還取得不錯的效果,但是一直以來忽略了一個非常重要的話題,那就是強化學習的《獎勵函式》的設定。

1、 Gym-Pendulum-v0例子分析獎勵函式

為什麼要講強化學習的概述呢?也許在我們以前執行的演算法中我們並沒有直接接觸到獎勵函式的設定,而是直接呼叫了介面函式,下面以ddpg演算法(點選檢視DDPG演算法)執行’Pendulum-v0’環境(下圖,讓擺杆立起來)為例子:
這裡寫圖片描述

for j in
range(MAX_EP_STEPS): if RENDER: env.render() # Add exploration noise a = ddpg.choose_action(s) # add randomness to action selection for exploration a = np.clip(np.random.normal(a, var), -2, 2) s_, r, done, info = env.step(a) ddpg.store_transition(s, a, r / 10
, s_)

這是episode執行過程,其中根據環境觀察值得到action(ddpg.choose_action(s))後, 直接將動作傳給了env.step()函數了,於是我們就非常直接的得到了對應的獎勵(Reward)、下一個狀態(S),隨後直接開始考慮改善核心演算法。

但是,我們忽略去研究強化學習中非常重要的獎勵函式的設定,因為它會決定強化學習演算法的收斂速度和程度。
那麼到底env.step()背後是怎樣的呢?

 def step(self, action, **kwargs):
        self._observation, reward, done, info = self.env.step(action)
        self._observation = np.clip(self._observation, self.env.observation_space.low, self.env.observation_space.high)
        return
self.observation, reward, done, info

其中第三行np.clip()函式就是,大於max取max,小於min取min(檢視clip()函式 ),然後繼續追蹤第二行self.env.step(action),得到下面程式碼

 def step(self,u):
        th, thdot = self.state # th := theta
        g = 10.
        m = 1.
        l = 1.
        dt = self.dt
        u = np.clip(u, -self.max_torque, self.max_torque)[0]
        self.last_u = u # for rendering
        costs = angle_normalize(th)**2 + .1*thdot**2 + .001*(u**2)

        newthdot = thdot + (-3*g/(2*l) * np.sin(th + np.pi) + 3./(m*l**2)*u) * dt
        newth = th + newthdot*dt
        newthdot = np.clip(newthdot, -self.max_speed, self.max_speed) #pylint: disable=E1111

        self.state = np.array([newth, newthdot])
        return self._get_obs(), -costs, False, {}

這其實就是Pendulum-v0的獎勵函式的設定本質,但是全是程式碼,並且是cos(),sin(),等函式,完全不知到從哪裡來,當然還是能想到角度的,但是具體還要從其原理來講:
Pendulum的角度和角速度,記為th和thdot,至於具體哪個角度我們將在後面進行分析。 此外,同樣可以看出observation包括了cos(th)、sin(th)、thdot三個量。而在上文中我們知道action的定義,對於Pendulum問題來說,action space只有一個維度,就是電機的控制力矩,且有最大值和最小值的限制。其中cost是代價,且最終返回的獎勵是-cost()

return self._get_obs(), -costs, False, {}

那麼我們既可以對cost進行分析了:

costs = angle_normalize(th)**2 + .1*thdot**2 + .001*(u**2)

costs包含三項,
1、angle_normalize(th)**2
2、1*thdot**2,
3、001*(u**2)

第一項 這是對於當前倒立擺與目標位置的角度差的懲罰,那到底th表示哪個角度呢?對於angle_normalize()函式分析如下:

def angle_normalize(x):
    return (((x+np.pi) % (2*np.pi)) - np.pi)

我們先對(x+π)進行分析,帶入幾個角度,
比如x=π/4return=π/4x=3π/4return=3π/4x=5π/4return=3π/4。這樣我們就可以繪圖如下
這裡寫圖片描述
這就是我們的th, cos和sin都是大於-1小於1,thdot大於-8小於8,torque大於-2小於2,至於單位我們就不用考慮咯。
第二項表示對於角速度的懲罰,畢竟如果我們在到達目標位置(豎直)之後,如果還有較大的速度的話,就越過去了;至此,我們的分析就告一段落啦,
第三項是對於輸入力矩的懲罰,我們所使用的力矩越大,懲罰越大,畢竟力矩×角速度=功率,還是小點的好。過程程式碼如圖:
這裡寫圖片描述

到這裡,終於把一個例子的獎勵函式分析了,也知道它的獎勵和角度,力矩等有關。然而學習過程中我們卻很少去關注,比如gym各種環境、Atari環境以及Deepmind的dm_control空間,所有的就是已經封裝好的,但是我們自己怎樣去設定一個獎勵函式呢?reward很重要,因為強化學習就是基於 Reward Hypothesis(關於這個假設詳見老爺子sutton【嘮叨一句,老爺子可是強化學習的大師級人物,著有強化學習聖經《reinforcement learning: an introduction》,現在在Google工作】的頁面:RewardHypothesis.)。這是假設所有的目標都可以被描述成最大化預期的累計的reward訊號。

可能平時我們感覺不到獎勵的區別,引用一故事:

進階版是加上一個對於能量的penalty。也就是reward會扣除你所消耗的能量。如果運氣好的話,那些多餘的手部動作應該就不存在了,但是直接加這個penalty似乎效果不大。另一種就是,既然覺得那種動作太逗比了,我們就給他一個我們想讓他做的動作。於是reward變成了和人行走姿態比有多大不同,於是得到了比較正常的結果:https://xbpeng.github.io/projects/DeepLoco/index.html結論:reward的影響很大。

2、 獎勵函式設定

目前強化學習的獎勵設定系統性介紹的文章特別少,查了很多資料,沒有很多實質內容

Daniel Dewey在他的文章《Reinforcement Learning and the Reward Engineering Principle》提到了獎勵函式(工程)的原則,原話是:
The Reward Engineering Principle: As reinforcement-learningbased AI systems become more general and autonomous, the design of reward mechanisms that elicit desired behaviours becomes both more important and more difficult.
翻譯過來就是強化學習系統變得越來越普通的時候,引發期望行為的獎勵機制的設計變得更加重要和困難!另外在獎勵shaping中我們發現,獎勵形成對強化學習速度的影響分析。 我們得出結論:獎勵範圍是一個重要的引數,它涉及整形的有效性,並證明它對於一個簡單的強化學習演算法在執行時間上具有最強的影響力。 此外,當學習利用獎勵視界時,可以在不依賴於狀態空間大小的情況下及時學習近似最優策略,而是根據視野內的狀態數量。

(1)稀疏獎勵(sparse reward)

稀疏獎勵是最常見的一種獎勵,在遊戲中有很多的應用,即“完成比賽得分,輸掉比賽不得分”這種形式。這個問題已經一直困擾了 RL 很多年了. 打個比方, 下圍棋, 下的過程中是沒有任何 reward 的, 只有下到最後才會出現一個 reward 訊號說誰贏了. 這是很不好學的. 這一個 reward 訊號很容易就消失在了茫茫的資料中(沒有 reward 的資料). 而如果時時刻刻都有一個 reward 訊號, 而且這個 reward 訊號有小有大, sparse 的問題就很容易解決了. 所以做出一個好的 reward function 在現階段很重要.
但是這種一般比較少,大多數在遊戲中,至少我想到的周圍的應用比較少,另外一個問題就是比較難,所以連續性的獎勵就比較好,比如Atari遊戲中的打磚塊,打一個得一分,一個回合就是一次遊戲得多少分,這樣對於系統的學習也就響度簡單點,後期遇到合適資料再進行補充。

(2)形式化獎勵

這裡寫圖片描述
在HalfCheetah環境中,我們有一個受限於一個垂直平面的雙足機器人,這意味著它只能向前或向後運動。
機器人的目標是學會跑步步態,獎勵是速度。這是一種形式化的獎勵,機器人越接近獎勵目標,系統給予的獎勵就越多。這和稀疏獎勵形成鮮明對比,因為這種獎勵只在目標狀態下給予獎勵,在其他任何地方則沒有獎勵。這種形式化的獎勵通常更容易促進學習,因為即使策略沒有找到解決問題的完整解決方案,它們也能提供積極的反饋。具體的關於halfcheeath的原理如圖:它是一個多自由度的控制,具體的是每個自由度上的速度,而計算獎勵則是按照前後位置的位置進行計算.
這裡寫圖片描述
這裡寫圖片描述
它的獎勵函式的原始碼如下:

    def step(self, action):
        xposbefore = self.sim.data.qpos[0]
        self.do_simulation(action, self.frame_skip)
        xposafter = self.sim.data.qpos[0]
        ob = self._get_obs()
        reward_ctrl = - 0.1 * np.square(action).sum()
        reward_run = (xposafter - xposbefore)/self.dt
        reward = reward_ctrl + reward_run
        done = False
        return ob, reward, done, dict(reward_run=reward_run, reward_ctrl=reward_ctrl)

不幸的是,形式化的獎勵也可能會影響學習效果。如前所述,它可能會導致機器人動作與預期不符。一個典型的例子是OpenAI的博文Faulty Reward Functions in the Wild,

(3)分佈獎勵

分佈獎勵思想來源於概率論中的分佈,通常的做法是將獎勵根據高斯分佈等做,也有在rnn演算法中通過記憶等做的,由於資料不多,故不詳述.

(4)獎勵係數變化獎勵

這部分說起來比較簡單,就是獎勵是隨其他變數而變化的,並不像前面的.比如:打保齡球,距離線的距離就可以算作每次發力的獎勵。
 

(1)Rt={1.0distance>20.75<1distance<20.50.2<distance<100<=distance<0.2

(5)中間難度起點獎勵(SoID)

強化學習過程中經常會出現一個問題,剛開始學習全部是負面獎勵,則學習起來很慢,但要是全部是積極獎勵,系統又學不到不好的一面,於是科學家就提出了一種中間難度起點獎勵,就是從中間開始的意思.
於是過程變成了記錄目前實驗物件的效能,為RL提供訊號,特別關注策略梯度,通過採取預期總獎勵的預計梯度來改變策略.數學描述為:

θJ=1Ni=1θlogπθ(τi)[R(τi,s0i)R(πi,s0i)]
即目標在導向任務中,R(τi,s0i) 是二元的,表示物件是否達到目標,所以常規的