用深度學習技術自編碼你的皮卡丘 ?
歡迎訪問我們的主站:集智 - 通向智能時代的引擎
好像每隔幾個月就會有謠言傳說在 2016 年火遍國外的遊戲 Pokemon Go 即將由網易代理的形式登錄中國市場,不知真假,反正期待這條消息是真的吧。
於 2016 年 7 月上線的 Pokemon Go,當時那叫一個火爆。不管是在室內還是室外,國外到處都能看到有人拿著手機抓小精靈。
目前,Pokemon Go 已經更新到第三世代,並加入對蘋果 ARKit 的支持。玩家可以在遊戲中抓到超過 300 種 Pokemon,玩法也越來越多。國外有個叫 Niyas Mohammed 的程序員小哥決定嘗試一個新玩法:用深度學習技術自編碼遊戲中的小精靈!
看看他是怎麼玩的吧:
我(本文作者Niyas Mohammed——譯者注)最近在學習深度學習技術,學到了自動編碼器(autoencoder)這裡後,我決定自己實踐一番,那就自編碼我的 Pokemon 吧。
什麼是自動編碼器?
首先我先給沒聽說過這個詞的朋友解釋一下,知道的請先等等我,容我多說幾句。
自動編碼器是深度學習中的一種演算法,這種演算法的大致思想是:將神經網路的隱含層看成是一個編碼器和解碼器,輸入數據經過隱含層的編碼和解碼,到達輸出層時,確保輸出的結果盡量與輸入數據保持一致。
也就是說,隱含層是盡量保證輸出數據等於輸入數據的。這樣做的一個好處是,隱含層能夠抓住輸入數據的特點,使其特徵保持不變。由於隱含層的任務是尋找輸入數據的特徵,所以自動編碼器會盡量用最少的維度來代表輸入速度(此處劃重點)。
這麼比方吧,把這個過程想像成你畫了一個圈,用這個圈代表一個球體。你知道實際上這就是一個球體,但是你覺得在做課堂筆記時簡單畫個圈比真的描出一個球體要方便的多。將來哪天你回頭翻看筆記時,你看見這個圈,還是會把它當成球體來理解。之所以能這樣,是因為你潛意識的學會了將一個3維球體自動編碼成了一個2維圓圈。
懂了吧?在這個過程中,你就相當於一個自動編碼器!實際上,你也知道你不光能畫圈,還能畫方塊,達芬奇甚至能畫出《蒙娜麗莎》。從本質上講,我們寫東西的過程,就是將我們的思維自動編碼為2維字體的一個過程。好了,現在你應該能理解自動編碼器這個概念了。
一個自動編碼器包含兩個部分:一個編碼器,學習將輸入數據(X)轉換為一個較低維度的表示形式(Z);一個解碼器,學習將較低維度的表示形式(Z)轉換為其初始維度(Y)。
如果你的編碼器性能很好,那麼你的輸入數據和輸出會是一致的。那就是個很完美的自動編碼器了。不過在實際操作中,很難達到這麼好的效果。
那麼我們為什麼要自動編碼呢?
很多人會想到這是為了壓縮,對吧?因為你在減少維度,這樣你只需傳遞較低維度的數據就行了。但是想想看,即便是我們實現了壓縮,我們還是要把解碼器傳遞給別人,好讓他們能理解我們最開始都編碼了什麼信息。
我舉個例子,想想一下我們在英國倫敦傳遞中文小紙條。
比如你想編碼英語單詞「tree」,你會將4個英語字母縮減為中文的一個字「樹」。但是另一個人看到後如果想知道這是什麼意思,通常他也得懂中文才行。所以為了讓其他不懂中文的倫敦人不會把「樹」和其它「木」字旁的字搞混,你還要給他們一份中英對照手冊才行。
很顯然,這會很麻煩。OK,如果不是為了壓縮才用到自動編碼器,那我們用它來幹嘛?
在上面我們提到自動編碼器一般不是完美無缺,其中的解碼器的輸出數據往往和數據被編碼時的狀況不一致。如果我們用它生成和輸入數據相似的輸出數據呢?
這意味著我們可以用自動編碼器生成更多和輸入數據相同的東西。比如,從一堆鮮花照片中生成更多的鮮花照片。
自動編碼器中有個特殊的類型,叫「變分自編碼器」(variational autoencoder,即VAE),是專門設計用來解決這個問題的。VAE可以為我們的編碼過程引入一些變數,生成很多和我們的輸入數據相似的輸出數據。
OK,是時候召喚我們的Pokemon了!
瞧瞧我們的Pokemon
我們用到的Pokemon都是來自任天堂 DS 風格的點陣圖圖像。可以點擊這裡獲取(https://www.pokecommunity.com/showthread.php?t=267728)。
圖像的解析度為 64 X 64。我覺得這比很多人喜歡使用的 MNIST 數據集要好一點,而且這次還是彩色的圖像。每個像素表現為 3 個 RGB 值,所以每張圖像可以表示為 64 x 64 x 3 個值,這就給我們一共 12288 個值。
而且,注意每個 Pokemon 都很獨特,從根本上各不相同,所以會有很多變體。
先看看第一代Pokemon。
我們的數據集里不光有它們的前景圖,還有後視圖。每張視圖都不相同。每個 Pokemon 都有 4 張視圖,會有很多變數!
好的,數據聊完了,我們開始自編碼吧。
我們的自動編碼器如何工作的?
自動編碼器首先會提取所有 64 X 64 X 3 的圖像,把它們壓縮為一個有 12288 個值的一維向量,然後逐步對該向量進行降採樣(downsample),直到得到我們想要的編碼後的維度。實質上,這個過程是一系列的矩陣相乘運算。解碼器的工作恰好相反,是通過一系列類似的矩陣相乘運算,從編碼後的值中重建原始圖像。
編碼器如何知道用什麼矩陣乘以輸入數據?這正是我們要訓練自動編碼器的原因。一旦我們指定了編碼器和解碼器矩陣的維度,自動編碼器會努力找出矩陣的最佳值,從而能以最好的狀況完成任務!
編碼為 4 個值
我使用了一個編碼器將圖像從 12288 個值降採樣,最後為 4 個值。所以,我們編碼的每個 Pokemon 都可以僅用 4 個值表示。所有這 150 個 Pokemon 都可以!真是太棒了對吧?
OK,我們看一下我們的輸入數據:
很好。上面是 100 個 Pokemon 樣本,和我們預料的一樣,背景、攝像角度和 Pokemon 的特徵都變化多端。我把自動編碼器訓練了 250 次後,解碼器輸出了如下結果:
我的天吶,效果不錯,是吧?雖然有些模糊,很多 Pokemon 都能識別出來,要記得我們可是把 12288 個值降採樣到了僅僅 4 個值!
為了可視化自動編碼器的訓練過程,我用每十個時間點的輸出圖像快照製作了一個 GIF 圖:
你可以看到自編碼器學會了逐步去接近最佳結果,直到第 150 個時間點後趨於穩定(如果你眼神兒好的話,會發現是 GIF 圖的第 15 幀)。
但是結果還是可以的!等學到新的機器學習知識後,我哪天說不準會讓神經網路生成新的 Pokemon 呢。
你也可以自己去試試這麼操作。好了,我要去捉小精靈了!
推薦閱讀:
TAG:景略集智 | 深度学习DeepLearning | 人工智能 |