神经网络-全连接层(1)
寫在前面:感謝@夏龍對本文的審閱并提出了寶貴的意見。
接下來聊一聊現(xiàn)在大熱的神經(jīng)網(wǎng)絡(luò)。最近這幾年深度學(xué)習(xí)發(fā)展十分迅速,感覺已經(jīng)占據(jù)了整個機(jī)器學(xué)習(xí)的“半壁江山”。各大會議也是被深度學(xué)習(xí)占據(jù),引領(lǐng)了一波潮流。深度學(xué)習(xí)中目前最火熱的兩大類是卷積神經(jīng)網(wǎng)絡(luò)(CNN)和遞歸神經(jīng)網(wǎng)絡(luò)(RNN),就從這兩個模型開始聊起。當(dāng)然,這兩個模型所涉及到概念內(nèi)容實在太多,要寫的東西也比較多,所以為了能把事情講得更清楚,這里從一些基本概念聊起,大神們不要覺得無聊啊……
今天扯的是全連接層,也是神經(jīng)網(wǎng)絡(luò)中的重要組成部分。關(guān)于神經(jīng)網(wǎng)絡(luò)是怎么發(fā)明出來的這里就不說了。全連接層一般由兩個部分組成,為了后面的公式能夠更加清楚的表述,以下的變量名中上標(biāo)表示所在的層,下標(biāo)表示一個向量或矩陣內(nèi)的行列號:
- 線性部分:主要做線性轉(zhuǎn)換,輸入用X表示,輸出用Z表示
- 非線性部分:那當(dāng)然是做非線性變換了,輸入用線性部分的輸出Z表示,輸出用X表示。
線性部分
線性部分的運(yùn)算方法基本上就是線性加權(quán)求和的感覺,如果對于一個輸入向量,線性部分的輸出向量是,那么線性部分的參數(shù)就可以想象一個m*n的矩陣W,再加上一個偏置項,于是有:
線性部分做了什么事情呢?簡單來說就是對輸入數(shù)據(jù)做不同角度的分析,得出該角度下對整體輸入數(shù)據(jù)的判斷。
這么說有點抽象,舉一個實際點的例子,就拿CNN的入門case——MNIST舉例。MNIST的例子在此不多說了,它是一個手寫數(shù)字的識別項目,輸入是一張28*28的二值圖,輸出是0-9這是個數(shù)字,這里假設(shè)我們采用完全全連接的模型,那么我們的輸入就是28*28=784個像素點。數(shù)據(jù)顯示到屏幕上大概是這個樣子:
對于我們來說,這個像素點都太過于抽象了,我們無法判斷這些像素點的取值和最終識別的關(guān)系:
他們是正相關(guān)還是負(fù)相關(guān)?
很顯然,像素點之間是存在相關(guān)關(guān)系的,這個關(guān)系具體是什么我們后面再說,但存在關(guān)系這件事是板上釘釘?shù)摹K灾唤o每一個像素點一個權(quán)重是解決不了問題的,我們需要多組權(quán)重。
我們可以
1)在第一組權(quán)重中給第一個像素一個正數(shù),第二個也是正數(shù),
2)在第二組權(quán)重中給第一個像素負(fù)數(shù),而第二個還是正數(shù)……
這樣,我們相當(dāng)于從多個角度對輸入數(shù)據(jù)進(jìn)行分析匯總,得到了多個輸出結(jié)果,也就是對數(shù)據(jù)的多種評價。
非線性部分
非線性部分有一些“套路”函數(shù),這里只說下其中的一個經(jīng)典函數(shù)——sigmoid。它的函數(shù)形式如下所示:
圖像如下所示:
這個函數(shù)的輸入正是我們上一步線性部分的輸出z,此時z取值范圍在,經(jīng)過了這個函數(shù)就變成了。
那非線性部分為什么要做這個函數(shù)轉(zhuǎn)換呢?以我的粗淺理解,其中的一個作用就是作數(shù)據(jù)的歸一化。不管前面的線性部分做了怎樣的工作,到了非線性這里,所有的數(shù)值將被限制在一個范圍內(nèi),這樣后面的網(wǎng)絡(luò)層如果要基于前面層的數(shù)據(jù)繼續(xù)計算,這個數(shù)值就相對可控了。不然如果每一層的數(shù)值大小都不一樣,有的范圍在(0,1),有的在(0,10000),做優(yōu)化的時候優(yōu)化步長的設(shè)定就會有麻煩。
另外一個作用,就是打破之前的線性映射關(guān)系。如果全連接層沒有非線性部分,只有線性部分,我們在模型中疊加多層神經(jīng)網(wǎng)絡(luò)是沒有意義的,我們假設(shè)有一個2層全連接神經(jīng)網(wǎng)絡(luò),其中沒有非線性層,那么對于第一層有:
對于第二層有:
兩式合并,有
所以我們只要令?,?,就可以用一層神經(jīng)網(wǎng)絡(luò)表示之前的兩層神經(jīng)網(wǎng)絡(luò)了。所以非線性層的加入,使得多層神經(jīng)網(wǎng)絡(luò)的存在有了意義。
另外還有一個比較有名的非線性函數(shù),叫做雙曲正切函數(shù)。它的函數(shù)形式如下所示:
這個長得很復(fù)雜的函數(shù)的范圍是(-1,1)。可以看出,它的函數(shù)范圍和前面的sigmoid不同,它是有正有負(fù)的,而sigmoid是全為正的。
神經(jīng)網(wǎng)絡(luò)的模樣
實際上對于只有一層且只有一個輸出的神經(jīng)網(wǎng)絡(luò),如果它的非線性部分還使用sigmoid函數(shù),那么它的形式和邏輯斯特回歸(logistic regression)是一樣的。所以可以想象神經(jīng)網(wǎng)絡(luò)模型從概念上來看比邏輯斯特回歸要復(fù)雜。那么它的復(fù)雜的樣子是什么樣呢?下面給出一段全連接層的代碼,開始做實驗:
class FC:def __init__(self, in_num, out_num, lr = 0.01):self._in_num = in_numself._out_num = out_numself.w = np.random.randn(out_num, in_num) * 10self.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)從代碼上看東西并不多嘛,注意到我們會對參數(shù)中的w進(jìn)行隨機(jī)初始化,有時我們會讓老天隨機(jī)一個神經(jīng)網(wǎng)絡(luò)給我們,我們也可以看看隨機(jī)大帝的旨意。
為了方便可視化,這里只做輸入為2,輸出為1的數(shù)據(jù)。好了,先來看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)定睛一看這其實就是一個標(biāo)準(zhǔn)的Logistic Regression。他的圖像如下所示:
經(jīng)過多次隨機(jī)測試,基本上它都是這個形狀,只不過隨著權(quán)重隨機(jī)的數(shù)值變化,這個“臺階”對旋轉(zhuǎn)到不同的方向,但歸根結(jié)底還是一個臺階。
這也說明1層神經(jīng)網(wǎng)絡(luò)是沒有出路的,它本質(zhì)上還是個線性分類器的實力,那么小伙伴還給它加一層吧:
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)這次我們暫時不用隨機(jī)權(quán)重,而是自己設(shè)置了幾個數(shù)值,可以看出,參數(shù)設(shè)置得很用心。兩層全都是正數(shù)……,那么圖像呢?
看上去比之前的臺階“柔軟”了一些,但歸根結(jié)底還是很像一個臺階……好吧,那我們加點負(fù)權(quán)重,讓我們從兩個方面分析輸入數(shù)據(jù):
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)趕緊上圖:
加了負(fù)權(quán)重后,看上去終于不那么像臺階了,這時候2層神經(jīng)網(wǎng)絡(luò)的非線性能力開始顯現(xiàn)出來了。下面把權(quán)重交給隨機(jī)大帝:
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))上圖:
這時候的非線性已經(jīng)非常明顯了,不過似乎還有個小問題,就是函數(shù)似乎是以原點做“中心對稱”劃分的?中心對稱的兩個點必然落入不同類別?非線性的不徹底啊……
既然如此那就繼續(xù)加層:
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))這個圖就有點……
從上面的實驗中可以看出,層數(shù)越高,非線性的“能力”確實越強(qiáng),腦洞開得也越大。
知道了他的厲害,下回我們將詳細(xì)聊下它的求解方法——反向傳播(Back Propagation)。
文章代碼可以在https://github.com/hsmyy/zhihuzhuanlan/blob/master/FCLayer.ipynb?找到
作者:馮超
鏈接:https://zhuanlan.zhihu.com/p/21525237
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
總結(jié)
以上是生活随笔為你收集整理的神经网络-全连接层(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 那些开源库你是怎么知道的?
- 下一篇: github上可供新手阅读和玩耍的jav