當前位置: 華文星空 > 體育

DeepMind 研發的圍棋 AI AlphaGo 是如何下棋的?

2017-05-19體育

2016年,DeepMind的圍棋機器人AlphaGo在與李世石的第二局對決中第37手落子的瞬間,整個圍棋界都震驚了。評棋人Michael Redmond,一位有著近千場頂級比賽經驗的職業棋手,在直播中目瞪口呆,他甚至把這顆棋子從棋盤上拿下來觀察周邊的情況,仿佛要確認AlphaGo是否下錯了棋。第二天,Redmond告訴美國圍棋E雜誌:「我到現在還不明白這步棋背後的道理。」李世石這位統治了世界棋壇十年的大師,花了 12 分鐘來研究這一棋局,之後才做出回應。圖 13-1展示了這手傳說中的落子。

圖13-1 AlphaGo在對陣李世石的第二局中做出的傳奇落子動作。這手落子震驚了許多職業棋手

這手落子完全違背了傳統的圍棋理論。對角落子,或者叫尖沖,會引誘白子沿著邊界繼續長出,並做出一道實墻。人們通常認為這是一個五五開的交換:白方獲得邊界的空點,而黑方則獲得對棋盤中央區域的影響力。但是白棋落在離邊界4格的地方,一旦讓黑方做出實墻,黑方會得到過多的地盤。(我們需要對正在閱讀的圍棋高手表示歉意,這裏的描述做了過多的簡化。)第5行的尖沖看起來有些業余——至少在「AlphaGo教授」最終五局四勝戰勝這位傳奇棋手之前看來確實如此。在這一步尖沖之後,AlphaGo還做出了許多出人意料的落子動作。一年之後,上到頂級職業棋手,下至業余俱樂部棋手,所有人都在嘗試模仿AlphaGo所采用的動作。

【深度學習與圍棋】這本書的第二部份分層次深入介紹AlphaGo背後的機器學習和深度學習技術,包括樹搜尋、神經網絡、深度學習機器人和強化學習,以及強化學習的幾個高級技巧,包括策略梯度、價值評估方法、演員-評價方法 3 類技術;第三部份將前面兩部份準備好的知識整合到一起,並最終引導讀者實作自己的AlphaGo,以及改進版AlphaGo Zero。讀完本書之後,讀者會對深度學習這個學科以及AlphaGo的技術細節有非常全面的了解,為進一步深入鉆研AI理論、拓展AI套用打下良好基礎。

小編截選 AlphaGo:全部集結 的部份內容來回答這個問題。

