標籤:神經網路 機器學習 neural network
序:
本系列是以NeuralNetwork and Deep Learning書為基礎,加上自己的見解寫得,第一次寫系列,不好之處,請指出哦!接下來我們會先對神經網路有一個介紹,好讓大家明白神經網路是一個什麼東西。為了更好的進行學習,在後面會以識別數字為引導,讓我們循序漸進學習吧!
先說些有的沒的吧!有時候你會不會覺得人的視覺系統在這個世界上,是多麼偉大的傑作,請看下面的圖:
當我們看到這些數位時候,我們馬上便可以知道這些數字是什麼,為什麼我們可以這麼快的就能夠瞭解呢,難道我們天生就能識別數字嗎?我想答案是no。我們大腦的神經網路是一個非常複雜的系統(拜託,這可是用了幾十億年進化得來的產物呐!),在這樣偉大神奇的系統的協助下,我們得以很快的識別上面的數字。接下來,我們遇到的問題是,如何讓電腦來識別這些數字。我們不是一直提倡數字化,資訊化嗎?識別這些數位功效我想大家都能想到!那麼,如何做呢?也許你會說,上面的數字比較簡單啦,不就幾張圖而已嘛!那麼我會說,同學,請看下面的圖:
驚倒了吧!這麼多,有時候,其實有一些數字寫得比較草的時候,人也不是馬上可以識別這些數位,不過我們暫時忽略連人都不能識別的數字吧!
那麼,我們該如何開始呢!嘿嘿,我們的主角—神經網路登場啦!我想大家一定曾經或多或少的聽過一些關於神經網路的介紹。但我們在簡單介紹一下吧!首先,神經網路是機器學習中一個手段啦,機器學習嘛,瞭解一點的人知道,就是輸入資料,訓練下,得出一個網狀圖,然後輸入資料就會給出輸出了。像我們小時候,老師告訴我們這個字母是A,B,C…然後,我們漸漸的懂得了這些字母,當再給我們一些字母的時候,我們就會明白這些字母的含義。
Perceptrons:
什麼是神經網路,讓我們先來介紹一下什麼是Perceptrons,是一種人工神經元(嗯哼,翻譯的好挫有沒有,見諒下哈,如果有更好的翻譯請告訴我)。Perceptrons是1950s和1960s,由研究人員 Warren McCulloch 和 Walter Pitts提出,被Frank Rosenblatt發展。而今天,有更多的神經元被提出,比如sigmoid神經元(我們後面會有介紹),這些神經元在很多模型中已經相當普遍了。總之就是很火啦,不懂的話就會顯得out了啦,所以要懂點了啦!而Perceptrons是一個比較基礎的,所以我們從基礎介紹起嘛!
好了,廢話太多了,進入正題,我想你應該大致學過點生物學,對於神經細胞的工作方式有一點瞭解,神經元之間傳遞訊號的方式就是前面的神經元向後面的神經元釋放一些訊號,後面的神經元處理下,再傳遞給下一個,我說的好像太簡單了,讓我們看看我們的人工神經元的工作方式。Perceptrons是如何工作的呢?
Perceptrons能夠處理一些二進位的輸入,然後給你一個單一的二進位輸出。
還是用圖片說話比較好,看得比較清楚了吧,x1,x2和x3輸入,然後得出一個輸出。那麼輸出如何得到呢?這個人Rosenblatt 提出了一個簡單的規則去計算輸出。他給每一個輸入都給一個權重,w1,w2,…,權重可以用來表示輸入的重要性,(其實直白點,就是,嗯哼,這個輸入不錯,給它定個0.8吧,誒喲,這個也不錯,定個0.7吧,下個次點,定個0.1吧),這些值會對輸出結果產生影響,權重越大,對結果的影響越大(女:“我和你媽掉進水裡,你救哪個?” 男:“那得看你們的權重” 開個玩笑啦,嘿嘿)。那麼輸出是如何得到的呢?可以這樣得到,設定一個值threshhold,然後計算∑jwjxj,如果結果比設定值大,輸出1;否則輸出0。
公式表達的應該挺清楚的了。接下來,讓我們用一個不錯的模型來看看,這個神經元怎麼用。
假設有一個露天演唱會,你其實內心還是比較想去的,可是有一些因素你需要考率下,比如:1那天的天氣怎麼樣? 2你的女朋友或者男朋友是否願意陪你去? 3那個門票費用是多少?
讓我們分別用x1,x2,x3來進行表示,x1=1表示天氣好,x1=0表示天氣糟糕;x2=1,表示你的異性朋友(同性也可以的)願意陪你去,x2=0表示不願意;x3=1表示門票費用低,x3=0表示門票費用高。
好了,定完輸入的意義,下面就是你自己對各個因素的重視程度來設定了。比如你對天氣很看重,你可以設定w1=6,你對第二和第三個輸入不太看重,那麼w2=2和w3=3,如上面說的,權重就是你對這些輸入的重視程度,越大表示越重視。最後,我們需要設定一個threshhold,可以設定為5,但這個比較均衡設定,你也可以設定為3,表示你很希望參加這個演唱會。最終的輸出的意思就是1表示去,0表示不去。好了,我們用Perceptrons描述了參加演唱會這個活動。
看下面的一幅圖:
和上面我們描述的是不是有一些不太一樣,中間多了一些神經元,其實,比較複雜的神經網路就是層次比較多,我們把最左邊的叫做輸入層,中間的叫做隱含層,最右邊的叫做輸出層。後面我們會見到更多的複雜的神經網路.
剛剛上面的輸出函數中有一個threshhold值,我們在這裡做一個稍微的修改,編程下面的。
和公式(1)對比一下我們看到,就是把threshhold移到左邊了,這裡的b=-threshhold,你可以稱為bias(不會翻譯還是省省好了,大家記住英文,更原味點)。
看到這裡,你會不會覺得上面的神經元有點死板誒,值還要自己設定,多麻煩啊,神經元應該自己可以設定啊,嗯哼,有這個想法就對了,神經網路就是應該自己更新。下面我們來看一看另一個神經元,這個會自己更新的哦!
Sigmoid neurons:
假定我們需要一個能夠自己進行學習的神經元,上面的顯然不能夠達到我們的要求嘛,那麼我們該怎麼辦呢?比如我們的輸入是一個掃描的映像矩陣,並且上面都是人寫的數字呢?我們遇到這樣的情況該怎麼辦呢?
看一下下面的圖:
改圖想要表達的意思是,如果在各輸入權重或者bias有一點改變,這些改變導致輸出結果output改變了一點,那麼我們可以利用這些資訊對權重和bias進行修改,讓網路變得更符合我們想要的。假設我們的神經網路模型誤把“8”讀成了“9”,對weight和bias進行修改,讓它能夠正確的讀數字。
但是如果輸出只是0和1的話,那麼我們做的一點改變或許並不會對結果產生多大的影響,就是說比較難讓結果從0跳變成1,即使我們修改了神經網路模型,讓它能夠正確的讀“9”了,也許中間改變的weights和bias是巨大的,這樣的話,對於其它的數字,可能會遇上相同的問題,導致最後模型變來變去,而且每次變化都不小。也許你覺得不麻煩是不是,可是聰明的你,請仔細想想,如果做這些改變本身就需要消耗時間和資源,那麼巨大的改變是不是相當消耗資源和時間的事,我們還是不要這樣折騰電腦了吧,因為我們可以用更好的模型來進行表示。
回到這個圖,我們做一些改變吧,同樣是應對一些輸入,我們得到一個輸出,但是這次我們的輸出不再是0和1這麼簡單了,我們讓輸出介於0和1之間的任意值,我們引進一個函數, σ(w?x+b)這個引進是什麼呢,我們把σ看成是一個sigmoid 函數,這個函數的定義如下:
更確切的說,我們對於輸入X1,X2…,,和w1,w2,…,和b,輸出是:
也許,你會說一句,我去,這個函數是幹嘛的,sigmoid函數其實主要的功能,在我看來,是一種將一個在- ∞ 至 + ∞之間的函數轉換為(0,1)區間的函數。並且性質單調的,就是當z越大,則σ(z)越大,反之越小。例如,當z趨近於+∞時,σ(z)趨近於1;當z趨近於- ∞時,σ(z)趨近於0。若還是不清楚可以看σ(z)的形狀。
現在有了sigmoid函數,我們可以對w和b進行細微的變動,而這些小變動一般會導致output的變化(想想現在函數已經連續了)。用Δoutput來表示output的變化,用Δwj表示在weights的變化,Δb表示在bias的變化,根據微積分,有一個公式
?output/?wj 和 ?output/?b 是偏導數,如果對偏導數不是太瞭解,不用緊張,記住以下這裡表達了,Δoutput是由Δwj和Δb變化導致的。其實翻翻微積分的一些書,這裡的東東都能夠看懂的,因為微積分是很多東西的基礎嘛,還是要好好學滴,我們還是假定大家有對高數的瞭解,所以後面有關數學方面的東東就不再扯太多了。
現在我們的輸出已經是(0,1)區間內的一個實數了,不再是簡單的0或1了。在原來的時候,我們判斷一個數位影像是否是“9”,輸出的是0表示不是“9”,“1”表示是“9”,現在可以設定一個值,比如0.5,當輸出>0.5,判斷是“9”;反之相反。講了重要的sigmoid neuron了,下面就要開始設計神經網路了。
神經網路的結構
下面我們開始介紹神經網路,並且以數字識別舉例。(準備好咯,比較好玩的東西來咯!)
先看下面的這幅圖:
上面我們介紹過,最左邊的是輸入層,裡面是輸入神經元;最右邊是輸出層,裡面是輸出神經元;中間的是隱含層。當然,我們可以有很多中間隱含層。看:
輸入層和輸出層的設計是比較直接的,例如,我們想要判定一個手寫字元是否是“9”,我們就將改圖作為輸入,圖片一般可以轉換為灰階矩陣,用灰階矩陣作為輸入處理更方便些。少點其它的判斷。當然針對一些其它的判斷,有時候還是用原圖比較好。這些東西都需要具體情況具體分析。假設圖片是64 by 64 的圖片,可以有4,096=64×64個輸入神經元,輸出可以就是一個,就想前面說過的,輸出少於0.5判斷不是“9”,大於等於“0.5”判斷是。
中介層設計方式除了像上面比較直接的方式外,其實還有很多其它方法可以對中介層進行設計,一些啟發學習法方法可以用來權衡中介層數和訓練時間,這裡不再仔細詳述。
直至現在,我們討論的神經網路,都是前一層的結果作為下一層的輸入這種方式存在,這種網路我們稱為前饋網路(feedforward neural networks),這樣的網路不會有環的存在。還有一些網路,比如迴歸神經網路(recurrent neural networks),這樣的結構內部可能存在環,感興趣的可以去差一些資料(資料連結)。
一個簡單是識別手寫數位神經網路
現在我們進行一個還不錯的課題,手寫數位識別,這是一個已經被研究得很成熟的方向,識別率已經非常高的了。
看上面的圖,我們一般把手寫數位識別分成兩部分,一部分是數位分割,再一部分就是數位識別了。關於第一部分,有很多有效方式可以用來分割。與其研究第一個問題,不如把重點放在更困難,更有意思的第二部分。
下面可能是我們會用到的神經網路的結構圖。
一般我們的輸入資料是28×28的像素圖,所以我們用784=28×28 neurons作為輸入層,每一個輸入是灰階矩陣值,介於(0,1)之間,越小顏色越淡,反之越深。
第二層是隱含層,有15個神經元,這些值是可以自己設定試試設定多少精度最高的。
最後一層是輸出層,有10個神經元,每個輸出0或1,為什麼不是4個,(2^4=16,所以若按照二進位編碼,4個輸出神經元就ok了),這個問題可以作為一個有意思的思考題,不瞭解的可以在評論裡面留個言,比如郵箱,我可以發給你答案。當然最好自己先思考下哈!
現在假設我們已經有了訓練資料。用x表示輸入,每一個輸入資料是一個28×28=784-維的向量,在向量中的每一個值代表灰階值。我們用y=y(x)表示預期的輸出。y是一個10維的向量,如果對於一個輸入資料x,它對應的是一個6,那麼我們的y=(0,0,0,0,0,0,1,0,0,0)T;
接下來看下面的一個函數:
w表示神經網路中所有的權重,b表示所有的bias,a是神經網路中對應x的輸出, y(x)是預期的輸出。所以輸出a依賴於w,b,x。那麼C(w,b)表示的是什麼呢?就是神經網路的輸出和對應資料預計輸出的差的平方和,為什麼要用平方和呢?其實當然,這裡的定義都是人定的,你要是覺得不爽,用其他的衡量也是ok的,不過這裡用平方和還是比較好滴。想想,現在會怎麼樣,C(w,b)越大,表示我們設計的神經網路輸出和實際輸出差距越大,C的值越小,則差距越小。“那麼我們的目標是什麼呢?”“沒有誤差(蛀牙!嘿嘿)”,只要C(w,b)近於0,那麼我們建立的神經網路結構就是一個優秀的模型。
好了,現在問題就歸結為如何把C(w,b)變得小點。而這個就是Gradient Descent該做的事情了。
Gradient Descent:
接觸過機器學習的人,對於GradientDescent一定不會陌生的吧。如果你覺得對這個演算法已經沒有問題了,那麼可以跳過這段了,下面的介紹主要參考這裡(LeftNotEasy的介紹文章),不過請大家注意一下,裡面的任何公式,只是限於這個Gradient Descent內部介紹用的,後面我們使用Gradient Descent方法時,用的參數名字不一定相同,但是在後面我會標註一下。(主要是單獨寫一個關於Gradient介紹的內容比較麻煩,偷懶下,借鑒一下,而且這篇寫得很好)
Gradient Descent 在神經網路中的運用:
其實我們使用GradientDescent的目的就是找到w和b,根據Gradient Descent方法,我們得出下面的遞推規則。
這裡的η就是上面GradientDescent中的步長,根據這個規則我們不斷更新w和b,最終趨向於使C最小。附加下面的圖有利於空間想象一下。
這樣,我們就把Gradient Descent加進神經網路結構中。並且根據上面的推斷規則,我們可以不斷讓結構中的w和b值更加準確,最終達到一個不錯的效果。
stochastic gradient descent:
現在我們雖然可以進行遞推了,不過,你會發現,有一個很大的問題沒有解決。就是如果訓練資料非常多,我們對每個訓練資料都要進行一次Gradient Descent,顯然會消耗大量的時間,學習的速度回非常非常慢。
為了克服這個問題,可以用stochasticgradient descent方法。隨機地從訓練資料中挑選一部分資料,如m個,進行標記X1,X2,…Xm,用這一小撮來表示大資料。
?Cx表示表示對於某個訓練資料X的C(w,b),上面可以看到,用m個來表示n個。
同時,我們可以對w和b的更新方式,進一步改進:
當然,這裡要不要m,還是你說了算,可以自己根據實際訓練情況,確定最佳的步長。一般最佳的步長都是通過大量的測試得出來的一個依據。
好了,大致的介紹內容就是這些了!
實現:
看了這麼多,如果你想要動手實踐一下,ok,鼓勵啊,資料可以在 MNIST下載,裡面的資料都是收集到的專門用來訓練的資料。
當然,針對上面所說的, Michael Nielsen 也有一個實現,在他的github上(連結),python實現,因為程式需要裡面需要安裝numpy,scikit-learn,scipy,三個python庫,如果你是windows 64位,我在網上沒有找到官方的scipy windows 64位的,不過在這裡找到了http://blog.csdn.net/zhonghuan1992/article/details/32912557,當然,這裡有很多python的包,上面三個都有,雖然是非官方的,但是還是挺健康的。
神經網路的初識