放養的深度學習-淺談自編碼器

放養的深度學習-淺談自編碼器

來自專欄 混沌巡洋艦

說起非監督學習,總逃不過Yann LeCnn的這張圖,他將強化學習比做蛋糕上的櫻桃,將監督學習比做蛋糕的奶油,而將非監督學習比做蛋糕底座。這個比喻不止說明了這三種學習範式的江湖地位。更形象的指出了各自的特點,強化學習得到最多的關注,監督學習好吃但是相對價格更貴(需要人工進行數據標記),而非監督學習雖然潛力巨大,但卻相對來說最默默無聞。

除了不需要人工數據標記這個優點,非監督學習的另一個優點是不會引入人的偏見。舉一個具體的例子,如果要開發一個能夠自動對手機里照片按照內容分類的工具,那麼監督學習的做法就是將圖像進行分類,看看圖片中的主體是人物,動植物,建築,自然風景或是文字,然後按照每張照片的分類將照片放到不同的相冊中。而非監督的方式要做的是將每一張圖片放到一個二維空間中,不是隨便的放,而是要讓內容相近的圖片都湊到一起,最終出現幾個圖片簇,而在每個簇之間的距離要儘可能的大。

如何判斷圖片的語義是否相近了,可以假設同一個時間段拍攝的,在同一個地點拍攝的照片具有相似的內容。一旦訓練好了這樣一個將圖片自動聚類(降維)的模型,那麼你朋友第二天發給你的昨天聚會照片,即使系統顯示的時間不在同一天,也會被歸檔在正確的相冊中。

在深度學習出現之前,聚類已經有了很多種成熟的方法了,從最簡單的K means到不需要設定聚類數的affinity propagation,再到層次化的聚類。然而,這些聚類方法對於非結構化的數據,例如圖片,聲音處理的不好,如果能夠將非結構化數據的維度降低,那就可以使用傳統的聚類方法了。然而,線性的聚類方法,例如PCA或MDS,在圖像上的表現不佳。這裡展示的是使用PCA對MINST數據進行降維的結果。不同的數字並沒有被明顯的區分開。

而使用非監督學習在深度學習中最典型的架構-自編碼器,就可以做到對圖像等非結構數據進行降維。下面展示的是用深度學習對手寫數字進行的降維,不同的數字區分要比上一副圖好的多。

任何深度學習的架構的構建,都是將想要達到的目標翻譯成損失函數的過程,數據降維的目標是讓降維後的數據能夠更好的保持原有數據的區分度,讓原來能分開的數據現在也能分開。但原始的沒有標籤的數據點之間距離都沒有明確的定義,又如何用一個公式來量化降維後數據點之間的區分度。

如果在橫向上無法解決問題,那可以試試在縱向上進行探索。先假設問題已經解決了,我們找到了一種完美的將MINST圖像進行降維的方案,那麼我們能拿這個方案做什麼?假設每個MINST數據集中的圖像有一個唯一的6位ID,越靠前的位置表示對該圖片的越大類的分類。那麼我們完美的降維方案給出的結果將可以100%的預測出圖片的ID。接著假設我們還沒有找到這個完美的降維方案,但已經差的不多了,那麼我們根據降維後預測出的圖像ID應該只在最後幾位有差距。到了這一步,待優化的損失函數已經呼之欲出了,即降維後的特徵生成的圖像和原始的圖像差距有多大。接下來要做的就是先訓練一個神經網路來降維,再訓練一個網路進行升維。

從最基本的自編碼器出發,將損失函數進行改變,讓輸入加入誤差,而待重構的是不帶誤差的原始數據,就可以得到變分自編碼器(VAE)。而在網路結構上,也可以使用卷積網路或循環神經網路。然而不同於深度網路,自編碼器的結構使得網路可以逐層訓練。例如一個堆疊的自編碼器,先將原始的100維數據降低為50維,再降低為10維,最後降低為3維。那麼就可以先訓練一個淺層的100->50->100的自編碼器,訓練好後將網路固定,再使用上次訓練得出的降維數據訓練50->10>50的自編碼器,依次類推,最後將訓練好的編碼器和解碼器按順序堆疊起來。這樣的訓練方式可以避免梯度消失的問題。

不同深度的網路學習率隨著深度增加顯著降低

自編碼器進行數據降維的目地,是為了進行方便聚類。使用Kmeans等演算法,可以對原來的Minst數據進行聚類。在有數據標籤的時候,使用Normalized Mutual Information (NMI),可以來評價聚類的效果,這個數字越大,表示被正確的聚在一起的數字越多。如此,就可以評價使用原始的數據聚類和使用自編碼器降維後的數據聚類的效果。

以下是Keras相關代碼