我們將學習組成AlphaGo的所有結構,並了解它的工作機制。AlphaGo是基於職業棋譜的監督深度學習(即我們在第5章至第8章中所學的)與基於自我對弈數據的深度強化學習(即第9章至第12章所介紹的)的一種巧妙結合,然後再創造性地用這兩種深度學習網絡來改進樹搜尋。讀者可能會感覺驚奇,原來我們已經對AlphaGo的所有元件都有所了解了。更精確地說,我們將要詳細介紹AlphaGo系統的如下流程工作。

  • 首先開始訓練 兩個 深度摺積神經網絡(即 策略網絡 ),用於動作預測。在這兩個網絡架構中,其中一個深度更深,能夠 產生更準確的結果 ,而另一個則更淺,可以 更快地進行評估 。我們將它們分別稱為 強策略 網絡和 快策略 網絡。
  • 強策略網絡和快策略網絡采用了更加復雜的棋盤編碼器,包含48個特征平面。它們的網絡架構深度也比我們在第6章和第7章中所見的網絡更深。不過除此之外,它們看起來還是讓人覺得很熟悉的。13.1節會介紹AlphaGo的策略網絡架構。
  • 在13.2節中,在完成了策略網絡的第一個訓練步驟之後,我們將會用強策略網絡作為初始點來進行自我對弈。如果用大量的算力來執行這一步,將會讓機器人得到巨大的改進。
  • 在13.3節中,我們將使用這個強自我對弈網絡來生成一個 價值網絡 。這樣就完成了網絡訓練階段,之後就不用再做任何深度學習了。
  • 要進行一局圍棋對弈,可以把樹搜尋作為下棋策略的基礎。但與第4章的簡單蒙地卡羅推演法不同的是,我們需要使用快策略網絡來指導接下來的步驟。另外,還需要參考價值函數的輸出,來平衡這個樹搜尋演算法的輸出。我們會在13.4節中介紹這種創新技術。
  • 從訓練策略網絡到自我對弈,再到使用超越人類棋手的搜尋樹來下棋的整個過程,都需要巨大的計算資源和計算時間。13.5節會給出幾點思考,解釋AlphaGo如何達到它所具有的強度,以及在進行自己的實驗時合理的預期程度。
  • 圖13-2歸納了我們剛剛列出的整個流程。在本章中,我們會深入討論圖中的各個部份,並在各節中提供更多的細節。

    圖13-2 如何訓練AlphaGo AI背後的3個神經網絡。首先,從人類棋譜集合開始,訓練兩個神經網絡來預測下一步動作:一個網絡更小更迅速,而另一個更大更準確。接著,我們可以繼續透過自我對弈來改進較大網絡的效能。自我對弈同時也為訓練一個價值網絡提供了數據。最後,AlphaGo會在一個樹搜尋演算法中同時采用這3個網絡,得到極強的對弈表現

    13.1 為AlphaGo訓練深度神經網絡

    在前面的介紹中我們已經了解到,AlphaGo使用了3個神經網絡:2個策略網絡和1個價值網絡。雖然看起來有點多,但在本節中我們將會看到,這幾個網絡以及它們的輸入特征在概念上是很接近的。而關於AlphaGo所用的深度學習技術,最令人驚奇的地方反而是我們對它們的熟悉程度,本書在第5章至第12章已經對它們做了大量的介紹。在深入介紹這幾個神經網絡的構建和訓練的細節之前,讓我們先討論一下它們在AlphaGo系統中所扮演的角色。

  • 快策略網絡 ——這個圍棋動作預測網絡與第7章和第8章中訓練的網絡有相似的規模。它的目的並不是成為最準確的動作預測器,而是在保證足夠好的預測準確率的同時能夠非常迅速地做出動作預測。13.4節介紹的樹搜尋推演過程會使用這個網絡——而我們已經在第4章中了解到,在樹搜尋中要做到基本可用的程度,推演時必須能夠迅速建立大量的網絡。我們不會對這個網絡做太深入的討論,而會將更多的精力放在下面兩個網絡上。
  • 強策略網絡 ——這個動作預測網絡的最佳化目標是準確率,而不是速度。它是一個摺積網絡,其架構比快策略網絡的要深很多,而且動作預測的效果比快策略網絡好兩倍。和快策略網絡一樣,這個網絡也是用人工棋譜數據訓練得出的,這一點與第7章介紹的相同。訓練好這個網絡之後,就可以把它作為起始點來進行自我對弈,並采用第9章和第10章中介紹的強化學習技術進行改良。這個過程能夠讓強策略網絡變得更加強大。
  • 價值網絡 ——強策略網絡進行的自我對弈產生了一個新的數據集,可以用來訓練一個價值網絡。具體來說,我們將采用這些棋局的輸出,以及第11章和第12章中介紹的技術,來學習一個價值函數。它會在13.4節中扮演關鍵角色。
  • 13.1.1 AlphaGo的網絡架構

    現在我們已經基本了解了這3個深度神經網絡在AlphaGo中的作用,下一步接著展示如何在Python的Keras庫構建它們。在深入討論程式碼之前,我們先概述這幾個網絡的架構,如下所示。如果讀者需要溫習摺積網絡的術語,請再次閱讀第7章。

  • 強策略網絡是一個13層摺積網絡。這13層都產出19×19的過濾器,也就是說,在整個網絡中,我們都保留了初始的棋盤尺寸。與第7章一樣,我們需要把這個網絡的輸入進行 對齊 pad )操作。第一個摺積層的核心尺寸是5,而後面的所有層的核心尺寸都是3。最後一層采用softmax啟用函數,並且有一個輸出過濾器。前12層都采用ReLU啟用函數,且各有192個輸出過濾器。
  • 價值網絡是一個16層摺積網絡。它的前12層與強策略網絡 完全一致 。第13層是一個額外的摺積層,與第2~12層結構一致。第14層是一個核心尺寸為1、有一個輸出過濾器的摺積層。網絡最後以兩個稠密層結束,一個有256個輸出,采用ReLU啟用函數;另一個只有單個輸出,並采用tanh啟用函數。
  • 可以看到,在AlphaGo中策略網絡和價值網絡采用的正是第6章所介紹的深度摺積神經網絡。這兩個網絡非常相似,我們甚至可以直接用一個Python函數來定義它們。在此之前,我們先看看Keras的一種特殊用法,它可以顯著地縮短網絡的定義。第7章中講過,我們可以使用Keras的 ZeroPadding2D 實用工具層來對齊輸入影像。這樣做完全沒問題,但如果把它的功能移入 Conv2D 層中,就能在模型定義時節省許多筆墨。在價值網絡和策略網絡中,可以對齊每個摺積層的輸入,使它們的輸出過濾器的尺寸與輸入 相同 (19×19)。例如,按照我們以往的做法,第1層有19×19輸入,第2層核心尺寸為5,輸出是19×19過濾器,需要將第1層對齊成23×23的影像。而現在我們可以直接讓摺積層維持輸入尺寸,只需在定義摺積層時提供參數 padding='same' ,它就能夠自己處理對齊操作了。有了這種快捷定義,接下來我們就可以方便地定義AlphaGo的策略網絡與價值網絡所共有的11個層,如程式碼清單13-1所示。讀者可以在GitHub程式碼庫中的dlgo.networks模組中的alphago.py檔中找到這個定義。

    程式碼清單13-1 為AlphaGo的策略網絡和價值網絡初始化神經網絡

    from keras.models import Sequential from keras.layers.core import Dense, Flatten from keras.layers.convolutional import Conv2D def alphago_model(input_shape, is_policy_net=False, ⇽--- 這個布爾值選項用來在初始化時指定是策略網絡還是價值網絡 num_filters=192, ⇽--- 除最後一個摺積層之外,所有層的過濾器數量都相同 first_kernel_size=5, other_kernel_size=3): ⇽--- 第1層的核心尺寸為5,其他層都是3 model = Sequential() model.add( Conv2D(num_filters, first_kernel_size, input_shape=input_shape, padding='same', data_format='channels_first', activation='relu')) for i in range(2, 12): ⇽--- AlphaGo的策略網絡和價值網絡的前12層完全一致 model.add( Conv2D(num_filters, other_kernel_size, padding='same', data_format='channels_first', activation='relu'))

    註意,我們還沒有指定第1層的輸入形狀。這是因為這個形狀在策略網絡和價值網絡中略有不同。我們可以在13.1.2節介紹AlphaGo的棋盤編碼器的程式碼中看到這個區別。繼續 model 的定義,我們還差一個最終摺積層就能完成強策略網絡的定義,如程式碼清單13-2所示。

    程式碼清單13-2 在Keras中建立AlphaGo的強策略網絡

    if is_policy_net: model.add( Conv2D(filters=1, kernel_size=1, padding='same', data_format='channels_first', activation='softmax')) model.add(Flatten()) return model

    可以看到,最後需要添加一個 Flatten 層來展平前面的預測輸出,並確保與第5章至第8章中定義的模型的一致性。

    如果想要返回的是AlphaGo的價值網絡,可以再添加兩個 Conv2D 層、一個 Flatten 層和兩個 Dense 層,然後將它們連線起來,如程式碼清單13-3所示。

    程式碼清單13-3 在Keras中構建AlphaGo的價值網絡

    else: model.add( Conv2D(num_filters, other_kernel_size, padding='same', data_format='channels_first', activation='relu')) model.add( Conv2D(filters=1, kernel_size=1, padding='same', data_format='channels_first', activation='relu')) model.add(Flatten()) model.add(Dense(256, activation='relu')) model.add(Dense(1, activation='tanh')) return model

    這裏我們不具體討論快策略網絡的架構。快策略網絡的輸入特征定義與網絡架構有更多技術細節,但並不能幫助我們加深對AlphaGo系統的理解。所以如果讀者想要進行自己的試驗,完全可以直接采用我們在dlog.networks模組中已經定義好的網絡,例如 small medium large 。快策略網絡的主要目的是構建一個比強策略網絡更小的網絡,能夠進行快速評估。接下來我們會深入了解訓練過程的細節。

    13.1.2 AlphaGo棋盤編碼器

    現在我們已經了解了AlphaGo使用的所有網絡,下面討論一下AlphaGo如何對棋盤數據進行編碼。在第6章和第7章中我們已經實作了不少棋盤編碼器,包括 oneplane sevenplane simple ,這些編碼器都存放在dlgo.encoders模組中。AlphaGo所使用的特征平面會比它們更復雜一些,但也是這些已知編碼器的自然延續。

    AlphaGo策略網絡所用的棋盤編碼器有48個特征平面,而它的價值網絡還需要再添加一個平面。這48個平麪包含11種概念,其中一部份是我們已經見過的,其他則是新的,我們會逐一詳細討論。總的來說,與以往的編碼器相比,AlphaGo更多地利用了圍棋專有的定式。最典型的例子就是在特征集合中引入了 征子和引征 概念(參見圖13-3)。

    圖13-3 AlphaGo將很多圍棋策略概念直接編碼到特征平面中,包括征子概念。在第一個例子中,白子只剩一口氣了,這意味著黑方可以在下一回合吃掉它。白方可以長出來增加一口氣,但是黑方也可以接著落子將白子的氣減少為一口。這樣一直持續下去,直到碰到棋盤邊線,白子還是會被全部吃掉。而在另一種情況下,如果在征子的路線上已經有一顆白子,白方就有可能逃離被吃子的命運。AlphaGo中有一個特征平面專門用來表示征子是否能成功

    我們之前所有的圍棋棋盤編碼器都采用了一個技巧,即 二元特征 binary feature ),這個技巧在AlphaGo中也被采用。例如,在捕獲氣的概念(棋盤上相鄰的空白點)時,我們並不只用一個特征平面來表示棋盤上每顆棋子的氣數,而是用3個二元表達的平面來表示一顆棋子是有1口氣、2口氣還是3口氣。在AlphaGo中也可以看到相同的做法,但是它采用了8個特征平面來記錄二元計數。在氣的例子中,這意味著8個平面分別代表每顆棋子是否有1口、2口、3口、4口、5口、6口、7口和至少8口氣。

    AlphaGo與第6章至第8章中介紹的唯一不同點在於,它將棋子的顏色獨立出來,顯式地編碼到另一個單獨的特征平面中。回顧一下第7章的 sevenplane 編碼器,我們的眼平面同時包含黑子平面和白子平面,而AlphaGo只用一個特征集合用來記錄氣的數量,並且所有的特征都是針對下一回合的執子方。例如,在特征集「吃子數」(用來記錄一個動作能吃掉的棋子數目)中,只記錄 當前 執子方能夠吃掉的棋子數量,不論它是黑方還是白方。

    表13-1總結了AlphaGo所使用的全部特征平面。前48個平面用於策略網絡,最後一個只用於價值網絡。

    表13-1 AlphaGo所使用的特征平面(略)

    這些特征的實作可以在本書的GitHub程式碼庫中的dlgo.encoder模組中找到,檔是alphago.py。雖然每一個特征集的實作都不困難,但和我們將要介紹的AlphaGo其他部份相比,它們並不顯得很有趣。實作「征子提子」平面難度較高,而且要對一個動作從執行時到現在的回合數進行編碼,需要修改圍棋棋盤的定義。因此如果讀者對這些實作有興趣的話,可以參看GitHub上的實作程式碼。

    讓我們看看 AlphaGoEncoder 如何初始化,然後把它套用到深度神經網絡的訓練中。它需要一個圍棋棋盤尺寸參數,以及一個布爾值參數 use_player_plane (代表是否包含第49個平面)。程式碼清單13-4展示了它的簽名以及初始化過程。

    程式碼清單13-4 AlphaGo棋盤編碼器的簽名以及初始化

    class AlphaGoEncoder(Encoder): def __init__(self, board_size, use_player_plane=False): self.board_width, self.board_height = board_size self.use_player_plane = use_player_plane self.num_planes = 48 + use_player_plane

    13.1.3 訓練AlphaGo風格的策略網絡

    網絡架構和輸入特征都準備好之後,我們開始為AlphaGo訓練策略網絡。第一步與第7章的流程完全一致:指定一個棋盤編碼器和一個代理,載入棋譜數據,並使用這些數據來訓練代理。圖13-4展示了這個流程。雖然我們使用了更加復雜的特征和網絡,但流程還是完全一樣的。

    圖13-4 AlphaGo的策略網絡監督訓練過程與第6章和第7章中介紹的完全一致。我們對人工棋譜進行復盤,並重新產生一系列遊戲狀態。每個遊戲狀態編碼為一個張量(這個圖展示了一個只有兩個平面的張量,而AlphaGo實際使用了48個平面)。訓練目標是一個與棋盤尺寸相同的向量,並在實際落子點填入1

    要初始化並訓練AlphaGo的強策略網絡,需要先初始化一個 AlphaGoEncoder ,然後建立兩個圍棋數據生成器,分別用於訓練和測試,如程式碼清單13-5所示。這個步驟與第7章一樣。這一步的程式碼可以在GitHub上的examples/alphago/alphago_policy_sl.py檔中找到。

    程式碼清單13-5 為AlphaGo的策略網絡的第一步訓練載入數據

    from dlgo.data.parallel_processor import GoDataProcessor from dlgo.encoders.alphago import AlphaGoEncoder from dlgo.agent.predict import DeepLearningAgent from dlgo.networks.alphago import alphago_model from keras.callbacks import ModelCheckpoint import ppy rows, cols = 19, 19 num_ classes = rows * cols num_games = 10000 encoder = AlphaGoEncoder() processor = GoDataProcessor(encoder=encoder.name()) generator = processor.load_go_data('train', num_games, use_generator=True) test_generator = processor.load_go_data('test', num_games, use_generator=True)

    接下來,我們可以使用本節之前定義的 alphago_model 函數來載入AlphaGo的策略網絡,並采用分類交叉熵損失函數和隨機梯度下降法來對這個 Keras 模型進行編譯,如程式碼清單 13-6所示。我們把這個模型稱為 alphago_sl_policy ,以表示它是一個采用監督學習(sl是supervised learning的簡寫)的策略網絡。

    程式碼清單13-6 用Keras建立一個AlphaGo策略網絡

    input_shape = (encoder.num_planes, rows, cols) alphago_sl_policy = alphago_model(input_shape, is_policy_net=True) alphago_sl_policy.compile('sgd', 'categorical_crossentropy', metrics=['accuracy'])

    現在第一階段的訓練只剩下最後一步了。和第7章一樣,使用訓練生成器和測試生成器對這個策略網絡呼叫 fit_generator 。除網絡更大、編碼器更復雜之外,其他地方都和第6章至第8章完全一樣。

    訓練結束後,我們可以從 model encoder 建立一個 DeepLearningAgent ,並把它儲存起來(如程式碼清單13-7所示),以備後面討論的兩個訓練階段使用。

    程式碼清單13-7 訓練一個策略網絡並持久化儲存

    epochs = 200 batch_size = 128 alphago_sl_policy.fit_generator( generator=generator.generate(batch_size, num_ classes), epochs=epochs, steps_per_epoch=generator.get_num_samples() / batch_size, validation_data=test_generator.generate(batch_size, num_ classes), validation_steps=test_generator.get_num_samples() / batch_size, callbacks=[ModelCheckpoint('alphago_sl_policy_{epoch}.p')] ) alphago_sl_agent = DeepLearningAgent(alphago_sl_policy, encoder) with ppy.File('alphago_sl_policy.p', 'w') as sl_agent_out: alphago_sl_agent.serialize(sl_agent_out)

    為簡潔起見,在本章中我們並不需要像AlphaGo論文所說的那樣分別訓練強策略網絡和快策略網絡。我們不另外單獨訓練一個更小更快的策略網絡,而是直接使用alphago_sl_agent作為快策略網絡。下一節會介紹如何以這個代理為起點進行強化學習,生成一個更強的策略網絡。

    讀到這裏還想繼續探索,可以閱讀【深度學習與圍棋】

    1.本書是一本人工智能的實踐性入門教程,成功地把AlphaGo這個人工智能領域中最激動人心的裏程碑之一,轉化為一門優秀的入門課程;
    2.采用Keras深度學習框架,用Python來實作程式碼;
    3.內容全面,層次劃分細致,基本上將AlphaGo背後所有的理論知識都覆蓋了;
    4.提供配套原始碼。

    圍棋這個古老的策略遊戲是AI研究的特別適用的案例。2016年,一個基於深度學習的系統戰勝了圍棋世界冠軍,震驚了整個圍棋界。不久之後,這個系統的升級版AlphaGo Zero利用深度強化學習掌握了圍棋技藝,輕松擊敗了其原始版本。讀者可以透過閱讀本書來學習潛藏在它們背後的深度學習技術,並構建屬於自己的圍棋機器人!

    本書透過教讀者構建一個圍棋機器人來介紹深度學習技術。隨著閱讀的深入,讀者可以透過Python深度學習庫Keras采用更復雜的訓練方法和策略。讀者可以欣賞自己的機器人掌握圍棋技藝,並找出將學到的深度學習技術套用到其他廣泛的場景中的方法。