本篇博客將會介紹R中的一個神經網絡算法包:Neuralnet,通過模擬一組數據,展現其在R中是如何使用,以及如何訓練和預測。在介紹Neuranet之前,我們先簡單介紹一下神經網絡算法。
人工神經網絡(ANN),簡稱神經網絡,是一種模仿生物神經網絡的結構和功能的數學模型或計算模型。神經網絡由大量的人工神經元聯結進行計算。大多數情況下人工神經網絡能在外界信息的基礎上改變內部結構,是一種自適應系統。現代神經網絡是一種非線性統計性數據建模工具,常用來對輸入和輸出間復雜的關系進行建模,或用來探索數據的模式。
人工神經網絡從以下四個方面去模擬人的智能行為:
物理結構:人工神經元將模擬生物神經元的功能
計算模擬:人腦的神經元有局部計算和存儲的功能,通過連接構成一個系統。人工神經網絡中也有大量有局部處理能力的神經元,也能夠將信息進行大規模並行處理
存儲與操作:人腦和人工神經網絡都是通過神經元的連接強度來實現記憶存儲功能,同時為概括、類比、推廣提供有力的支持
訓練:同人腦一樣,人工神經網絡將根據自己的結構特性,使用不同的訓練、學習過程,自動從實踐中獲得相關知識
神經網絡是一種運算模型,由大量的節點(或稱“神經元”,或“單元”)和之間相互聯接構成。每個節點代表一種特定的輸出函數,稱為激勵函數。每兩個節點間的連接都代表一個對於通過該連接信號的加權值,稱之為權重,這相當於人工神經網絡的記憶。網絡的輸出則依網絡的連接方式,權重值和激勵函數的不同而不同。而網絡自身通常都是對自然界某種算法或者函數的逼近,也可能是對一種邏輯策略的表達。
一. 感知器
感知器相當於神經網絡的一個單層,由一個線性組合器和一個二值閾值原件構成:構成ANN系統的單層感知器:
感知器以一個實數值向量作為輸入,計算這些輸入的線性組合,如果結果大於某個閾值,就輸出1,否則輸出‐1。
感知器函數可寫為:sign(w*x)有時可加入偏置b,寫為sign(w*x+b)
學習一個感知器意味着選擇權w0,…,wn的值。所以感知器學習要考慮的候選假設空間H就是所有可能的實數值權向量的集合
算法訓練步驟:
1、定義變量與參數x(輸入向量),w(權值向量),b(偏置),y(實際輸出),d(期望輸出),a(學習率參數)
2、初始化,n=0,w=0
3、輸入訓練樣本,對每個訓練樣本指定其期望輸出:A類記為1,B類記為-1
4、計算實際輸出y=sign(w*x+b)
5、更新權值向量w(n+1)=w(n)+a[d-y(n)]*x(n),0
6、判斷,若滿足收斂條件,算法結束,否則返回3
注意,其中學習率a為了權值的穩定性不應過大,為了體現誤差對權值的修正不應過小,說到底,這是個經驗問題。
從前面的敘述來看,感知器對於線性可分的例子是一定收斂的,對於不可分問題,它沒法實現正確分類。這里與我們前面講到的支持向量機的想法十分的相近,只是確定分類直線的辦法有所不同。可以這么說,對於線性可分的例子,支持向量機找到了“最優的”那條分類直線,而單層感知器找到了一條可行的直線。
我們以鳶尾花數據集(iris)為例(截取前十行,共150行數據):
ID Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 5.0 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
由於單層感知器是一個二分類器,所以我們將鳶尾花數據也分為兩類,“setosa”與“versicolor”(將后兩類均看做第2類),那么數據按照特征:花瓣長度與寬度做分類。
運行下面的代碼:
#感知器訓練代碼:
1 a<-0.2 2 w<-rep(0,3) 3 iris1<-t(as.matrix(iris[,3:4])) 4 d<-c(rep(0,50),rep(1,100)) 5 e<-rep(0,150) 6 p<-rbind(rep(1,150),iris1) 7 max<-100000 8 eps<-rep(0,100000) 9 i<-0 10 repeat{ 11 v<-w%*%p; 12 y<-ifelse(sign(v)>=0,1,0); 13 e<-d-y; 14 eps[i+1]<-sum(abs(e))/length(e) 15 if(eps[i+1]<0.01){ 16 print("finish:"); 17 print(w); 18 break; 19 } 20 w<-w+a*(d-y)%*%t(p); 21 i<-i+1; 22 if(i>max){ 23 print("max time loop"); 24 print(eps[i]) 25 print(y); 26 break; 27 } 28 }
#繪圖代碼:
1 plot(Petal.Length~Petal.Width,xlim=c(0,3),ylim=c(0,8), 2 data=iris[iris$Species=="virginica",]) 3 data1<-iris[iris$Species=="versicolor",] 4 points(data1$Petal.Width,data1$Petal.Length,col=2) 5 data2<-iris[iris$Species=="setosa",] 6 points(data2$Petal.Width,data2$Petal.Length,col=3) 7 x<-seq(0,3,0.01) 8 y<-x*(-w[2]/w[3])-w[1]/w[3] 9 lines(x,y,col=4)
二. R中的神經網絡算法包——Neuralnet
本次學習將會通過Neuralnet輸出如下的神經網絡拓撲圖。我們將會模擬一組很簡單的數據實現輸入和輸出,其中,輸出的變量是獨立分布的隨機數,輸入的變量則是輸出變量的平方。本次試驗中,將會訓練10個隱藏神經元。
而輸入和輸出,包括神經網絡的預測數據如下:
Input Expected Output Neural Net Output
1 1 0.9623402772
4 2 2.0083461217
9 3 2.9958221776
16 4 4.0009548085
25 5 5.0028838579
36 6 5.9975810435
49 7 6.9968278722
64 8 8.0070028670
81 9 9.0019220736
100 10 9.9222007864
訓練代碼如下:
1 # 安裝並導入neuralnet包(還需要安裝grid和MASS兩個依賴包) 2 install.packages('neuralnet') 3 library("neuralnet") 4 5 # 構造50個獨立分布在0到100之間的隨機數 6 # 然后將他們保存成數據框架(data.frame) 7 8 traininginput <- as.data.frame(runif(50, min=0, max=100)) 9 trainingoutput <- sqrt(traininginput) 10 11 # 通過cbind函數將輸入和輸出向量構造成一個數據 12 # 用一些訓練數據測試該神經網絡 13 trainingdata <- cbind(traininginput,trainingoutput) 14 colnames(trainingdata) <- c("Input","Output") 15 16 # 訓練10個隱藏神經元的神經網絡 17 net.sqrt <- neuralnet(Output~Input,trainingdata, hidden=10, threshold=0.01) 18 print(net.sqrt) 19 20 # 繪制神經網絡拓撲圖 21 plot(net.sqrt) 22 23 testdata <- as.data.frame((1:10)^2)
24 net.results <- compute(net.sqrt, testdata)
25 26 ls(net.results) 27 28 # 查看結果 29 print(net.results$net.result) 30 31 # 讓結果更直觀些 32 cleanoutput <- cbind(testdata,sqrt(testdata), 33 as.data.frame(net.results$net.result)) 34 colnames(cleanoutput) <- c("Input","Expected Output","Neural Net Output") 35 print(cleanoutput)