1. Machine Learning

  2. Reinforcement Learning

Machine Learning

機器學習能夠解決的問題

問題需求 適用的機器學習種類
要將資料配適到某個函數或函數近似的議題 監督式學習 (Supervised learning)
針對無任何回饋的資料進行結果揣測 非監督式學習 (Unsupervised learning)
隨著時間累積而讓結果的獎勵最大化 增強式學習 (Reinforcement Learning)

演算法種類

演算法 所屬的機器學習種類 演算法類別 受限偏向 適用偏向
K-最近鄰法 (K-Nearest Neighbors) 監督式學習 實例式 受限於維度詛咒 適用於距離形式的問題
單純貝式分類 (Naive Bayesian Classification) 監督式學習 機率(Probabilistic) 處理輸入內容呈現彼此獨立的問題 每種機率大於零的問題
決策樹 (Decision Trees) 監督式學習 Tree 受限於 covariance 適用於種類性資料的問題

大致上列舉幾種演算法還有許多的學習演算法並未列出

Reinforcement Learning

-由分數來決定要做的方法

比如老師會根據我的開心程度來打分, 我開心時, 可以得到高分, 我不開心時得到低分. 有了這些被打分的經驗, 我就能判斷為了拿到高分, 我應該選擇一張開心的臉, 避免選到傷心的臉. 這也是強化學習的核心思想. 可以看出在強化學習中, 一種行為的分數是十分重要的. 所以強化學習具有分數導向性. 我們換一個角度來思考.這種分數導向性好比我們在監督學習中的正確標籤

通過價值選行為的演算法

  • Q-learning
  • Sarsa
  • Deep Q Network (DQN)

Q-Learning

Q-Learning

  • alpha 是一個小於1的數
  • gamma 是對未來的 reward 的衰減值
  • Epsilon greedy 是用在決策上的一種策略

Deep Q Network (DQN)

DQN 是一個記憶庫用於學習之前的經歷,主要解決了不用紀錄表格 (action & state) 因為 action 和 state 如果直接用表格紀錄,記憶體可能會有問題。 而在機器學習中有一種方法是可以用來規劃,也就是神經網路,將狀態以及動作當成神經網路的輸入,透過神經網路生成 Q 值,這樣就可以不用在表格中紀錄 Q 值。

Deep Deterministic Policy Gradient (DDPG)

  • 介紹

DDPG 是由 Google DeepMind 提出的一種使用 Actor-Critic 結構,但輸出不是機率而是具體的行為,用於連續動作 (continuous action)的預測。

  • 算法

$$\bigtriangledown {\theta^{\mu }}J\approx \frac{1}{N}\sum^{ }\bigtriangledown {a}Q(s,a|\theta^{Q})|,a = \mu(s_{i})^{ }\bigtriangledown_{\theta^{\mu }}\mu)(s|\theta^{\mu })|s_{i}$$

關於 Actor 部分,參數更新同樣涉及到 critic ,上面是關於 Actor 參數的更新,算式的前半部分 grad(Q) 是從 Critic 產生。 Actor 的動作移動,才能獲得更大的 Q 值。 而後半部分 gead[u] 是從 Actor 產生,Actor 要修改自己參數使得 Actor 更有可能做這個動作。所以兩個結合就會變成使: Actor 朝著更有可能獲得大的 Q 的方向修改動作參數。

$$\textbf{set} y_{i} = r^{i}+\gamma {Q}'(s_{i+1},{{\mu }}'(s_{i+1}|\theta^{\mu{}'})|\theta^{Q{}'}) $$ $$\textbf{update cricitic by minimizing the loss:} L = \frac{1}{N}\sum_{i}(y_{i}-Q(s_{i},a_{i}|\theta^{Q}))^{2}$$

這個式子是關於 critic 的更新,參考 DQN 的方式,使用兩個 Q 的神經網路,Q target 中依據下一個狀態,由 Actor 來選擇動作,這時 Actor 也有一個 Actor_target ,使用這種方法獲得的 Q_target 能像 DQN 切斷相關性,提高收斂性。

  • 主結構