# this is our input placeholderinput_img = Input(shape=(784,))# "encoded" is the encoded representation of the inputencoded = Dense(500, activation=relu)(input_img)encoded = Dense(500, activation=relu)(encoded)encoded = Dense(2000, activation=relu)(encoded)encoded = Dense(10, activation=sigmoid)(encoded)# "decoded" is the lossy reconstruction of the inputdecoded = Dense(2000, activation=relu)(encoded)decoded = Dense(500, activation=relu)(decoded)decoded = Dense(500, activation=relu)(decoded)decoded = Dense(784)(decoded)# this model maps an input to its reconstructionautoencoder = Model(input_img, decoded)# this model maps an input to its encoded representationencoder = Model(input_img, encoded)autoencoder.compile(optimizer=adam, loss=mse)pred_auto_train = encoder.predict(train_x)pred_auto = encoder.predict(val_x)km.fit(pred_auto_train)pred = km.predict(pred_auto)normalized_mutual_info_score(val_y, pred)

可以看到,使用自編碼器+Kmeans 的方法,其MNI從0.50提升到了0.74,效果很明顯。類似的,使用自編碼器降維後的特徵,也可以結合傳統的機器學習演算法,例如KNN,隨機森林等進行分類任務,你可以訓練多個層數不同自編碼器,有的將原始數據(100維)降低為10維,有的降低為2維,再分別使用降維後的數據進行分類,這可以理解成集成弱分類器,也可以從神經網路的角度理解成殘差網路,即在深度的網路中加入直接連接的短路層。

殘差網路的結構

自編碼器在監督學習中還有另一種應用。還是拿Minst數據分類舉例,已知標籤時,可以對每一個數字訓練一個自編碼器,然後一個待分類的數字來了,分別用在訓練集中訓練好的自編碼器進行重構,根據那個自編碼器的重構誤差大小,使用softmax函數,將不同數字對應的自編碼器的重構誤差轉化為該圖片為那個數字的概率分布。

這樣的分類方式下,假設你拿一張寫著字母A的圖片,那麼這十個用手寫數字訓練出來的自編碼器,就會出現沒有一個重構誤差足夠小的情況,這使得你的模型能夠發現異常點,而傳統的分類模型,你的圖片總會被歸到一類中。再假設現在你在Minst數據集之外,又拿到了一萬張手寫的8的照片,這時你不需要重新訓練模型,只需要重新訓練數字8對應的自編碼器。

假設你在訓練中發現數字8和數字6總是容易區分不開,那你可以根據一個新的圖片在數字6和8中對應的自編碼器中的重構誤差進行人為的調整,比對在經過softmax時放大其中的差異。這使的深度學習不在是一個黑盒,使得研究者可以看到預測過程中發生了什麼。

在模型訓練的過程中,也可以針對原始圖像和生成圖像的距離進行類似Relu函數的截斷。通過更改權重,讓模型在重構誤差小於一定cutoff的情況就不進行優化,而只關注那些重構誤差還相對較大的樣本。這裡的思路就類似Xgboost中將預測結果不好的樣本再放回重新訓練的思路了。

假設現在數字8的樣本數已經是其他數字的100倍了,上述的使用自編碼器的分類模型不會像傳統的分類模型那樣,受到樣本數不均的負面影響。這對於醫療,金融這種正負樣本量差距很大的應用場景,極其有用。同時,這樣的方法進行的預測,更加穩健,不用擔心圖像修改一個像素,模型的預測結果就會改變。

將自編碼器用於圖像生成,可以避免GAN中的模式塌縮問題(只生成黃色的貓)。分別用貓和狗的圖像訓練自編碼器,將原始圖像的降維表示進行微調,就可以用來生成新的貓和狗的照片。由於生成的圖片都在原始圖片降維後的空間附近, 自編碼器生成的照片,不會出現GAN那樣五條腿的貓這種明顯不符合常識的圖片。

使用自編碼器降維,還會有更好玩的應用。還是MINST數據集,將所有6的圖片,分別轉90,180,270度,這樣一張圖片就變成了4張,通過自編碼器降維再進行Kmeans 聚類(K取4),是可以將圖像按照轉動的角度分成4類的。現在拿一張正常的9的圖片交給自編碼器去降維,這個圖片會被分到旋轉180度的那一簇6中,這說明模型可以學到圖片的語義信息,這種在不同事物間進行關聯的能力,是人類推理的基石。

更哲學一些的論述,非監督學習做的是根據現有的數據去預測將來。MInst數據集的例子可以看成是將一個人寫數字的過程拍了下來,假設一個人要花3秒寫數字,自編碼器做的可以看成根據第三秒後的筆跡預測前一秒之前的筆跡,最終能夠達到在一個數字還沒有寫完的時候就預測出這個數字本身是什麼。(空間的降維再升維對應時間上的歷史匹配加預知)

總結一下,這篇小文介紹了自編碼器的原理,訓練方法及在分類和聚類和圖像生成中多種的應用場景及優勢。自編碼器的變種很多,發展很快,代碼相比於CNN,RNN來,實現起來也不難,是一個值得細緻學習的探索深度學習框架,這篇小文要做的只是拋磚引玉。

更多越多

R 語言中的深度學習 Minst數據集下的聚類分析


推薦閱讀:

機器學習演算法實踐—K-Means演算法與圖像分割
機器學習入門:邏輯回歸案例
可視化展示神經網路是如何將分類正確率提升的
[貝葉斯五]之樸素貝葉斯
機器學習概述與演算法介紹

TAG:深度學習DeepLearning | 機器學習 | 神經網路 |