感知器与梯度下降
from:http://www.cnblogs.com/ronny/p/ann_01.html
機(jī)器學(xué)習(xí)算法 原理、實(shí)現(xiàn)與實(shí)踐 —— 感知機(jī)與梯度下降
?
一、前言
1,什么是神經(jīng)網(wǎng)絡(luò)?
人工神經(jīng)網(wǎng)絡(luò)(ANN)又稱神經(jīng)網(wǎng)絡(luò)(NN),它是一種受生物學(xué)啟發(fā)而產(chǎn)生的一種模擬人腦的學(xué)習(xí)系統(tǒng)。它通過(guò)相互連結(jié)的結(jié)點(diǎn)構(gòu)成一個(gè)復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu),每一個(gè)結(jié)點(diǎn)都具有多個(gè)輸入和一個(gè)輸出,并且該結(jié)點(diǎn)與其他結(jié)點(diǎn)以一個(gè)權(quán)重因子相連在一起。通俗來(lái)說(shuō),神經(jīng)網(wǎng)絡(luò)是一種學(xué)習(xí)器,給它一組輸入,它會(huì)得到一組輸出,神經(jīng)網(wǎng)絡(luò)里的結(jié)點(diǎn)相互連結(jié)決定了輸入的數(shù)據(jù)在里面經(jīng)過(guò)怎樣的計(jì)算。我們可以通過(guò)大量的輸入,讓神經(jīng)網(wǎng)絡(luò)調(diào)整它自身的連接情況從而總是能夠得到我們預(yù)期的輸出。
2,神經(jīng)網(wǎng)絡(luò)能干什么嗎?
神經(jīng)網(wǎng)絡(luò)對(duì)于逼近實(shí)數(shù)值、離散值或向量值的目標(biāo)函數(shù)提供了一種健壯性很強(qiáng)的方法,現(xiàn)在已經(jīng)成功應(yīng)用到很多領(lǐng)域,例如視覺(jué)場(chǎng)景分析、手寫字符識(shí)別、語(yǔ)音識(shí)別、人臉識(shí)別等。它可以適用在任何實(shí)例是“屬性-值”Feature→Value的情況中,需要學(xué)習(xí)的目標(biāo)函數(shù)是定義在可以用向量描述的實(shí)例上,向量由預(yù)先定義的特征組成,比如字符識(shí)別,那么特征可以是圖像中的每個(gè)像素亮度值。
現(xiàn)代計(jì)算機(jī)識(shí)別的過(guò)程通常都可以描述為這樣一個(gè)過(guò)程:對(duì)象?→特征→類別,理論上都可以用神經(jīng)網(wǎng)絡(luò)來(lái)解決。
本篇文章將是人工神經(jīng)網(wǎng)絡(luò)這個(gè)主題的第一篇文章,主要從最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)入手,介紹一些基本算法原理。后面會(huì)陸續(xù)涉及到多層神經(jīng)網(wǎng)絡(luò)的原理及其C++實(shí)現(xiàn),同時(shí)隨著深度學(xué)習(xí)的提出,卷積神經(jīng)網(wǎng)絡(luò)也漸漸走進(jìn)人們的視野,它在圖像識(shí)別上表現(xiàn)非常不錯(cuò),這個(gè)主題也將在后面的文章中有全面的介紹。
二、感知器
一個(gè)感知器的結(jié)構(gòu)圖如下:
稍后我們會(huì)知道感知器實(shí)際上是神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)中的一個(gè)神經(jīng)元,那么一個(gè)感知器就夠成了最簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)系統(tǒng)(雖然還算不上是網(wǎng)絡(luò))。感知器是以一組實(shí)數(shù)向量作為輸入,計(jì)算這些輸入的線性組合,如果結(jié)果大于某個(gè)閾值就輸出1,否則就輸出-1。如果我們用公式表達(dá),則假設(shè)輸入為x1到xn,那么感知器可以表示為一個(gè)函數(shù):
o(x)={1?1?if???w0+x1w1+?+xnwn>0?otherwise
我們把?w0看作是上面提到的閾值,w1至wn為一組權(quán)值。o(x)就是將輸入向量按一組權(quán)重進(jìn)行線性加權(quán)求和后做的一個(gè)符號(hào)函數(shù)。
我們可以把感知器看成n維實(shí)例空間(點(diǎn)空間)中的超平面的決策面,平面一側(cè)的所有實(shí)例輸出1,對(duì)另一側(cè)的實(shí)例輸出-1,這個(gè)決策超平面的方程是w???x??=0。
針對(duì)于我們?cè)跀?shù)據(jù)分類的應(yīng)用時(shí),就是將我們提供的所有樣本數(shù)據(jù)分為2類,對(duì)于其中一類樣本,感知器總是輸出1,而另一類總是輸出-1。但是對(duì)于任意樣本總能找出這個(gè)超平面嗎,或者是說(shuō)是找出一組這樣的權(quán)值向量嗎?答案顯然是否定的,只有線性可分的空間可以找到超平面,或者說(shuō)可以找出一組權(quán)值。
那么我們?cè)趺蠢酶兄髂?#xff1f;或者說(shuō)我們的目標(biāo)是什么?
我們希望找到一組這樣的權(quán)值,對(duì)于我們輸入的每一組向量,總是能夠得到一個(gè)我們期望的值。但是上面的感知器功能顯然不夠,它只能得到2個(gè)結(jié)果,即1和-1。
在實(shí)際的模式分類的應(yīng)用中,樣本空間往往并不是線性的,即使是2維數(shù)據(jù)的集合也可能不是線性可分的,比如下面這張圖:
而用這樣的感知器結(jié)點(diǎn)來(lái)構(gòu)建神經(jīng)網(wǎng)絡(luò)顯然是不行的,因?yàn)榫€性單元連結(jié)在一起得到的仍然是線性單元,我們需要的是一種非線性映射,于是就產(chǎn)生了激活函數(shù)這個(gè)概念。激活函數(shù)是一種非線性函數(shù)同時(shí)是可微函數(shù)(可以求導(dǎo)數(shù)),為什么要可微呢,因?yàn)槲覀冃枰罊?quán)重是怎么影響最終輸出的,我們要根據(jù)輸出來(lái)調(diào)節(jié)那些權(quán)重向量,也就是后面講到的梯度下降法則。
激活函數(shù)有很多種,關(guān)于激活函數(shù)的種類這里不準(zhǔn)備介紹太多,只要知道我們選用的是S型激活函數(shù),它將整個(gè)一維空間映射到[0,1]或[-1,1]。下面是S型sigmoid函數(shù)和它的導(dǎo)數(shù):
f(x)=11+e?αx(0<f(x)<1)
f′(x)=αe?αx(1+e?αx)2=αf(x)[1?f(x)]
經(jīng)過(guò)這樣的非線性映射,我們的感知器(現(xiàn)在應(yīng)該叫SIMGOID單元)就變成了下面這種結(jié)構(gòu):
上面結(jié)構(gòu)中w0我們習(xí)慣稱它為偏置,相當(dāng)于我們多了一個(gè)x0=1的輸入。
對(duì)于上面這種結(jié)構(gòu),我們可以有如下結(jié)論:
1)對(duì)于任意一組輸入和一個(gè)我們預(yù)想的在[0,1]之間的輸出,我們總可以找到一組w??使得。
2)對(duì)于很多組這樣的輸入樣本,我們可以通過(guò)不斷的調(diào)整權(quán)值,來(lái)讓它們的輸出接近于我們預(yù)想的輸出。
下面我們?cè)摽紤],如何求得這樣的一組權(quán)值向量。
三、反向傳播算法
我們需要在向量空間中搜索最合適的權(quán)值向量,但是我們不能盲目的搜索,需要有一定的規(guī)則指導(dǎo)我們的搜索,那么梯度下降就是很有用的方法。首先我們來(lái)定義輸出誤差,即對(duì)于任意一組權(quán)值向量,那它得到的輸出和我們預(yù)想的輸出之間的誤差值。
定義誤差的方法很多,不同的誤差計(jì)算方法可以得到不同的權(quán)值更新法則,這里我們先用這樣的定義:
E(w??)=12∑d∈D(td?od)2
上面公式中D代表了所有的輸入實(shí)例,或者說(shuō)是樣本,d代表了一個(gè)樣本實(shí)例,od表示感知器的輸出,td代表我們預(yù)想的輸出。
這樣,我們的目標(biāo)就明確了,就是想找到一組權(quán)值讓這個(gè)誤差的值最小,顯然我們用誤差對(duì)權(quán)值求導(dǎo)將是一個(gè)很好的選擇,導(dǎo)數(shù)的意義是提供了一個(gè)方向,沿著這個(gè)方向改變權(quán)值,將會(huì)讓總的誤差變大,更形象的叫它為梯度。
?E(wi)=?E?w=12?∑d∈D(td?od)2?wi=12∑d∈D?(td?od)2?wi
既然梯度確定了E最陡峭的上升的方向,那么梯度下降的訓(xùn)練法則是:
wi→←wi→+Δwi→,其中Δwi→=?η?E?wi
梯度下降是一種重要最優(yōu)化算法,但在應(yīng)用它的時(shí)候通常會(huì)有兩個(gè)問(wèn)題:
1)有時(shí)收斂過(guò)程可能非常慢;
2)如果誤差曲面上有多個(gè)局極小值,那么不能保證這個(gè)過(guò)程會(huì)找到全局最小值。
為了解決上面的問(wèn)題,實(shí)際中我們應(yīng)用的是梯度下降的一種變體被稱為隨機(jī)梯度下降。上面公式中的誤差是針對(duì)于所有訓(xùn)練樣本而得到的,而隨機(jī)梯度下降的思想是根據(jù)每個(gè)單獨(dú)的訓(xùn)練樣本來(lái)更新權(quán)值,這樣我們上面的梯度公式就變成了:
?E?wi=12?(t?o)2?wi=?(t?o)?o?wi
經(jīng)過(guò)推導(dǎo)后,我們就可以得到最終的權(quán)值更新的公式:
wi=wi+Δwiδ=(t?o)o(1?o)Δwi=ηδxi
有了上面權(quán)重的更新公式后,我們就可以通過(guò)輸入大量的實(shí)例樣本,來(lái)根據(jù)我們預(yù)期的結(jié)果不斷地調(diào)整權(quán)值,從而最終得到一組權(quán)值使得我們的SIGMOID能夠?qū)σ粋€(gè)新的樣本輸入得到正確的或無(wú)限接近的結(jié)果。
四、實(shí)例說(shuō)明
上面我們已經(jīng)介紹了經(jīng)過(guò)基本的感知器,我們構(gòu)造了一種SIGMOID單元,可以對(duì)“輸入向量-值”這種模式的數(shù)據(jù)進(jìn)行目標(biāo)函數(shù)的逼近,但是這畢竟只是單個(gè)神經(jīng)元,它逼近不了太復(fù)雜的映射關(guān)系,我們需要構(gòu)造一個(gè)多層的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)來(lái)解決更一般的學(xué)習(xí)與分類問(wèn)題。
下面我們通過(guò)一個(gè)簡(jiǎn)單的逼近實(shí)例來(lái)說(shuō)明單個(gè)SIMGOID單元的工作原理。
首先,我們假設(shè)我們的輸入是一個(gè)4維的向量x=[x1,x2,x3,x4],其中xi的值為0或者1。為了簡(jiǎn)單其見(jiàn),我們只設(shè)計(jì)了下面4種樣本。
x1=[1,0,0,0]x2=[0,1,0,0]x3=[0,0,1,0]x4=[0,0,0,1]
對(duì)于這4類樣本,我們希望它們得到4種不同的結(jié)果以說(shuō)明它們屬于哪一種,也就是我們的目標(biāo)輸出是一個(gè)標(biāo)號(hào),像下面這樣:
x1→1x2→2x3→3x4→4
上面的樣本只是4種,我們可以讓每一種樣本重復(fù)來(lái)構(gòu)建大量的樣本實(shí)例。比如實(shí)際采集到的樣本可能會(huì)有所浮動(dòng),比如與x1同類的樣本可能采集到的數(shù)據(jù)是這樣的x=[0.993,0.002,0.0012,?0.019],所以我們可以用很小的隨機(jī)數(shù)來(lái)模擬大量的樣本輸入。
因?yàn)槲覀兊腟IMGOID單元輸出值只可能是[0,1],所以我們可以將我們的類別標(biāo)號(hào)歸一化為[1,2,3,4]/4,下面我們用C++來(lái)模擬這一過(guò)程。
1,樣本獲取:
1 void SampleNN::getSamplesData() 2 { 3 const int iterations = 15000; // 15000個(gè)樣本 4 for (int i = 0; i < iterations; i++) 5 { 6 int index = i % 4; 7 vector<double> dvect(4, 0); 8 dvect[index] = 1; 9 for (size_t i = 0; i != dvect.size(); i++) 10 { 11 dvect[i] += (5e-3*rand() / RAND_MAX - 2.5e-3); 12 } 13 inputData.push_back(dvect); 14 } 15 }2,用[0,0.05]之間的隨機(jī)值初始化權(quán)重。
1 void SampleNN::intialWgt() 2 { 3 // 4個(gè)連結(jié)和一個(gè)偏置w0 4 for (int i = 0; i != 5; i++) 5 { 6 weight.push_back(0.05*rand()/RAND_MAX); 7 } 8 }3,向前計(jì)算
1 void SampleNN::cmtForward(const vector<double>& inVect) 2 { 3 double dsum = weight[4];//先把偏置加上 4 for (size_t i = 0; i != inVect.size(); i++) 5 { 6 dsum += (inVect[i] * weight[i]); 7 } 8 actual_output = 1 / (1 + exp(-1*dsum)); 9 }4,更新權(quán)重
1 void SampleNN::updataWgt(const vector<double>& inVect,const double true_output) 2 { 3 double learnRate = 0.05; // 權(quán)重更新參數(shù) 4 for (size_t i = 0; i != weight.size() - 1; i++) 5 { 6 weight[i] += (learnRate*(true_output - actual_output)*actual_output*(1 - actual_output)*inVect[i]); 7 } 8 // w0單獨(dú)計(jì)算 9 weight[4] += (learnRate*(true_output - actual_output)*actual_output*(1 - actual_output)*1); 10 }下面是經(jīng)過(guò)15000次迭代后得到的結(jié)果:
從上面結(jié)果可以看出,輸出的值基本收斂于0.25、0.5、0.75與0.96,說(shuō)明已經(jīng)可以用來(lái)分類的了。
五、結(jié)束語(yǔ)
經(jīng)過(guò)上面的討論,單個(gè)神經(jīng)元的功能及其原理應(yīng)該可以清楚的了解,那么下一步,我們將用這些單個(gè)的神經(jīng)元(SIGMOID單元)相互連結(jié)組成一個(gè)網(wǎng)狀結(jié)構(gòu)形成神經(jīng)網(wǎng)絡(luò),并用來(lái)做更一些有意義的識(shí)別,這些內(nèi)容將在下一篇文章中詳細(xì)描述。
總結(jié)
- 上一篇: ML 06、感知机
- 下一篇: 神经网络:卷积神经网络