class Actor(object):
    def __init__(self):
        ...
        with tf.variable_scope('Actor'):
            # 這個網路用於即時更新網路
            self.a = self._build_net(S, scope='eval_net', trainable=True)
            # 這個網路不及時更新參数, 用于預測 Critic 的 Q_target 中的 action
            self.a_ = self._build_net(S_, scope='target_net', trainable=False)
        ...

class Critic(object):
    def __init__(self):
        with tf.variable_scope('Critic'):
            # 這個網路用於即時更新參數
            self.a = a  # 這個 a 是来自 Actor 的, 但是 self.a 在更新 Critic 的时候是之前選擇的 a 而不是来自 Actor 的 a.
            self.q = self._build_net(S, self.a, 'eval_net', trainable=True)
            # 這個網路不及時更新參数, 给出 Actor 更新參数时的 Gradient ascent 强度
            self.q_ = self._build_net(S_, a_, 'target_net', trainable=False)
  • Actor Critic

由圖可以看到兩個 eval_net ,Actor class 的寫法

with tf.variable_scope('policy_grads'):
    # 這是在計算 (dQ/da) * (da/dparams)
    self.policy_grads = tf.gradients(
        ys=self.a, xs=self.e_params, # 計算 ys 對於 xs 的梯度
        grad_ys=a_grads # 這是從 Critic 来的 dQ/da
    )
with tf.variable_scope('A_train'):
    opt = tf.train.AdamOptimizer(-self.lr)  # 父的學習率是為了使我們計算梯度向上, 和 Policy Gradient 中的方式是同一個性質
    self.train_op = opt.apply_gradients(zip(self.policy_grads, self.e_params)) # 對 eval_net 的參數更新

# 計算 target Q
with tf.variable_scope('target_q'):
    self.target_q = R + self.gamma * self.q_    # self.q_ 根據 Actor 的 target_net 来的
# 計算誤差並反向傳遞誤差
with tf.variable_scope('TD_error'):
    self.loss = tf.reduce_mean(tf.squared_difference(self.target_q, self.q))  # self.q 又基於 Actor 的 target_net
with tf.variable_scope('C_train'):
    self.train_op = tf.train.AdamOptimizer(self.lr).minimize(self.loss)

最後把建立好的 actor 以及 critic 融合再一起

actor = Actor(...)
critic = Critic(..., actor.a, actor.a_)  # 將 actor 同它的 eval_net/target_net 產生的 a/a_ 傳給 Critic
actor.add_grad_to_graph(critic.a_grads) # 将 critic 產出的 dQ/da 加入到 Actor 的 Graph 中
  • 記憶 Merory

建立一個 class 進行存取

class Memory(object):
def __init__(self, capacity, dims):
        """numpy 初始化"""

    def store_transition(self, s, a, r, s_):
        """保存每次記億到 numpy array"""

    def sample(self, n):
        """隨機從記憶庫中抽取 n 個記憶進行學習"""

  • 每回合算法 (部分)
var = 3  # 初始化一個方差用於增强 actor 的探索性

for i in range(MAX_EPISODES):
    ...
    for j in range(MAX_EP_STEPS):
        ...

        a = actor.choose_action(s)
        a = np.clip(np.random.normal(a, var), -2, 2) # 增强探索性
        s_, r, done, info = env.step(a)

        M.store_transition(s, a, r / 10, s_)   # 記憶庫

        if M.pointer > MEMORY_CAPACITY: # 記憶庫滿了以後
            var *= .9998    # 逐漸降低探索性
            b_M = M.sample(BATCH_SIZE)
            ...   # 將 b_M 拆分成下面的输入信息
            critic.learn(b_s, b_a, b_r, b_s_)
            actor.learn(b_s)
        # 將現在的 state 取代舊的 S
        s = s_

        if j == MAX_EP_STEPS-1:
            break

以上部分資料參考於 youtube 一位 python 的教學課程還有一些書本的資料 參考網址


Comments

comments powered by Disqus