#Deep Learning 上一篇主要是講了全鏈接神經網絡,這裏主要講的就是深度學習網絡的一些設計以及一些權值的設置。神經網絡能夠根據模型的層數,模型的複雜度和神經元的多少大體能夠分紅兩類:Shallow Neural Network和Deep Neural Network。比較一下二者:git
Network Name | Time | complexity | theoretical |
---|---|---|---|
Shallow Neural Network | more efficient to train | simple | powerful enough |
Deep Nerual Network | need more time | sophisticated | more meaningful |
###Autoencoder 什麼是權重?在神經網絡的模型裏面權重表明的就是特徵轉換(feature transform)。從編碼方面來講,權重也能夠當作是一種編碼方式,把一個數據編碼成另外一種數據。神經網絡是一層一層的進行的,因此若是是一個好的權重的話,是應該能夠提取出數據的特徵的,也就是information-preserving encoding,一種能夠保留有用信息的編碼。第i層提取了特徵,傳到了i+1層,i+1層在i層的基礎上再提取一些更加複雜的特徵,傳到i+2層。最後每一次均可以提取出特徵來,這樣就能夠最大限度的把數據的特徵保留下來。上面講到的手寫數字識別是能夠把一個數字劃分紅不少個筆畫,反過來,也能夠由特徵轉換回數字。這種可逆的轉換叫作information-preserving,經過神經網絡轉換的特徵最後是能夠轉換回原來的輸入,這也正是pre-train要作到的。因此pre-train要知足的特徵就是要求information-preserving。由於拿到了特徵又能夠用獲得的特徵獲得原輸入,證實獲得的特徵是能夠表明整個數據的,沒有遺漏。github
想要獲得這樣的效果,只須要創建一個三層的神經網絡便可。 這個神經網絡通過權重$$W_{ij}^{1}$$獲得的結果就是encode以後的數據,也就是經過feature transform提取特徵的過程,通過$$W_{ji}^2$$的就是解碼過程,要求輸出層輸出的數據要和原數據差很少接近。整個網絡是$$d - d' - d$$的結構,重點就在重構,輸入層到隱含層是特徵轉換,隱含層到輸出層是重構。這種結構咱們叫autoencode,對應編碼和解碼,整個過程就是在逼近indentity function(恆等函數) 可是這樣好像畫蛇添足,既然輸出都是差很少的爲何要畫蛇添足?對於監督式學習,隱藏層其實就是特徵轉換,乘上一些權值轉換成對應特徵的值。就好像手寫數字識別獲得每個數字的特徵,包含了一些提取出有用的特徵,能夠獲得一些數據具備表明性的信息。對於非監督的學習,也可使用autoencode來作density estimation,密度估計,若是$$g(x) ≈ x$$密度較大,說明能夠提取到的特徵不少,不然就是密度很小。也能夠作outlier detection,異常值的檢測,也就是孤立點,噪音。找出哪些是典型的資料,哪些不是。 對於編碼器,咱們更加關心的實際上是中間的隱藏層,也就是特徵轉換權重$$W_{ij}^{(1)}$$天然對應的error function:$$\sum_{i=1}^d(g_i(x) - x_i)^2$$ 三層的autoencode也叫basic autoencode 由於它是最簡單的了。一般限定$$d' < d$$方便數字的編碼,數據集能夠表示爲$$(x_1, y_1 = x_1) (x_2, y_2 = x_2)(x_3, y_3 = x_3)......$$因此能夠當作是一個非監督式的學習,一個重要的限制條件是$$W_{ij}^{(1)} = W_{ji}^{(2)}$$ 解碼權重等於編碼權重,這起到了regularization的做用。 深度學習中,basic autoencoder的過程也就對應着pre-training的過程,使用這種方法,對無label的原始數據進行編碼和解碼,獲得的編碼權重$$W_{ij}^{(1)}$$就能夠做爲pre-trained的比較不錯的初始化權重,也就是做爲深度學習中層與層之間的初始化權重。 因此,pre-train的訓練過程:首先,autoencoder會對深度學習網絡第一層(即原始輸入)進行編碼和解碼,獲得編碼權重$$W_{ij}^{(1)}$$,做爲網絡第一層到第二層的的初始化權重;而後再對網絡第二層進行編碼和解碼,獲得編碼權重W(1)ij,做爲網絡第二層到第三層的初始化權重,以此類推,直到深度學習網絡中全部層與層之間都獲得初始化權重。值得注意的是,對於l-1層的網絡$${{x_n^{l-1}}}$$,autoencoder中的d˘應與下一層(即l層)的神經元個數相同。 這裏介紹的只是一種最簡單的,還有不少的編碼器,稀疏編碼器,去燥編碼器等等。 ####②regularization 控制模型的複雜度就是使用正則化了。 神經網絡每一層都有不少的權重和神經元,這就致使了模型的複雜度會很大,regularization是必要的。 咱們以前介紹過一些方法: 1.structural decisions。架構能夠設計的簡單點,可是深度學習神經網絡的結構是不可能簡單的,這輩子的不可能。只能是相對來講用dropout減輕一些壓力。2.weight decay or weight elimination regularizers。可使用正則化來減少權值。 3.early stop。不要訓練的這麼準確,差很少差很少就夠了。 下面是一種新的regularization的方式:###Denoising Autoencoder 回顧一下以前的overfit的緣由: 算法
和樣本數量,噪聲大小都有關係,若是數據量是不變的,那麼noise的影響就會很是大。那麼這個時候實現regularization的一個方法就是消除noise的影響。 有一種方法是對數據clean操做,可是這樣費時費力。有一種更加牛逼的作法,就是在數據中添加一些noise再訓練。 這種作法的初衷是想創建一個比較健壯,容錯性高的autoencode。在一個已經訓練好的autoencode中,g(x) ≈ x的,對於已經容錯性很高,比較健壯的autoencode,獲得的輸出是和x很接近的。好比手寫數字識別,一個很規範很正的6輸進去能夠獲得一個6,可是若是原始的圖片是歪歪的6,而後仍是能夠獲得6的話那麼這個自編碼器就是一個健壯的自編碼器了。比較不是每個人寫6都是寫的正正,這就使得這個自編碼器的抗噪能力很強。 因此,最後咱們要訓練的樣本集$$(x_1',y_1 = x_1),(x_2',y_2 = x_2),(x_3',y_3 = x_3)......$$ 其中$$x_n' = x_n + noise$$ 因此使用這種autoencode的目的就是使得加入了有噪音的x均可以獲得純淨的x。不只能從純淨的樣本中編解碼獲得純淨的樣本,還能從混入noise的樣本中編解碼獲得純淨的樣本。這樣獲得的權重初始值更好,由於它具備更好的抗噪聲能力,即健壯性好。實際應用中,denoising autoencoder很是有用,在訓練過程當中,輸入混入人工noise,輸出純淨信號,讓模型自己具備抗噪聲的效果,讓模型健壯性更強,最關鍵的是起到了regularization的做用。這也是以前說的去燥自編碼器。 #linear autoencode 剛剛介紹的自編碼器是非線性的,由於中間的tanh(x)函數就是非線性的。常見的autoencode經常使用於在深度學習中,這裏要介紹的是線性的自編碼器,linear autoencode。對於一個線性的自編碼器,只須要不包括非線性轉換就行了。 因此,就變成$$h_k(x) = \sum_{j = 0}^{d'}W_{jk}^{(2)}\sum_{i = 0}^{d}W_{ij}^{(1)}$$ 這裏有三個限制條件: ①移除bias項,保持維度一致。 ②編碼權重與解碼權重一致:$$W_{ij}^{(1)} = W_{jk}^{(2)} = W_{ij}$$ ③$$d' < d$$ 因爲兩個權重是同樣的,W的維度是dxd',x的維度是dx1,因此整個公式能夠變爲:$$h_k(x) = WW^Tx$$ 可是要求$$h(x) = x$$ 因此error function$$E_{in}(h) = E_{in}(W) = \frac{1}{N}\sum_{n=1}^{N}|x_n - WW^Tx_n|^2 with(dxd')W$$ 對於那個協方差矩陣首先能夠進行特徵值分解$$WW^T = VΓV^T$$其中Γ是一個對角矩陣,V矩陣知足$$VV^T = I_d$$ 而I矩陣有一個很重要的性質,因爲W是dxd'的,d < d’。有I的非零元素的數量是不大於d'的。###證實 對於一個矩陣W(dxd',d < d'),那麼有Rank(W) <= d'。這個結論直接給出,不用證實。假設有兩個矩陣A,B,C = AB,那麼AX = C的解就是B,也就是惟一解,也就是說Rank(A, C) = Rank(A )。證實:對於Rank(A,C)和Rank(A)無非就是兩種狀況,=和>。<是沒有的,Rank(A)是不可能大於Rank(A,C)的。若是是Rank(A) < Rank(A,C),那麼這個增廣矩陣(A,C)變換成初等矩陣以後,最後一行就會出現$$[0,0,0,0,a]$$的狀況,0 != a,天然就是無解了。因此證實了上訴狀況必定是有Rank(A) = Rank(A,C) 而因爲R(C) <= R(A,C),因此R(C) <= R(A),同理,也能夠證實得R(C) <= R(B),而在這裏$$A = W,B = W^T,C = WW^T$$因此,$$rank(WW^T)$$是不大於d'的,由於一個矩陣的秩是不能夠大於它最小的維度的。$$Rand(W) = Rank(W^T) <= d'$$綜上所訴,$$Rank(WW^T) <= d'$$更重要的是,秩就是這個矩陣特徵值的數量,而I矩陣的斜對角線就是WW^T矩陣的特徵值,因此纔有I的非零元素的數量是不大於d'的。bash
回到正文。$$VV^T = I => VIV^T = I $$那麼就能夠推出$$x_n = VIV^Tx_n$$ 網絡
這樣就把表達式轉換成了一個求解V和Γ的方程:$$min_vmax_Γ\frac{1}{N}\sum_{n=1}^{N}|VIV^Tx_n - VΓV^Tx_n|^2 $$提取一下公因式$$min_vmax_Γ\frac{1}{N}\sum_{n=1}^{N}|VV^Tx_n(I - Γ)|^2$$ 因此第一個要解決的就是$$minimum(I - Γ)$$這樣天然是越接近越好了,因此Γ最好就是對角線上有d'個1。 到這裏Γ的最優解已經知道了 最小化問題有點複雜,轉換一下: 當d' = 1的時候,那就只有V的第一行是有用,因此 條件是在作特徵分解的時候獲得的,這裏也要繼承下來。 有條件的天然是拉格朗日乘子法了:$$L(v) = max_v(\sum_{n=1}^{N}v^Tx_nx_n^Tv + λ(v^Tv - 1))$$ 求導得0$$\sum_{n=1}^{N}x_nx_n^Tv = λv$$ 仔細看一下,這個λ其實就是$$x_nx_n^T$$的特徵值 既然d' = 1是這樣了,那麼當d' > 1的時候,就是依次把d'個特徵值求出來就行了,因此這個就是linear autoencoder的過程了。 過程和PCA很類似,大體都是差很少的,可是PCA還須要減去一下平均值,也就是對x輸入數據作去均值化的處理。 linear autoencode和PCA不徹底同樣,至少出發點不是同樣的,linear autoencode是用來pre-train而被髮明的,雖然機器學習不太須要,可是既然引出了非線性的autoencode那順便把linear也探討一下。可是,linear autoencode在公式的推導上是基本一致的,上面的推導其實也是能夠作爲PCA的推導。 #Dimensionality Reduction——Principal Component Analysis 既然講到了降維,那順便把PCA也講了,Deep Learning的部分已經講完。 ####①數據降維 一般咱們獲得的數據有不少的維度,好比一個商店,能夠有名字,年齡,出生日期,性別,成交量等等。而年齡和性別實際上是表示一個東西,兩個表示徹底是多餘的。固然咱們也能夠直接不作處理就使用這些數據來作機器學習。可是這樣會耗費巨大的資源。在這種狀況下天然就須要數據降維了。降維意味着會有數據丟失,丟失是必定會有的,因此只能保證丟失了多少而已。 舉個例子,假如某學籍數據有兩列M和F,其中M列的取值是如何此學生爲男性取值1,爲女性取值0;而F列是學生爲女性取值1,男性取值0。此時若是咱們統計所有學籍數據,會發現對於任何一條記錄來講,當M爲1時F一定爲0,反之當M爲0時F一定爲1。在這種狀況下,咱們將M或F去掉實際上沒有任何信息的損失,由於只要保留一列就能夠徹底還原另外一列。 ####②向量和基 先看一個向量的運算:$$(a_1,a_2,a_3...a_n)^T(b_1,b_2,b_3...b_n)^T = a_1b_1+a_2b_2+a_3b_3...+a_nb_n$$ 這種乘積方式並不能看出有什麼意義,換一種表達方式$$A*B = |A||B|cos(a)$$a爲A和B的夾角。再進一步|B| = 1,那麼就能夠看出來,**當向量B的模爲1,則A與B的內積值等於A向B所在直線投影的矢量長度。**這個結論很重要。 假設有一個點(3,2),那麼在座標系中的表示: 向量(3,2)就從原點發射到(3,2)這個點的有向線段。在x軸上的投影值是3,在y軸上的投影值是2。也就是說咱們其實隱式引入了一個定義:以x軸和y軸上正方向長度爲1的向量爲標準。因此向量(x,y)其實是一種線性組合:$$x(1,0)^T+y(0,1)^T$$而(1,0)和(0,1)就是這個空間裏面的一組基。 **因此,能夠用另一種方法來描述,肯定一組基,而後給出在基所在的各個直線上的投影值,就能夠了。不過通常直接忽略第一步,比較可靠維度就知道了。可是事實上,基並非一個固定的東西,任何一個線性無關的向量均可以成爲一組基。**例如,(1,1)和(-1,1)也能夠成爲一組基。通常來講,咱們但願基的模是1,由於從內積的意義能夠看到,若是基的模是1,那麼就能夠方便的用向量點乘基而直接得到其在新基上的座標了!實際上,對應任何一個向量咱們總能夠找到其同方向上模爲1的向量,只要讓兩個份量分別除以模就行了。 ####③基變換的矩陣表示 仍是拿上面的(3,2)作爲例子,好比咱們如今有兩個基$$(\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}}),(-\frac{1}{\sqrt{2}},\frac{1}{\sqrt{2}})$$ 那麼把(3,2)變爲新的基上的座標,則有因此,通常的,若是咱們有M個N維向量,想將其變換爲由R個N維向量表示的新空間中,那麼首先將R個基按行組成矩陣A,而後將向量按列組成矩陣B,那麼兩矩陣的乘積AB就是變換結果,其中AB的第m列爲A中第m列變換後的結果。 架構
這裏是R是要變換的維度,R是能夠小於N的。 基於以上的理論,兩個矩陣相乘的意義是將右邊矩陣中的每一列列向量變換到左邊矩陣中每一行行向量爲基所表示的空間中去 ####④協方差 上面討論了基已經座標基於基的變換,若是基的數量是小於數據維度的就能夠達到降維的效果了。 可是,問題來了,基是無限多個的,如何選擇基是一個很大的問題。 舉一個例子:問題來了,這5個數據都是2維度的,如今想降到一維,若是咱們必須使用一維來表示這些數據,又但願儘可能保留原始的信息,你要如何選擇?這個問題其實是要在二維平面中選擇一個方向,將全部數據都投影到這個方向所在直線上,用投影值表示原始記錄。這是一個實際的二維降到一維的問題。 一種直觀的見解是:但願投影后的投影值儘量分散。同一個維度數據之間不"擠"在一塊兒,由於擠在一塊兒表達不了數據自己了。而表徵數據之間離散程度,就考慮到了方差。具體作法就是 想辦法讓高維數據左乘一個矩陣,獲得降維後的數據,降維後的數據的方差最大化。在線性代數中學過,一個矩陣能夠當作是不少個列向量,每個向量表明着一個物體的數據。要表達這個矩陣真的須要這麼多數據嗎,顯然不必定,求解一個矩陣的秩R,看看R 的值,在絕大多數狀況下,矩陣都不是滿秩的,說明矩陣中的元素表達客觀世界中的物體有一些是多餘的。 既然是求離散程度,那麼就是方差了,對於每個字段的方差$$Var(a) = \frac{1}{m}\sum_{i=1}^{m}(a_i - u)^2$$若是已經去除了均值那就能夠直接轉換$$Var(a) = \frac{1}{m}\sum_{i=1}^{m}(a_i)^2$$ 對於上面二維降成一維的問題來講,找到那個使得方差最大的方向就能夠了。不過對於更高維,還有一個問題須要解決。考慮三維降到二維問題。與以前相同,首先咱們但願找到一個方向使得投影后方差最大,這樣就完成了第一個方向的選擇,繼而咱們選擇第二個投影方向。可是若是第二次仍是堅持選擇方差最大的方向,那麼確定仍是會和第一個方向相同的,這樣表達的信息頗有可能重合,因此應該要加上一些限制。從直觀上說,讓兩個字段儘量表示更多的原始信息,咱們是不但願它們之間存在(線性)相關性的,由於相關性意味着兩個字段不是徹底獨立,必然存在重複表示的信息。 事實上兩個字段的相關性是能夠用協方差來表示。$$Cov(a,b) = \frac{1}{m}\sum_{i=1}^{m}a_ib_i$$協方差爲0的時候,兩個字段是互相獨立的。協方差爲0因此只能在一個基的正交方向選擇第二個基。將一組N維向量降爲K維(K大於0,小於N),其目標是選擇K個單位(模爲1)正交基,使得原始數據變換到這組基上後,各字段兩兩間協方差爲0,而字段的方差則儘量大(在正交的約束下,取最大的K個方差)。 ####⑤協方差矩陣的優化 協方差矩陣的對角線表明了原來樣本在各個維度上的方差,其餘元素表明了各個維度之間的相關關係。因此咱們須要把協方差對角化,由於咱們須要處理的就是維度中的關係,而不是維度之間的。設Y=PX,則Y爲X對P作基變換後的數據。設Y的協方差矩陣爲D,則有: dom
因此如今明白了,咱們要找的P就是使得能夠對角化C的矩陣,最後按照獲得的對角矩陣從大到小排列,取P的前k行做爲基進行轉換便可。這其實就是求解特徵值的過程。總結:一開始對數據進行降維操做,咱們想到的就是要使得數據投影以後方差最大,那麼就須要尋找一組基使達成這個條件。可是發現若是隻是找最大的方差是會有重複,好比第一個發現的基是最大的,那麼第二個方向確定也差很少是這個方向,這樣信息就有重複,因此又至關數據維度之間是應該有非相關性的,因而就使用到了協方差來表明,可是咱們須要的是數據裏的非相關性最大化,數據間的最大化方差最大已經處理了,因此這個時候協方差只須要關注對角線,天然就是對角化了。又發現對角化其實就是特徵分解的一個過程,最後求出結果。 另外一個方面,W咱們能夠看作是基的組合,WX就是降維以後的數據$$|x - ww^Tx|^2$$就是要求了降維以後的數據要和原來的數據相差不遠,爲何不是X-WX呢?首先這兩個東西不是同緯度的,不可能計算,其次乘上一個轉置其實就是轉換回來的結果了。若是壓縮以後轉換回來的結果和原來差很少,那不就證實了這個降維是OK的嗎?因此這就和Autoencode的思想同樣了,因此上面linear autoencode的過程也能夠看作就是PCA的公式化推導。 ####⑤PCA算法過程: ①將原始數據按列組成n行m列矩陣X ②均值化操做。 ③求協方差 ④求特徵值特徵向量 ⑤排列取前k大的特徵值對應的特徵向量 ⑥降維操做 #Coding ####Autoencode 編碼器有幾個很重要的特徵: ①編碼器是數據相關的,這就意味着只能壓縮那些和訓練數據相關的數據,好比用數字的圖像訓練了而後有跑去壓縮人臉的圖片,這樣效果是不好的。 ②編碼器不管是訓練多少次,都是有損的。 ③自動編碼器是從數據樣本中自動學習的,這意味着很容易對指定類的輸入訓練出一種特定的編碼器,而不須要完成任何新工做 ####Tool 先介紹一下工具類:機器學習
import numpy as np
from keras.datasets import mnist
import matplotlib.pyplot as plt
def get_dataSets():
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32')/255.
x_test = x_test.astype('float32')/255.
x_train = x_train.reshape(len(x_train), np.prod(x_train.shape[1:]))
x_test = x_test.reshape(len(x_test), np.prod(x_test.shape[1:]))
return x_train, x_test
pass
複製代碼
首先是引入數據,mnist.load_data()這個數據導入有點問題,上網百度了一下發現百分之90的博客都是有問題本身下的,因此不例外我也是本身下載了4個壓縮包放在了當前目錄data下面。 獲得數據時候先進行歸一化操做,而後reshape,由於後面一開始用到的是單層的編碼器,用的全鏈接神經網絡,因此應該變成是二維的數據。函數
def show(orignal, x):
n = 10 # how many digits we will display
plt.figure(figsize=(20, 4))
for i in range(n):
ax = plt.subplot(2, n, i + 1)
plt.imshow(orignal[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
ax = plt.subplot(2, n, i + 1 + n)
plt.imshow(x[i].reshape(28, 28))
plt.gray()
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
複製代碼
這個函數用於顯示,傳入的參數是原始圖像和預測的圖像。好像都蠻直觀的。 雖然每一種編碼器都是用了一個類來封裝,可是每個只有應該create方法,返回一個已經訓練好的autoencode,因此下面全部的代碼都是在create裏面。 ####①單層自編碼器 單層自編碼器就是以前說的最簡單的base autoencode。使用Keras實現。 所有都封裝在一個類裏面,用類的create函數返回一個已經訓練好的autoencode。使用的數據集是mnist數據集。工具
def create(self):
x_train, x_test = get_dataSets()
encoding_dim = 32
input_img = Input(shape=(784,))
複製代碼
獲得數據,隱藏層神經元的數量,入口函數。
encoded = Dense(encoding_dim, activation='relu')(input_img)
decoded = Dense(784, activation='sigmoid')(encoded)
複製代碼
編碼層,最後那個小括號裏面(input_img)就是輸入的內容了,解碼層就是從encoded輸入。Dense裏面定義的是當前層的神經元,decoded層輸出了,天然就是784 = 28 x 28個了。
autoencoder = Model(input=input_img, output=decoded)
encoder = Model(input=input_img, output=encoded)
encoded_input = Input(shape=(encoding_dim,))
decoder_layer = autoencoder.layers[-1]
decoder = Model(input=encoded_input, output=decoder_layer(encoded_input))
複製代碼
接下來的這幾個就是獲得完整的模型,使用Keras的Model API來構建。下面的幾個就是encoder獲得編碼層,獲得解碼層。都很直觀。
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train,
epochs=50,
batch_size=128,
shuffle=True,
validation_data=(x_test, x_test))
return autoencoder, encoder, decoder
複製代碼
以後就是模型的編譯,模型的訓練了。 最後的效果:
事實上仍是能夠的,達到了要求。 ####②多層自編碼器 其餘差很少同樣,就是多了幾層。input_img = Input(shape=(784,))
encoded = Dense(128, activation='relu')(input_img)
encoded = Dense(64, activation='relu')(encoded)
encoded = Dense(32, activation='relu')(encoded)
decoded = Dense(64, activation='relu')(encoded)
decoded = Dense(128, activation='relu')(decoded)
decoded = Dense(784, activation='sigmoid')(decoded)
autoencoder = Model(input=input_img, output=decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train,
epochs=1,
batch_size=128,
shuffle=True,
validation_data=(x_test, x_test))
複製代碼
中間那幾層獲得編碼層的那些去掉了。最後看看效果。
損失函數這些就不放了,由於訓練的話是很容易給出的。 ####③稀疏自編碼器 **稀疏自編碼器通常用來學習特徵,以便用於像分類這樣的任務。稀疏正則化的自編碼器必須反映訓練數據集的獨特統計特徵,而不是簡單地充當恆等函數。以這種方式訓練,執行附帶稀疏懲罰的複製任務能夠獲得能學習有用特徵的模型。**使用L1範式懲罰項就行了,可是效果不太好,就不放結果了。encoded = Dense(encoding_dim, activation='relu',
activity_regularizer=regularizers.l1(10e-5))(input_img)
decoded = Dense(784, activation='sigmoid')(encoded)
複製代碼
####④卷積自編碼器 其實就是卷積神經網絡作編碼而已。
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test = np.reshape(x_test, (len(x_test),28, 28, 1))
複製代碼
數據格式要正確,由於是卷積處理了,要按照(個數,長,寬,顏色)排列。
input_img = Input(shape=(28, 28, 1))
x = Convolution2D(16, (3, 3), activation='relu', border_mode='same')(input_img)
x = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', border_mode='same')(x)
x = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', border_mode='same')(x)
encoded = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(8, (3, 3), activation='relu', border_mode='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(8, (3, 3), activation='relu', border_mode='same')(x)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(16, 3, 3, activation='relu')(x)
x = UpSampling2D((2, 2))(x)
decoded = Convolution2D(1, (3, 3), activation='sigmoid', border_mode='same')(x)
複製代碼
encode和decode是兩個對應的東西,反着來而已,因爲是一個圖片一個圖片的進來,因此輸出就是一個。
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train, epochs=20, batch_size=256,
shuffle=True,
validation_data=(x_test, x_test))
return autoencoder
複製代碼
最後就是常規操做了。 這個訓練時間有點長,電腦不行沒辦法。效果:
最後損失到了0.10,仍是很好的。 ####⑤去噪編碼器 這個是在卷積神經網絡的基礎上作的。用帶噪音的數據來訓練。def get_nosing(noise_factor):
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = np.reshape(x_train, (len(x_train), 28, 28, 1))
x_test = np.reshape(x_test, (len(x_test), 28, 28, 1))
noise_factor = noise_factor
x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_train.shape)
x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, size=x_test.shape)
x_train_noisy = np.clip(x_train_noisy, 0., 1.)
x_test_noisy = np.clip(x_test_noisy, 0., 1.)
return x_train, x_train_noisy, x_test, x_test_noisy
pass
複製代碼
時間就是使用高斯分佈來獲得了。
x_train, x_train_noisy, x_test, x_test_noisy = get_nosing(0.5)
input_img = Input(shape=(28, 28, 1))
x = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(input_img)
x = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(x)
encoded = MaxPooling2D((2, 2), border_mode='same')(x)
x = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(encoded)
x = UpSampling2D((2, 2))(x)
x = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(x)
x = UpSampling2D((2, 2))(x)
decoded = Convolution2D(1, 3, 3, activation='sigmoid', border_mode='same')(x)
autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')
autoencoder.fit(x_train_noisy, x_train, shuffle=True,epochs=1, batch_size=128,
validation_data=(x_test_noisy, x_test))
return autoencoder
複製代碼
這裏的網絡有些許不一樣,是由於便於計算罷了。過程是同樣,扔的數據不一樣而已。效果:
####PCA PCA就不用mnist數據集了,畢竟784維降到2維不是很好看,使用iris數據集。 獲取數據那些就不寫了,畢竟蠻簡單的。
class pca(object):
def fit(self, data_features, y):
data_mean = np.mean(data_features, axis=0)
data_features -= data_mean
cov = np.dot(data_features.T, data_features)
eig_vals, eig_vecs = np.linalg.eig(cov)
eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:, i]) for i in range(len(eig_vals))]
a = np.matrix(eig_pairs[0][1]).T
b = np.matrix(eig_pairs[1][1]).T
u = np.hstack((a, b))
data_new = np.dot(data_features, u)
return data_new
def show(self, data_new):
plt.scatter(data_new[:, 0].tolist(), data_new[:, 1].tolist(), c='red')
plt.show()
pass
複製代碼
步驟其實很簡單,均值化求特徵值排序組合向量基對原數據作乘法。
最後降維效果。####最後附上GitHub代碼:github.com/GreenArrow2…