<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 九、強化學習 本章介紹**強化學習**(**RL**)-學習最少,但最有前途的學習范例。 本章包括以下主題: * 了解 OpenAI Gym * 實現神經網絡智能體來玩吃豆人 * 用 Q 學習平衡推車 * 深度 Q 網絡和 Atari 游戲 * 用策略梯度玩 Pong 游戲 # 介紹 2016 年 3 月,由 Google DeepMind 制作的程序 AlphaGo 以 4 比 1 擊敗了世界上最好的圍棋選手,十八屆世界冠軍李·塞多爾(Lee Sedol)。 ,具有: ```py 208,168,199,381,979,984,699,478,633,344,862,770,286,522, 453,884,530,548,425,639,456,820,927,419,612,738,015,378, 525,648,451,698,519,643,907,259,916,015,628,128,546,089, 888,314,427, 129,715,319,317,557,736,620,397,247,064,840,935 ``` 可能的法律委員會職位。 玩和贏得圍棋無法通過簡單的蠻力完成。 它需要技巧,創造力,以及專業圍棋選手所說的直覺。 AlphaGo 在基于 RL 算法的深度神經網絡與最先進的樹搜索算法相結合的幫助下實現了這一非凡的成就。 本章介紹 RL 和我們用于執行 RL 的一些算法。 因此,出現的第一個問題是什么是 RL,它與我們在前幾章中探討的有監督和無監督學習有何不同? 擁有寵物的任何人都知道,訓練寵物的最佳策略是獎勵其期望的行為,并懲罰其不良行為。 RL 也稱為與批評者進行的**學習**,它是一種學習范例,其中智能體以相同的方式進行學習。 這里的智能體對應我們的網絡(程序); 它可以執行一組**動作**(`a`),這會導致環境的**狀態**(`s`)發生變化。 ,則智能體會感知其是否獲得獎勵或懲罰。 例如,在狗的情況下,狗是我們的智能體,狗的自愿肌肉運動是動作,地面是環境。 狗給我們骨頭作為獎勵,從而感覺到我們對其動作的反應: ![](https://img.kancloud.cn/f9/ae/f9ae6f807b007f6f74334bd8d8fad192_1561x936.png) 改編自強化學習:薩頓(Sutton)和巴托(Barto)的引言即使我們的大腦在前腦底部有一組稱為“基底神經節”的皮層下核,根據神經科學,它們負責選擇動作,即幫助 我們決定在任何給定時間執行幾個可能的動作中的哪一個。 智能體的目的是使報酬最大化并減少懲罰。 做出此決策涉及各種挑戰,最重要的挑戰是如何最大化未來的回報,也稱為**臨時得分分配問題**。 智能體根據某些策略(`π`)決定其操作; 智能體根據其與環境的交互來學習此策略(`π`)。 有各種策略學習算法; 我們將在本章中探索其中的一些。 智能體通過反復試驗的過程來推斷最優策略(`π*`),并且要學習最優策略,智能體需要與之交互的環境; 我們將使用提供不同環境的 OpenAI Gym。 在這里,我們僅對 RL 中涉及的基本概念進行了回顧; 我們假設您熟悉馬爾可夫概念的決策過程,折現因子和值函數(狀態值和動作值)。 在本章以及隨后的秘籍中,我們將一集定義為游戲的一次運行,例如,解決一個數獨游戲。 通常,智能體會播放許多劇集以學習一種最佳策略,該策略可使獎勵最大化。 看到 RL 特工在沒有任何游戲隱性知識的情況下,如何在這些游戲中學會玩游戲,不僅玩游戲,甚至擊敗人類,真是太神奇了。 # 了解 OpenAI Gym 我們將使用 OpenAI Gym 為我們的智能體提供一個環境。 OpenAI Gym 是一個開源工具包,用于開發和比較 RL 算法。 它包含各種模擬環境,可用于訓練智能體和開發新的 RL 算法。 # 準備 首先要做的是安裝 OpenAI Gym; 使用`pip install gym`可以完成最少的安裝。 OpenAI 運動場提供了多種環境,例如 Atari,棋盤游戲以及 2D 或 3D 物理引擎。 最小安裝可在 Windows 上運行,并且僅支持基本環境-算法,`toy_text`和`classic_control`-但如果您要探索其他環境,則它們將需要更多的依賴項。 OSX 和 Ubuntu 支持完整版本。 可以在 OpenAI Gym 的 [GitHub 鏈接](https://github.com/openai/gym#installing-dependencies-for-specific-environments)上閱讀詳細說明。 # 操作步驟 讓我們從秘籍開始: 1. OpenAI Gym 提供的核心接口是統一環境接口。 智能體可以使用三種基本方法與環境進行交互,即重置,逐步和渲染。 `reset`方法重置環境并返回觀察值。 `step`方法將環境步進一個時間步,并返回觀察,獎勵,完成和信息。 `render`方法呈現一幀環境,例如彈出一個窗口。 2. 要使用 OpenAI Gym,您需要先將其導入: ```py import gym ``` 3. 接下來,我們創建我們的第一個環境: ```py env_name = 'Breakout-v3' env = gym.make(env_name) ``` 4. 我們使用`reset`方法啟動環境: ```py obs = env.reset() ``` 5. 讓我們檢查一下環境的形狀: ```py print(obs.shape) ``` 6. 可以使用命令`actions = env.action_space`檢查可能的操作數量。 從此結果可以看出,對于 Breakout-v4,我們有四個可能的動作:`NoOp`,`Fire`,`Left`和`Right`。 可以通過調用`env.action_space.n`命令獲得操作總數。 7. 讓我們定義一個具有隨機策略的智能體。 智能體會隨機選擇四個可能的動作中的任何一個: ```py def random_policy(n): action = np.random.randint(0,n) return action ``` 8. 接下來,我們使用`obs, reward, done, info = env.step(action)`允許我們的隨機智能體播放 1,000 步: ```py for step in range(1000): # 1000 steps max action = random_policy(env.action_space.n) obs, reward, done, info = env.step(action) env.render() if done: img = env.render(mode='rgb_array') plt.imshow(img) plt.show() print("The game is over in {} steps".format(step)) break ``` `obs`告訴智能體程序環境是什么樣的; 對于我們的環境,它對應于大小為`210 x 160 x 3`的 RGB 圖像。在每個步驟中,智能體將獲得 0 或 1 獎勵,根據 OpenAI Gym Wiki,其`reward`為`[-inf, inf]`。 游戲結束后,環境將`done`返回為`True`。 `info`可用于調試,但智能體不使用。 `env.render()`命令彈出一個窗口,顯示環境的當前狀態。 當包含此命令時,您可以通過彈出窗口查看座席如何嘗試玩耍和學習。 最好在座席接受訓練時對此進行評論,以節省時間。 9. 最后,關閉環境: ```py env.close() ``` # 工作原理 前面的代碼實現了一個隨機智能體; 智能體會隨機選擇以下四個動作之一: ![](https://img.kancloud.cn/f4/bd/f4bdb345d14890387273782b766b5b9a_640x480.jpg) 要觀察的另一件重要事情是,在這種環境中,動作空間是離散的,而觀察空間是盒子類型的。 OpenAI 中關于空間(動作/觀察)的術語“離散”和“框”是指允許的值。 離散空間允許固定范圍的非負數,在我們的情況下為(`0,1,2,3`)。 另一方面,盒子空間表示一個`n`維盒子,因此對于吃豆人來說,任何有效觀察結果都是`210×160×3`數字的數組。 # 更多 OpenAI Gym 由許多不同的環境組成,其活躍的貢獻社區在其中添加了許多環境。 要獲取所有現有環境的列表,可以運行[以下簡單代碼](https://github.com/openai/gym): ```py from gym import envs env_ids = [spec.id for spec in envs.registry.all()] print("Total Number of environments are", len(env_ids)) for env_id in sorted(env_ids): print(env_id) ``` 目前,OpenAI Gym 共有 777 個環境。 這是吃豆人使用與之前相同的隨機智能體的圖像: ![](https://img.kancloud.cn/82/3d/823d13fa0275768379df09c3209c276c_640x480.jpg) # 另見 * 可以從[這里](https://gym.openai.com/envs)獲取有關不同環境的詳細信息。 * 在[這個鏈接](https://github.com/openai/gym/wiki)中為某些環境維護了 Wiki 頁面 * 可以從[這個鏈接](https://github.com/openai/gym)獲得有關安裝說明和依賴項的詳細信息。 # 實現神經網絡智能體來玩吃豆人 讓我們首先構建一個簡單的神經網絡智能體來玩“吃豆人”游戲。 我們將創建具有一組隨機權重和偏差的智能體。 然后,這些特工將嘗試玩游戲; 我們選擇能夠發揮最長平均持續時間的特工,并假設他們是最佳策略。 # 準備 此秘籍中的智能體沒有學習任何策略; 他們根據初始權重(固定策略)做出決策。 智能體根據神經網絡給出的概率來選擇動作。 每個智能體做出的決定僅基于對環境的當前觀察。 我們通過完全連接的神經網絡來實現。 NN 的輸入由環境的觀察空間決定; 輸出神經元的數量由可能的離散動作的數量決定。 吃豆人游戲有九種可能的離散動作-無操作,右轉,左轉,上轉,向下轉,左移,右移,上移和下移-因此我們的 NN 具有九個輸出神經元。 # 操作步驟 讓我們從秘籍開始: 1. 與往常一樣,第一步是導入模塊。 在這種情況下,除了通常的模塊之外,我們還將導入`gym`,以便我們可以使用它提供的不同環境: ```py import gym import numpy as np import tensorflow as tf import matplotlib.pyplot as plt ``` 2. 接下來,我們創建一個`RlAgent`類。 該類由三種方法組成-`__init__`方法初始化 NN 大小并創建計算圖。 在這里,我們使用了 TensorFlow 函數`tf.multinomial`來決定采取的可能措施。 該函數根據我們網絡的 9 個輸出神經元的 Sigmoid 值返回操作。 這樣可以確保網絡根據概率選擇最終操作。 `predict`方法返回由 NN 預測的動作。 `get_weights`方法可幫助我們獲得獲勝者智能體的權重和偏置: ```py class RlAgent(object): def __init__(self,m,n,ini=False,W=None, b=None ): self._graph = tf.Graph() with self._graph.as_default(): self._X = tf.placeholder(tf.float32,shape=(1,m)) if ini==False: self.W = tf.Variable(tf.random_normal([m,n]), trainable=False) self.bias = tf.Variable(tf.random_normal([1,n]),trainable=False) else: self.W = W self.bias = b out = tf.nn.sigmoid(tf.matmul(self._X,self.W)+ self.bias) self._result = tf.multinomial(out,1) init = tf.global_variables_initializer() self._sess = tf.Session() self._sess.run(init) def predict(self, X): action = self._sess.run(self._result, feed_dict= {self._X: X}) return action def get_weights(self): W, b = self._sess.run([self.W, self.bias]) return W, b ``` 3. 我們定義了一些輔助函數來玩一個完整的游戲`play_one_episode`: ```py def play_one_episode(env, agent): obs = env.reset() img_pre = preprocess_image(obs) done = False t = 0 while not done and t < 10000: env.render() # This can be commented to speed up t += 1 action = agent.predict(img_pre) #print(t,action) obs, reward, done, info = env.step(action) img_pre = preprocess_image(obs) if done: break return t ``` 4. `play_multiple_episodes`函數創建智能體的一個實例,并使用該智能體進行許多游戲,并返回其平均游戲時間: ```py def play_multiple_episodes(env, T,ini=False, W=None, b=None): episode_lengths = np.empty(T) obs = env.reset() img_pre = preprocess_image(obs) if ini== False: agent = RlAgent(img_pre.shape[1],env.action_space.n) else: agent = RlAgent(img_pre.shape[1],env.action_space.n,ini, W, b) for i in range(T): episode_lengths[i] = play_one_episode(env, agent) avg_length = episode_lengths.mean() print("avg length:", avg_length) if ini == False: W, b = agent.get_weights() return avg_length, W, b ``` 5. `random_search`函數調用`play_multiple_episodes`; 每次調用`play_multiple_episodes`時,都會使用一組新的隨機權重和偏差來實例化新智能體。 這些隨機創建的 NN 智能體之一將勝過其他智能體,這將是我們最終選擇的智能體: ```py def random_search(env): episode_lengths = [] best = 0 for t in range(10): print("Agent {} reporting".format(t)) avg_length, wts, bias = play_multiple_episodes(env, 10) episode_lengths.append(avg_length) if avg_length > best: best_wt = wts best_bias = bias best = avg_length return episode_lengths, best_wt, best_bias ``` 6. 每次執行步驟時,環境都會返回一個觀察場。 該觀察具有三個顏色通道。 為了將其饋送到 NN,需要對觀測值進行預處理,目前,我們唯一要做的預處理是將其轉換為灰度,增加對比度并將其整形為行向量: ```py def preprocess_image(img): img = img.mean(axis =2) # to grayscale img[img==150] = 0 # Bring about a better contrast img = (img - 128)/128 - 1 # Normalize image from -1 to 1 m,n = img.shape return img.reshape(1,m*n) ``` 7. NN 智能體一一實例化,然后選擇最佳智能體。 為了提高計算效率,我們目前僅搜索 10 個智能體,每個智能體玩 10 場比賽。 玩得最長的游戲被認為是最好的: ```py if __name__ == '__main__': env_name = 'Breakout-v0' #env_name = 'MsPacman-v0' env = gym.make(env_name) episode_lengths, W, b = random_search(env) plt.plot(episode_lengths) plt.show() print("Final Run with best Agent") play_multiple_episodes(env,10, ini=True, W=W, b=b) ``` 結果如下: ![](https://img.kancloud.cn/38/a4/38a4d06f56bd6e7b4e4cfab59d7f9c79_1145x588.png) 我們可以看到我們的隨機智能體也可以平均 **615.5** 的長度玩游戲。 不錯! # 用 Q 學習平衡推車 如導言所述,我們有一個由狀態`s`(`s ∈ S`,其中`S`是所有可能狀態的集合)描述的環境,可以執行動作`a`(`a ∈ A`,其中`A`由所有可能的動作組成),從而導致主體從一種狀態移動到另一種狀態 。 智能體因其行為而受到獎勵,智能體的目標是使獎勵最大化。 在 Q 學習中,智能體通過計算最大化報酬的狀態-動作組合的數量(`R`)來學習要采取的動作(策略,`π`)。 在選擇行動時,智能體不僅要考慮現在的獎勵,而且要考慮未來的折扣。 `Q: S × A → R` 智能體以`Q`的任意初始值開頭,并且隨著智能體選擇動作`a`并獲得獎勵`r`,它會更新狀態`s`(取決于過去狀態`s`和動作`a`)和`Q`值: `Q(s, a) = (1 - α) · Q(s, a) + α(r + γ · max[a']Q(s', a'))` 在此,`α`是學習率,`γ`是折扣因子。 第一項保留`Q`的舊值,第二項提供`Q`值的改進估計值(它包括當前獎勵和未來行動的折現獎勵)。 當結果狀態不理想時,這將降低`Q`值,從而確保智能體在下次遇到此狀態時不會選擇相同的動作。 類似地,當期望結果狀態時,相應的`Q`值將增加。 Q 學習的最簡單實現涉及維護和更新狀態-作用值查找表; 表的大小將為`N×M`,其中`N`是所有可能狀態的數量,`M`是所有可能動作的數量。 對于大多數環境,此表將很大。 表越大,搜索所需的時間就越多,并且存儲表所需的內存也就越多,因此這不是可行的解決方案。 在本秘籍中,我們將使用 Q 學習的 NN 實現。 在此,將神經網絡用作函數逼近器來預測值函數(Q)。 NN 具有等于可能動作數的輸出節點,并且它們的輸出表示相應動作的值函數。 # 準備 我們將訓練一個線性神經網絡來解決[`'CartPole-v0'`環境](https://github.com/openai/gym/wiki/CartPole-v0)。 目的是平衡手推車上的桿。 觀測狀態由四個連續值參數組成:推車位置`[-2.4, 2.4]`,推車速度`[-∞, ∞]`,極角`[~-41.8o, ~41.8o]`和極限速度`[-∞, ∞]`。 可以通過向左或向右推推車來實現平衡,因此動作空間由兩個可能的動作組成。 您可以看到`CartPole-v0`環境空間: ![](https://img.kancloud.cn/66/4b/664b9a363879915a08c796d4d8880568_593x398.png) 現在,對于 Q 學習,我們需要找到一種量化連續值觀測狀態的方法。 這是使用類`FeatureTransform`實現的; 該類首先生成 20,000 個觀察空間示例的隨機樣本。 隨機生成的觀察空間示例使用 scikit `StandardScaler`類進行了標準化。 然后以不同的方差使用 scikit 的`RBFSampler`來覆蓋觀察空間的不同部分。 `FeatureTransformer`類由隨機觀察空間示例實例化,該示例用于使用`fit_transform`函數方法訓練`RBFSampler`。 后來,使用`transform`方法將連續觀察空間轉換為這種特征化表示: ```py class FeatureTransformer: def __init__(self, env): obs_examples = np.random.random((20000, 4)) print(obs_examples.shape) scaler = StandardScaler() scaler.fit(obs_examples) # Used to converte a state to a featurizes represenation. # We use RBF kernels with different variances to cover different parts of the space featurizer = FeatureUnion([ ("cart_position", RBFSampler(gamma=0.02, n_components=500)), ("cart_velocity", RBFSampler(gamma=1.0, n_components=500)), ("pole_angle", RBFSampler(gamma=0.5, n_components=500)), ("pole_velocity", RBFSampler(gamma=0.1, n_components=500)) ]) feature_examples = featurizer.fit_transform(scaler.transform(obs_examples)) print(feature_examples.shape) self.dimensions = feature_examples.shape[1] self.scaler = scaler self.featurizer = featurizer def transform(self, observations): scaled = self.scaler.transform(observations) return self.featurizer.transform(scaled) ``` # 操作步驟 我們按以下步驟進行: 1. 第一步是導入必要的模塊。 這次,除了我們通常的 TensorFlow,Numpy 和 Matplotlib,我們還將從 scikit 導入 Gym 和一些類: ```py import numpy as np import tensorflow as tf import gym import matplotlib.pyplot as plt from sklearn.pipeline import FeatureUnion from sklearn.preprocessing import StandardScaler from sklearn.kernel_approximation import RBFSampler ``` 2. 在 Q 學習中,我們使用 NN 作為函數逼近器來估計值函數。 我們定義一個線性`NeuralNetwork`類; NN 將把變換后的觀測空間作為輸入并預測估計的`Q`值。 由于我們有兩個可能的動作,因此我們需要兩個不同的神經網絡對象來獲取預測的狀態動作值。 該類包括訓練單個 NN 和預測輸出的方法: ```py class NeuralNetwork: def __init__(self, D): eta = 0.1 self.W = tf.Variable(tf.random_normal(shape=(D, 1)), name='w') self.X = tf.placeholder(tf.float32, shape=(None, D), name='X') self.Y = tf.placeholder(tf.float32, shape=(None,), name='Y') # make prediction and cost Y_hat = tf.reshape(tf.matmul(self.X, self.W), [-1]) err = self.Y - Y_hat cost = tf.reduce_sum(tf.pow(err,2)) # ops we want to call later self.train_op = tf.train.GradientDescentOptimizer(eta).minimize(cost) self.predict_op = Y_hat # start the session and initialize params init = tf.global_variables_initializer() self.session = tf.Session() self.session.run(init) def train(self, X, Y): self.session.run(self.train_op, feed_dict={self.X: X, self.Y: Y}) def predict(self, X): return self.session.run(self.predict_op, feed_dict={self.X: X}) ``` 3. 下一個重要的類是`Agent`類,它使用`NeuralNetwork`類來創建學習智能體。 實例化類創建具有兩個線性 NN 的智能體,每個線性 NN 具有 2,000 個輸入神經元和 1 個輸出神經元。 (從本質上講,這意味著該智能體具有 2 個神經元,每個神經元具有 2,000 個輸入,因為 NN 的輸入層不執行任何處理)。 `Agent`類具有定義為預測兩個 NN 的輸出并更新兩個 NN 權重的方法。 此處的智能體在訓練階段使用 Epsilon 貪婪策略進行探索。 在每個步驟中,智能體程序會根據 epsilon(`eps`)的值選擇具有最高`Q`值的操作或隨機操作。 epsilon 在訓練過程中經過退火處理,因此,最初,智能體會采取許多隨機動作(探索),但隨著訓練的進行,會采取具有最大`Q`值的動作(探索)。 這稱為**探索與開發**的權衡取舍:我們允許智能體在被利用的操作過程中探索隨機操作,這使智能體可以嘗試新的隨機操作并從中學習: ```py class Agent: def __init__(self, env, feature_transformer): self.env = env self.agent = [] self.feature_transformer = feature_transformer for i in range(env.action_space.n): model = NeuralNetwork(feature_transformer.dimensions) self.agent.append(model) def predict(self, s): X = self.feature_transformer.transform([s]) return np.array([m.predict(X)[0] for m in self.agent]) def update(self, s, a, G): X = self.feature_transformer.transform([s]) self.agent[a].train(X, [G]) def sample_action(self, s, eps): if np.random.random() < eps: return self.env.action_space.sample() else: return np.argmax(self.predict(s)) ``` 4. 接下來,我們定義一個函數來播放一集; 它類似于我們先前使用的`play_one`函數,但現在我們使用 Q 學習來更新智能體的權重。 我們首先使用`env.reset()`重置環境,然后開始游戲,直到完成游戲為止(并進行了最大迭代以確保程序結束)。 像以前一樣,智能體為當前觀察狀態選擇一個動作,并在環境上執行該動作(`env.step(action)`)。 現在的區別在于,根據先前狀態和采取操作后的狀態,使用`G = r + γ · max[a']Q(s', a')`更新 NN 權重,以便它可以預測與某個動作相對應的準確期望值。 為了獲得更好的穩定性,我們修改了獎勵-桿位下降時,座席會獲得 -400 的獎勵,否則,每一步都會獲得 +1 的獎勵: ```py def play_one(env, model, eps, gamma): obs = env.reset() done = False totalreward = 0 iters = 0 while not done and iters < 2000: action = model.sample_action(obs, eps) prev_obs = obs obs, reward, done, info = env.step(action) env.render() # Can comment it to speed up. if done: reward = -400 # update the model next = model.predict(obs) assert(len(next.shape) == 1) G = reward + gamma*np.max(next) model.update(prev_obs, action, G) if reward == 1: totalreward += reward iters += 1 ``` 5. 現在所有函數和類均已就緒,我們定義了智能體和環境(在本例中為`'CartPole-v0'`)。 該智能體總共播放 1000 集,并通過使用值函數與環境交互來學習: ```py if __name__ == '__main__': env_name = 'CartPole-v0' env = gym.make(env_name) ft = FeatureTransformer(env) agent = Agent(env, ft) gamma = 0.97 N = 1000 totalrewards = np.empty(N) running_avg = np.empty(N) for n in range(N): eps = 1.0 / np.sqrt(n + 1) totalreward = play_one(env, agent, eps, gamma) totalrewards[n] = totalreward running_avg[n] = totalrewards[max(0, n - 100):(n + 1)].mean() if n % 100 == 0: print("episode: {0}, total reward: {1} eps: {2} avg reward (last 100): {3}".format(n, totalreward, eps, running_avg[n]), ) print("avg reward for last 100 episodes:", totalrewards[-100:].mean()) print("total steps:", totalrewards.sum()) plt.plot(totalrewards) plt.xlabel('episodes') plt.ylabel('Total Rewards') plt.show() plt.plot(running_avg) plt.xlabel('episodes') plt.ylabel('Running Average') plt.show() env.close() ``` ![](https://img.kancloud.cn/44/af/44af36008f1ecf5749d09289aec07f6f_933x277.png) 6. 以下是智能體通過游戲獲悉的總獎勵和移動平均獎勵的圖。 根據 Cart-Pole Wiki 的說法,獎勵 200 分表示該特工在接受 1,000 次訓練后贏得了該劇集。 我們的特工播放 100 集時平均獲得 195.7 的平均獎勵,這是一項了不起的壯舉: ![](https://img.kancloud.cn/0d/b1/0db186f6bcc3d9835dcd88c14dccb6b8_640x480.png) ![](https://img.kancloud.cn/64/dc/64dc1a37c75470cba87e52f321fb2889_640x480.png) # 更多 可以使用相同的邏輯為 OpenAI 的其他環境創建智能體。 但是,對于諸如 Breakout 或 Pac-Man 之類的 Atari 游戲,觀察空間并不只是由四個數字組成的數組。 相反,它非常大(210×160 = 33,600 像素,具有 3 個 RGB 值); 如果沒有某種形式的量化,則這種簡單的 NN 可能的狀態是無限的,并且不會產生良好的結果。 我們將在深度 Q 學習秘籍中使用 CNN 解決此問題。 # 另見 盡管有很多有關 Q 學習的 Web 鏈接,但一些有用的鏈接如下: * https://zh.wikipedia.org/wiki/Q-Learning * <http://mnemstudio.org/path-finding-q-learning-tutorial.htm> * <http://artint.info/html/ArtInt_265.html> * <https://medium.com/emergent-future/simple-reinforcement-learning-with-tensorflow-part-0-q-learning-with-tables-and-neural-networks-d195264329d0> # 深度 Q 網絡和 Atari 游戲 **深度 Q 網絡**(**DQN**)是 Q 學習與**卷積神經網絡**(**CNN**)的結合。 [由 Mnih 等人在 2013 年提出](https://arxiv.org/pdf/1312.5602.pdf)。 CNN 網絡具有提取空間信息的能力,因此能夠從原始像素數據中學習成功的控制策略。 我們已經在第 4 章,“卷積神經網絡”中使用了 CNN,因此我們直接從這里開始。 此秘籍基于 DeepMind 的原始 DQN 論文《使用深度強化學習玩 Atari》。 在本文中,他們使用了一種稱為“經驗重放”的概念,該概念涉及隨機采樣先前的游戲動作(狀態,動作獎勵,下一狀態)。位于前腦底部的核稱為“基底神經節”, 根據神經科學,它們負責選擇動作,即幫助我們確定在任何給定時間執行幾種可能動作中的哪一種。 # 準備 如先前的秘籍所述,“用 Q 學習平衡 CartPole”,對于像《吃豆人》或 Breakout 之類的 Atari 游戲,我們需要預處理觀察狀態空間,該狀態空間由 33,600 個像素組成,具有 3 個 RGB 值。 這些像素中的每個像素都可以采用 0 到 255 之間的任何值。我們的`preprocess`函數應該能夠量化像素的可能值,同時減少觀察狀態空間。 我們利用 Scipy 的`imresize`函數對圖像進行下采樣。 以下函數`preprocess`在將圖像饋送到 DQN 之前: ```py def preprocess(img): img_temp = img[31:195] # Choose the important area of the image img_temp = img_temp.mean(axis=2) # Convert to Grayscale# # Downsample image using nearest neighbour interpolation img_temp = imresize(img_temp, size=(IM_SIZE, IM_SIZE), interp='nearest') return img_temp ``` `IM_SIZE`是一個全局參數-在代碼中,我們將其值為 80。該函數具有描述每個過程的注釋。 在這里,您可以看到預處理前后的觀察空間: ![](https://img.kancloud.cn/58/fa/58fa0bfd95bc4e11ce3e2faad1fe64f9_1878x720.png) 要注意的另一重要事項是,當前的觀察空間不能完全顯示游戲情況。 例如,參見上圖,您無法確定槳葉是向左還是向右移動。 因此,為了完全理解游戲的當前狀態,我們需要考慮動作和觀察的順序。 在秘籍中,我們考慮了四個動作和觀察序列,以確定當前情況并訓練智能體。 這是借助`state_update`函數完成的,該函數將當前的觀察狀態附加到先前的狀態,從而生成一系列狀態: ```py def update_state(state, obs): obs_small = preprocess(obs) return np.append(state[1:], np.expand_dims(obs_small, 0), axis=0) ``` 最后,為了解決訓練時的穩定性問題,我們使用了`target_network`的概念,它是 DQN 的副本,但更新頻率不高。 我們使用目標網絡來生成 DQN 網絡的目標值函數,而 DQN 在每個步驟/片段都進行更新,并且`target_network`在固定間隔后進行更新(與 DQN 相同)。 由于所有更新都在 TensorFlow 會話中進行,因此我們使用名稱范圍來區分`target_network`和 DQN 網絡。 # 操作步驟 1. 我們導入必要的模塊。 我們正在使用`sys`模塊的`stdout.flush()`來幫助我們強制 Python *刷新*標準輸出(在我們的情況下為計算機監視器)中的數據。 `random`模塊用于從經驗重放緩沖區(我們存儲過去經驗的緩沖區)中獲取隨機樣本。 `datetime`模塊用于跟蹤訓練時間: ```py import gym import sys import random import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from datetime import datetime from scipy.misc import imresize ``` 2. 我們定義訓練的超參數; 您可以通過更改它們進行試驗。 這些參數定義了經驗重放緩沖區的最小和最大大小以及更新目標網絡之后的情節數量: ```py MAX_EXPERIENCES = 500000 MIN_EXPERIENCES = 50000 TARGET_UPDATE_PERIOD = 10000 IM_SIZE = 80 K = 4 ``` 3. 定義了類`DQN`; 其構造器使用`tf.contrib.layers.conv2d`函數構建 CNN 網絡,并定義成本和訓練操作: ```py class DQN: def __init__(self, K, scope, save_path= 'models/atari.ckpt'): self.K = K self.scope = scope self.save_path = save_path with tf.variable_scope(scope): # inputs and targets self.X = tf.placeholder(tf.float32, shape=(None, 4, IM_SIZE, IM_SIZE), name='X') # tensorflow convolution needs the order to be: # (num_samples, height, width, "color") # so we need to tranpose later self.G = tf.placeholder(tf.float32, shape=(None,), name='G') self.actions = tf.placeholder(tf.int32, shape=(None,), name='actions') # calculate output and cost # convolutional layers Z = self.X / 255.0 Z = tf.transpose(Z, [0, 2, 3, 1]) cnn1 = tf.contrib.layers.conv2d(Z, 32, 8, 4, activation_fn=tf.nn.relu) cnn2 = tf.contrib.layers.conv2d(cnn1, 64, 4, 2, activation_fn=tf.nn.relu) cnn3 = tf.contrib.layers.conv2d(cnn2, 64, 3, 1, activation_fn=tf.nn.relu) # fully connected layers fc0 = tf.contrib.layers.flatten(cnn3) fc1 = tf.contrib.layers.fully_connected(fc0, 512) # final output layer self.predict_op = tf.contrib.layers.fully_connected(fc1, K) selected_action_values = tf.reduce_sum(self.predict_op * tf.one_hot(self.actions, K), reduction_indices=[1] ) self.cost = tf.reduce_mean(tf.square(self.G - selected_action_values)) self.train_op = tf.train.RMSPropOptimizer(0.00025, 0.99, 0.0, 1e-6).minimize(self.cost) ``` 4. 該類具有設置會話`set_session()`,預測動作值函數`predict()`,更新網絡`update()`以及使用 Epsilon 貪婪算法`sample_action()`選擇動作的方法: ```py def set_session(self, session): self.session = session def predict(self, states): return self.session.run(self.predict_op, feed_dict={self.X: states}) def update(self, states, actions, targets): c, _ = self.session.run( [self.cost, self.train_op], feed_dict={ self.X: states, self.G: targets, self.actions: actions } ) return c def sample_action(self, x, eps): """Implements epsilon greedy algorithm""" if np.random.random() < eps: return np.random.choice(self.K) else: return np.argmax(self.predict([x])[0]) ``` 5. 我們還定義了加載和保存網絡的方法,因為訓練可能會花費一些時間: ```py def load(self): self.saver = tf.train.Saver(tf.global_variables()) load_was_success = True try: save_dir = '/'.join(self.save_path.split('/')[:-1]) ckpt = tf.train.get_checkpoint_state(save_dir) load_path = ckpt.model_checkpoint_path self.saver.restore(self.session, load_path) except: print("no saved model to load. starting new session") load_was_success = False else: print("loaded model: {}".format(load_path)) saver = tf.train.Saver(tf.global_variables()) episode_number = int(load_path.split('-')[-1]) def save(self, n): self.saver.save(self.session, self.save_path, global_step=n) print("SAVED MODEL #{}".format(n)) ``` 6. 將主 DQN 網絡的參數復制到目標網絡的方法如下: ```py def copy_from(self, other): mine = [t for t in tf.trainable_variables() if t.name.startswith(self.scope)] mine = sorted(mine, key=lambda v: v.name) others = [t for t in tf.trainable_variables() if t.name.startswith(other.scope)] others = sorted(others, key=lambda v: v.name) ops = [] for p, q in zip(mine, others): actual = self.session.run(q) op = p.assign(actual) ops.append(op) self.session.run(ops) ``` 7. 我們定義一個函數`learn()`,它預測值函數并更新原始 DQN 網絡: ```py def learn(model, target_model, experience_replay_buffer, gamma, batch_size): # Sample experiences samples = random.sample(experience_replay_buffer, batch_size) states, actions, rewards, next_states, dones = map(np.array, zip(*samples)) # Calculate targets next_Qs = target_model.predict(next_states) next_Q = np.amax(next_Qs, axis=1) targets = rewards + np.invert(dones).astype(np.float32) * gamma * next_Q # Update model loss = model.update(states, actions, targets) return loss ``` 8. 既然我們已經在主代碼中定義了所有特征,我們就可以使用它們來構建和訓練 DQN 網絡以玩 Atari 游戲。 該代碼經過了很好的注釋,并且是對先前 Q 學習代碼的擴展,并增加了經驗重放緩沖區,因此您應該不難理解它: ```py if __name__ == '__main__': # hyperparameters gamma = 0.99 batch_sz = 32 num_episodes = 500 total_t = 0 experience_replay_buffer = [] episode_rewards = np.zeros(num_episodes) last_100_avgs = [] # epsilon for Epsilon Greedy Algorithm epsilon = 1.0 epsilon_min = 0.1 epsilon_change = (epsilon - epsilon_min) / 500000 # Create Atari Environment env = gym.envs.make("Breakout-v0") # Create original and target Networks model = DQN(K=K, gamma=gamma, scope="model") target_model = DQN(K=K, gamma=gamma, scope="target_model") with tf.Session() as sess: model.set_session(sess) target_model.set_session(sess) sess.run(tf.global_variables_initializer()) model.load() print("Filling experience replay buffer...") obs = env.reset() obs_small = preprocess(obs) state = np.stack([obs_small] * 4, axis=0) # Fill experience replay buffer for i in range(MIN_EXPERIENCES): action = np.random.randint(0,K) obs, reward, done, _ = env.step(action) next_state = update_state(state, obs) experience_replay_buffer.append((state, action, reward, next_state, done)) if done: obs = env.reset() obs_small = preprocess(obs) state = np.stack([obs_small] * 4, axis=0) else: state = next_state # Play a number of episodes and learn for i in range(num_episodes): t0 = datetime.now() # Reset the environment obs = env.reset() obs_small = preprocess(obs) state = np.stack([obs_small] * 4, axis=0) assert (state.shape == (4, 80, 80)) loss = None total_time_training = 0 num_steps_in_episode = 0 episode_reward = 0 done = False while not done: # Update target network if total_t % TARGET_UPDATE_PERIOD == 0: target_model.copy_from(model) print("Copied model parameters to target network. total_t = %s, period = %s" % ( total_t, TARGET_UPDATE_PERIOD)) # Take action action = model.sample_action(state, epsilon) obs, reward, done, _ = env.step(action) obs_small = preprocess(obs) next_state = np.append(state[1:], np.expand_dims(obs_small, 0), axis=0) episode_reward += reward # Remove oldest experience if replay buffer is full if len(experience_replay_buffer) == MAX_EXPERIENCES: experience_replay_buffer.pop(0) # Save the recent experience experience_replay_buffer.append((state, action, reward, next_state, done)) # Train the model and keep measure of time t0_2 = datetime.now() loss = learn(model, target_model, experience_replay_buffer, gamma, batch_sz) dt = datetime.now() - t0_2 total_time_training += dt.total_seconds() num_steps_in_episode += 1 state = next_state total_t += 1 epsilon = max(epsilon - epsilon_change, epsilon_min) duration = datetime.now() - t0 episode_rewards[i] = episode_reward time_per_step = total_time_training / num_steps_in_episode last_100_avg = episode_rewards[max(0, i - 100):i + 1].mean() last_100_avgs.append(last_100_avg) print("Episode:", i,"Duration:", duration, "Num steps:", num_steps_in_episode, "Reward:", episode_reward, "Training time per step:", "%.3f" % time_per_step, "Avg Reward (Last 100):", "%.3f" % last_100_avg,"Epsilon:", "%.3f" % epsilon) if i % 50 == 0: model.save(i) sys.stdout.flush() #Plots plt.plot(last_100_avgs) plt.xlabel('episodes') plt.ylabel('Average Rewards') plt.show() env.close() ``` ![](https://img.kancloud.cn/69/20/6920d5f7947655fc1609bec514c87a3a_640x480.png) 從上圖中我們可以看到,特工通過訓練獲得了更高的報酬,并且通過每 100 集的平均報酬圖可以清楚地看到情況: ![](https://img.kancloud.cn/cb/63/cb632585a5dc699ee37db4cf54d583c1_640x480.png) 這只是在訓練的前 500 集之后; 為了獲得更好的效果,您將需要訓練更長的時間,約 10,000 集。 # 更多 訓練智能體需要花費很多時間,這既浪費時間又消耗內存。 OpenAI Gym 提供了一個包裝器來將游戲另存為視頻,因此,除了使用渲染之外,您還可以使用包裝器來保存視頻并隨后監視智能體的學習方式。 AI 工程師和發燒友可以上傳這些視頻以顯示結果。 為此,我們需要首先導入包裝器,然后創建環境,最后使用監視器。 默認情況下,它將存儲 1、8、27、64 等視頻,然后每第 1000 集(帶有完美立方體的情節編號)存儲; 默認情況下,每項訓練都保存在一個文件夾中。 為此要添加的代碼如下: ```py import gym from gym import wrappers env = gym.make('Breakout-v0) env = wrappers.Monitor(env, '/save-path') ``` 如果您想在下一個訓練中使用相同的文件夾,可以將`force=True`添加到監視器。 # 另見 * `Mnih, Volodymyr, and others, Playing Atari with deep reinforcement learning, arXiv preprint arXiv:1312.5602 (2013) (https://arxiv.org/pdf/1312.5602.pdf)` * `Mnih, Volodymyr, et al. Human-level control through deep reinforcement learning,?Nature?518.7540 (2015): 529-533` * [玩 Atari 的 DQN 的一個很酷的實現](https://github.com/devsisters/DQN-tensorflow) # 使用策略梯度玩 Pong 游戲 到目前為止,策略梯度是最常用的 RL 算法之一。 研究表明,經過適當調優后,它們的表現要優于 DQN,同時不會遭受過多的內存和計算缺點。 與 Q 學習不同,策略梯度使用參數化策略,該策略可以選擇操作而不咨詢值函數。 在策略梯度中,我們討論了表現度量`η(θ[p])`; 目標是最大程度地提高表現,因此根據梯度上升算法更新 NN 的權重。 但是,TensorFlow 沒有`maximum`優化器,因此我們使用表現梯度的負值`-?η(θ[p])`并將其最小化。 # 準備 Pong 的游戲是一個兩人游戲,目標是將球彈回另一位玩家。 智能體可以上下移動操縱桿(是的,是標準`NoOp`)。 OpenAI 環境中的一名玩家是一位體面的 AI 玩家,他知道如何很好地玩游戲。 我們的目標是使用策略梯度來訓練第二個智能體。 我們的經紀人精通所玩的每款游戲。 雖然代碼已構建為只能運行 500 集,但我們應該添加一條規定以將智能體狀態保存在指定的檢查點,并且在下一次運行時,首先加載上一個檢查點。 為此,我們首先聲明一個保護程序,然后使用 TensorFlow `saver.save`方法保存當前的網絡狀態(檢查點),最后從最后保存的檢查點加載網絡。 為完成本秘籍的部分,在“操作步驟”一節中定義的以下`PolicyNetwork`類方法可以執行此工作: ```py def load(self): self.saver = tf.train.Saver(tf.global_variables()) load_was_success = True # yes, I'm being optimistic try: save_dir = '/'.join(self.save_path.split('/')[:-1]) ckpt = tf.train.get_checkpoint_state(save_dir) load_path = ckpt.model_checkpoint_path self.saver.restore(self.session, load_path) except: print("no saved model to load. starting new session") load_was_success = False else: print("loaded model: {}".format(load_path)) saver = tf.train.Saver(tf.global_variables()) episode_number = int(load_path.split('-')[-1]) ``` 為了每 50 集保存一次模型,我們使用以下方法: ```py def save(self): self.saver.save(self.session, self.save_path, global_step=n) print("SAVED MODEL #{}".format(n)) ``` # 操作步驟 1. 此秘籍的代碼基于 [Andrej Karpathy 博客](http://karpathy.github.io/2016/05/31/rl/),并且其中一部分已由 [Sam Greydanus](https://gist.github.com/karpathy/a4166c7fe253700972fcbc77e4ea32c5) 的代碼進行了改編。 2. 我們有通常的導入: ```py import numpy as np import gym import matplotlib.pyplot as plt import tensorflow as tf ``` 3. 我們定義我們的`PolicyNetwork`類。 在類構建期間,還將初始化模型超參數。 `__init__`方法定義輸入狀態`self.tf_x`的占位符; 預測作用,`self.tf.y`; 相應的獎勵,`self.tf_epr`; 網絡權重; 并預測行動值,訓練和更新。 您可以看到該類構造還啟動了一個交互式 TensorFlow 會話: ```py class PolicyNetwork(object): def __init__(self, N_SIZE, h=200, gamma=0.99, eta=1e-3, decay=0.99, save_path = 'models2/pong.ckpt' ): self.gamma = gamma self.save_path = save_path # Placeholders for passing state.... self.tf_x = tf.placeholder(dtype=tf.float32, shape=[None, N_SIZE * N_SIZE], name="tf_x") self.tf_y = tf.placeholder(dtype=tf.float32, shape=[None, n_actions], name="tf_y") self.tf_epr = tf.placeholder(dtype=tf.float32, shape=[None, 1], name="tf_epr") # Weights xavier_l1 = tf.truncated_normal_initializer(mean=0, stddev=1\. / N_SIZE, dtype=tf.float32) self.W1 = tf.get_variable("W1", [N_SIZE * N_SIZE, h], initializer=xavier_l1) xavier_l2 = tf.truncated_normal_initializer(mean=0, stddev=1\. / np.sqrt(h), dtype=tf.float32) self.W2 = tf.get_variable("W2", [h, n_actions], initializer=xavier_l2) # Build Computation # tf reward processing (need tf_discounted_epr for policy gradient wizardry) tf_discounted_epr = self.tf_discount_rewards(self.tf_epr) tf_mean, tf_variance = tf.nn.moments(tf_discounted_epr, [0], shift=None, name="reward_moments") tf_discounted_epr -= tf_mean tf_discounted_epr /= tf.sqrt(tf_variance + 1e-6) # Define Optimizer, compute and apply gradients self.tf_aprob = self.tf_policy_forward(self.tf_x) loss = tf.nn.l2_loss(self.tf_y - self.tf_aprob) optimizer = tf.train.RMSPropOptimizer(eta, decay=decay) tf_grads = optimizer.compute_gradients(loss, var_list=tf.trainable_variables(), grad_loss=tf_discounted_epr) self.train_op = optimizer.apply_gradients(tf_grads) # Initialize Variables init = tf.global_variables_initializer() self.session = tf.InteractiveSession() self.session.run(init) self.load() ``` 4. 我們定義了一種計算折現獎勵的方法。 這確保智能體不僅考慮當前獎勵,而且考慮未來獎勵。 任意時間`t`的折現獎勵為`R[t] = ∑γ[k]r[t + k]`,其中總和超過`k∈[0, ∞]`,并且`γ`是貼現因子,值在 0 到 1 之間。在我們的代碼中,我們使用了`gamma = 0.99`: ```py def tf_discount_rewards(self, tf_r): # tf_r ~ [game_steps,1] discount_f = lambda a, v: a * self.gamma + v; tf_r_reverse = tf.scan(discount_f, tf.reverse(tf_r, [0])) tf_discounted_r = tf.reverse(tf_r_reverse, [0]) return tf_discounted_r ``` 5. 在給定輸入觀察狀態的情況下,我們定義了`tf_policy_forward`方法來提供將槳向上移動的概率。 我們使用兩層神經網絡實現它。 網絡獲取處理過的游戲狀態圖像,并生成一個數字,表示將球拍向上移動的可能性。 在 TensorFlow 中,由于僅在 TensorFlow 會話中計算網絡圖,因此我們定義了另一種方法`predict_UP`來計算概率: ```py def tf_policy_forward(self, x): #x ~ [1,D] h = tf.matmul(x, self.W1) h = tf.nn.relu(h) logp = tf.matmul(h, self.W2) p = tf.nn.softmax(logp) return p def predict_UP(self,x): feed = {self.tf_x: np.reshape(x, (1, -1))} aprob = self.session.run(self.tf_aprob, feed); return aprob ``` 6. `PolicyNetwork`智能體使用`update`方法更新權重: ```py def update(self, feed): return self.session.run(self.train_op, feed) ``` 7. 我們定義一個輔助函數來預處理觀察狀態空間: ```py # downsampling def preprocess(I): """ prepro 210x160x3 uint8 frame into 6400 (80x80) 1D float vector """ I = I[35:195] # crop I = I[::2,::2,0] # downsample by factor of 2 I[I == 144] = 0 # erase background (background type 1) I[I == 109] = 0 # erase background (background type 2) I[I != 0] = 1 # everything else (paddles, ball) just set to 1 return I.astype(np.float).ravel() ``` 8. 其余的很簡單-我們創建一個游戲環境,定義要持有的數組(狀態,動作,獎勵,狀態),并使智能體學習大量情節(休息或連續不斷),這完全取決于您的計算能力和資源)。 這里要注意的重要一點是,智能體沒有按動作步驟學習。 相反,智能體使用一個情節的完整(狀態,動作,獎勵,狀態)集來糾正其策略。 這可能會占用大量內存: ```py if __name__ == '__main__': # Create Game Environment env_name = "Pong-v0" env = gym.make(env_name) env = wrappers.Monitor(env, '/tmp/pong', force=True) n_actions = env.action_space.n # Number of possible actions # Initializing Game and State(t-1), action, reward, state(t) xs, rs, ys = [], [], [] obs = env.reset() prev_x = None running_reward = None running_rewards = [] reward_sum = 0 n = 0 done = False n_size = 80 num_episodes = 500 #Create Agent agent = PolicyNetwork(n_size) # training loop while not done and n< num_episodes: # Preprocess the observation cur_x = preprocess(obs) x = cur_x - prev_x if prev_x is not None else np.zeros(n_size*n_size) prev_x = cur_x #Predict the action aprob = agent.predict_UP(x) ; aprob = aprob[0,:] action = np.random.choice(n_actions, p=aprob) #print(action) label = np.zeros_like(aprob) ; label[action] = 1 # Step the environment and get new measurements obs, reward, done, info = env.step(action) env.render() reward_sum += reward # record game history xs.append(x) ; ys.append(label) ; rs.append(reward) if done: # update running reward running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 running_rewards.append(running_reward) feed = {agent.tf_x: np.vstack(xs), agent.tf_epr: np.vstack(rs), agent.tf_y: np.vstack(ys)} agent.update(feed) # print progress console if n % 10 == 0: print ('ep {}: reward: {}, mean reward: {:3f}'.format(n, reward_sum, running_reward)) else: print ('\tep {}: reward: {}'.format(n, reward_sum)) # Start next episode and save model xs, rs, ys = [], [], [] obs = env.reset() n += 1 # the Next Episode reward_sum = 0 if n % 50 == 0: agent.save() done = False plt.plot(running_rewards) plt.xlabel('episodes') plt.ylabel('Running Averge') plt.show() env.close() ``` 下圖顯示了智能體在前 500 個情節中學習時的平均運行獎勵: ![](https://img.kancloud.cn/38/8d/388d34a0cde6777231816940e70e0a7b_640x480.png) # 工作原理 權重使用 Xavier 初始化進行了初始化,這確保了我們的權重既不會太大也不會太小。 兩種情況都阻礙了網絡的學習。 在 Xavier 初始化中,為權重分配一個具有零均值和特定方差`2/(nin+nout)`的值,其中`nin`和`nout`該層的輸入和輸出數。 要了解有關 Xavier 初始化的更多信息,請參閱 Glorot 和 Bengio 在 2009 年發表的論文。 有關詳細信息,請參見“另見”部分。 # 更多 看到智能體第一次學習演奏的任何人都會對此感到驚訝-看起來很像人。 最初的舉動總是很笨拙。 緩慢地,坐席會學習走哪條路,盡管速度很慢并且經常會錯過球。 但是,隨著學習的繼續,智能體將成為專家。 但這與我們很不一樣。 一旦學會玩游戲,我們便可以在其他任何類似情況下輕松使用該知識。 RL 智能體將無法執行此操作-即使是簡單的事情(例如更改環境空間的大小)也會將其恢復為零。 遷移學習是研究人員正在研究的一種技術,它可以幫助主體在另一環境空間中的一個環境中使用它所學到的知識,也許有一天可以為真正的人工智能奠定基礎。 # AlphaGo Zero 最近,DeepMind 發表了有關 AlphaGo Zero(AlphaGo 的最新版本)的文章。 根據他們發布的結果,AlphaGo Zero 甚至更強大,并且是歷史上最強大的圍棋選手。 AlphaGo 從表格狀態開始,即從空白狀態開始,并且僅使用棋盤狀態和與其對抗的游戲來調整神經網絡并預測正確的動作。 AlphaGo Zero 使用深層神經網絡,該網絡將原始板表示形式(當前和歷史)作為輸入,并輸出移動概率和值。 因此,該神經網絡結合了策略網絡和值網絡的作用。 該網絡是通過自玩游戲進行訓練的,這與以前的 AlphaGo 版本不同(它們是使用監督學習進行訓練的)。 在每個位置上,由神經網絡指導執行蒙特卡洛樹搜索(MCTS)。 通過使用 MCTS 播放每個動作的自演強化學習算法來訓練神經網絡。 最初,神經網絡的權重是隨機初始化的。 在每個迭代步驟中,都會生成許多自玩游戲。 在每個時間步,使用神經網絡的先前迭代對可能的策略執行 MCTS 搜索,然后通過對搜索概率進行采樣來進行移動。 重復此過程直到該特定游戲終止。 存儲游戲狀態,采取的策略以及游戲每個時間步驟的獎勵。 并行地,根據自播放的先前迭代的所有時間步長之間均勻采樣的數據訓練神經網絡。 調整神經網絡的權重,以最小化預測值和自贏者之間的誤差,并使神經網絡移動概率與搜索概率的相似性最大化。 在配備 4 個 TPU 的單臺機器上僅進行了 3 天的訓練,AlphaGo Zero 以 100-0 擊敗 AlphaGo。 AlphaGo Zero 完全基于 RL。 可以在 2017 年 10 月發表于《自然》上的論文《掌握無人掌握的圍棋游戲》中閱讀其實現的詳細信息。 # 另見 * <https://arxiv.org/pdf/1602.01783.pdf> * <http://ufal.mff.cuni.cz/~straka/courses/npfl114/2016/sutton-bookdraft2016sep.pdf> * <http://karpathy.github.io/2016/05/31/rl/> * `Xavier Glorot and Yoshua Bengio, Understanding the difficulty of training deep feedforward neural networks,?Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics,?2010,?http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf`
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看