寫在前面:感謝@夏龍對本文的審閱並提出了寶貴的意見。 接下來聊一聊現在大熱的神經網路。最近這幾年深度學習發展十分迅速,感覺已經佔據了整個機器學習的“半壁江山”。各大會議也是被深度學習佔據,引領了一波潮流。深度學習中目前最火熱的兩大類是卷積神經網路(CNN)和遞迴神經網路(RNN),就從這兩個模型開始聊起。
當然,這兩個模型所涉及到概念內容實在太多,要寫的東西也比較多,所以為了能把事情講得更清楚,這裡從一些基本概念聊起,大神們不要覺得無聊啊……
今天扯的是全串連層,也是神經網路中的重要組成部分。關於神經網路是怎麼發明出來的這裡就不說了。全串連層一般由兩個部分組成,為了後面的公式能夠更加清楚的表述,以下的變數名中上標表示所在的層,下標表示一個向量或矩陣內的行列號: 線性部分:主要做線性轉換,輸入用X表示,輸出用Z表示
非線性部分:那當然是做非線性變換了,輸入用線性部分的輸出Z表示,輸出用X表示。
線性部分
線性部分的運算方法基本上就是線性加權求和的感覺,如果對於一個輸入向量,線性部分的輸出向量是,那麼線性部分的參數就可以想象一個m*n的矩陣W,再加上一個偏置項,於是有:
線性部分做了什麼事情呢。簡單來說就是對輸入資料做不同角度的分析,得出該角度下對整體輸入資料的判斷。
這麼說有點抽象,舉一個實際點的例子,就拿CNN的入門case——MNIST舉例。MNIST的例子在此不多說了,它是一個手寫數位識別項目,輸入是一張28*28的二值圖,輸出是0-9這是個數字,這裡假設我們採用完全全串連的模型,那麼我們的輸入就是28*28=784個像素點。資料顯示到螢幕上大概是這個樣子:
對於我們來說,這個像素點都太過於抽象了,我們無法判斷這些像素點的取值和最終識別的關係:
他們是正相關還是負相關。
很顯然,像素點之間是存在相關關係的,這個關係具體是什麼我們後面再說,但存在關係這件事是板上DingTalk的。所以只給每一個像素點一個權重是解決不了問題的,我們需要多組權重。
我們可以
1)在第一組權重中給第一個像素一個正數,第二個也是正數,
2)在第二組權重中給第一個像素負數,而第二個還是正數……
這樣,我們相當於從多個角度對輸入資料進行分析匯總,得到了多個輸出結果,也就是對資料的多種評價。 非線性部分
非線性部分有一些“套路”函數,這裡只說下其中的一個經典函數——sigmoid。它的函數形式如下所示:
映像如下所示:
這個函數的輸入正是我們上一步線性部分的輸出z,此時z取值範圍在,經過了這個函數就變成了。
那非線性部分為什麼要做這個函數轉換呢。以我的粗淺理解,其中的一個作用就是作資料的歸一化。不管前面的線性部分做了怎樣的工作,到了非線性這裡,所有的數值將被限制在一個範圍內,這樣後面的網路層如果要基於前面層的資料繼續計算,這個數值就相對可控了。不然如果每一層的數值大小都不一樣,有的範圍在(0,1),有的在(0,10000),做最佳化的時候最佳化步長的設定就會有麻煩。
另外一個作用,就是打破之前的線性映射關係。如果全串連層沒有非線性部分,只有線性部分,我們在模型中疊加多層神經網路是沒有意義的,我們假設有一個2層全串連神經網路,其中沒有非線性層,那麼對於第一層有:
對於第二層有:
兩式合并,有
所以我們只要令 , ,就可以用一層神經網路表示之前的兩層神經網路了。所以非線性層的加入,使得多層神經網路的存在有了意義。
另外還有一個比較有名的非線性函數,叫做雙曲正切函數。它的函數形式如下所示:
這個長得很複雜的函數的範圍是(-1,1)。可以看出,它的函數範圍和前面的sigmoid不同,它是有正有負的,而sigmoid是全為正的。 神經網路的模樣
實際上對於只有一層且只有一個輸出的神經網路,如果它的非線性部分還使用sigmoid函數,那麼它的形式和邏輯斯特迴歸(logistic regression)是一樣的。所以可以想象神經網路模型從概念上來看比邏輯斯特迴歸要複雜。那麼它的複雜的樣子是什麼樣呢。下面給出一段全串連層的代碼,開始做實驗:
class FC: def __init__(self, in_num, out_num, lr = 0.01): self._in_num = in_num self._out_num = out_num self.w = np.random.randn(out_num, in_num) * 10 self.b = np.zeros(out_num) def _sigmoid(self, in_data): return 1 / (1 + np.exp(in_data)) def forward(self, in_data): return self._sigmoid(np.dot(self.w, in_data) + self.b)
從代碼上看東西並不多嘛,注意到我們會對參數中的w進行隨機初始化,有時我們會讓老天隨機一個神經網路給我們,我們也可以看看隨機大帝的旨意。
為了方便可視化,這裡只做輸入為2,輸出為1的資料。好了,先來看1號選手:
x = np.linspace(-10,10,100)y = np.linspace(-10,10,100)X, Y = np.meshgrid(x,y)X_f = X.flatten()Y_f = Y.flatten()data = zip(X_f, Y_f)fc = FC(2, 1)Z1 = np.array([fc.forward(d) for d in data])Z1 = Z1.reshape((100,100))draw3D(X, Y, Z1)
定睛一看這其實就是一個標準的Logistic Regression。他的映像如下所示:
經過多次隨機測試,基本上它都是這個形狀,只不過隨著權重隨機的數值變化,這個“台階”對旋轉到不同的方向,但歸根結底還是一個台階。
這也說明1層神經網路是沒有出路的,它本質上還是個線性分類器的實力,那麼小夥伴還給它加一層吧:
fc = FC(2, 3)fc.w = np.array([[0.4, 0.6],[0.3,0.7],[0.2,0.8]])fc.b = np.array([0.5,0.5,0.5])fc2 = FC(3, 1)fc2.w = np.array([0.3, 0.2, 0.1])fc2.b = np.array([0.5])Z1 = np.array([fc.forward(d) for d in data])Z2 = np.array([fc2.forward(d) for d in Z1])Z2 = Z2.reshape((100,100))draw3D(X, Y, Z2)
這次我們暫時不用隨機權重,而是自己設定了幾個數值,可以看出,參數設定得很用心。兩層全都是正數……,那麼映像呢。
看上去比之前的台階“柔軟”了一些,但歸根結底還是很像一個台階……好吧,那我們加點負權重,讓我們從兩個方面分析輸入資料:
fc = FC(2, 3)fc.w = np.array([[-0.4, 1.6],[-0.3,0.7],[0.2,-0.8]])fc.b = np.array([-0.5,0.5,0.5])fc2 = FC(3, 1)fc2.w = np.array([-3, 2, -1])fc2.b = np.array([0.5])Z1 = np.array([fc.forward(d) for d in data])Z2 = np.array([fc2.forward(d) for d in Z1])Z2 = Z2.reshape((100,100))draw3D(X, Y, Z2)
趕緊上圖:
加了負權重後,看上去終於不那麼像台階了,這時候2層神經網路的非線效能力開始顯現出來了。下面把權重交給隨機大帝:
fc = FC(2, 100)fc2 = FC(100, 1)Z1 = np.array([fc.forward(d) for d in data])Z2 = np.array([fc2.forward(d) for d in Z1])Z2 = Z2.reshape((100,100))draw3D(X, Y, Z2,(75,80))
上圖:
這時候的非線性已經非常明顯了,不過似乎還有個小問題,就是函數似乎是以原點做“中心對稱”劃分的。中心對稱的兩個點必然落入不同類別。非線性不徹底啊……
既然如此那就繼續加層:
fc = FC(2, 10)fc2 = FC(10, 20)fc3 = FC(20, 40)fc4 = FC(40, 80)fc5 = FC(80, 1)Z1 = np.array([fc.forward(d) for d in data])Z2 = np.array([fc2.forward(d) for d in Z1])Z3 = np.array([fc3.forward(d) for d in Z2])Z4 = np.array([fc4.forward(d) for d in Z3])Z5 = np.array([fc5.forward(d) for d in Z4])Z5 = Z5.reshape((100,100))draw3D(X, Y, Z5,(75,80))
這個圖就有點……
從上面的實驗中可以看出,層數越高,非線性“能力”確實越強,腦洞開得也越大。
知道了他的厲害,下回我們將詳細聊下它的求解方法——反向傳播(Back Propagation)。
文章代碼可以在https://github.com/hsmyy/zhihuzhuanlan/blob/master/FCLayer.ipynb 找到
作者:馮超
連結:https://zhuanlan.zhihu.com/p/21525237
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。