本篇目錄
要使用(倒傳遞)類神經網路,R提供一個可以設定「多個隱藏層」的套件,叫做neuralnet。
然而,當使用類神經網路時,有一個議題十分重要,那就是我們究竟該決定「多少隱藏層和節點」?
理論上來說,我們會針對層數和節點數進行調整,看怎麼樣的組合會有最小的MSE(RMSE),這樣的動作叫做tune parameters。
幸好,R提供一個套件caret,可以協助我們達成這樣的目的;否則的話,我們就需要自己撰寫迴圈(loop)和判斷式(if-else),那會是一個十分複雜且龐大的工程。
接下來,會以R內建的iris資料,進行「倒傳遞類神經網路(bpn)」的示範:
倒傳遞類神經網路(Backpropagation Neural Network)
首先,以下是必須安裝的套件:
require(neuralnet) # for neuralnet(), nn model
require(nnet) # for class.ind()
require(caret) # for train(), tune parameters很直觀的,Sepal.Length、Sepal.Width、Petal.Length、Petal.Width會是input nodes,而Species是output node。
然而,由於Species是類別變數(也就是「分類」的問題),類神經網路無法直接處理。
因此這個時候,必須先將Species,轉變成啞變數(dummy variables)的型態。
data <- iris
# 因為Species是類別型態,這邊轉換成三個output nodes,使用的是class.ind函式()
head(class.ind(data$Species))## setosa versicolor virginica
## [1,] 1 0 0
## [2,] 1 0 0
## [3,] 1 0 0
## [4,] 1 0 0
## [5,] 1 0 0
## [6,] 1 0 0
# 並和原始的資料合併在一起,cbind意即column-bind
data <- cbind(data, class.ind(data$Species))
# 原始資料就會變成像這樣
head(data)## Sepal.Length Sepal.Width Petal.Length Petal.Width Species setosa
## 1 5.1 3.5 1.4 0.2 setosa 1
## 2 4.9 3.0 1.4 0.2 setosa 1
## 3 4.7 3.2 1.3 0.2 setosa 1
## 4 4.6 3.1 1.5 0.2 setosa 1
## 5 5.0 3.6 1.4 0.2 setosa 1
## 6 5.4 3.9 1.7 0.4 setosa 1
## versicolor virginica
## 1 0 0
## 2 0 0
## 3 0 0
## 4 0 0
## 5 0 0
## 6 0 0
而在建構formula時,就可以寫成setosa + versicolor + virginica ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width。
formula.bpn <- setosa + versicolor + virginica ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width在訓練bpn模型的時候,使用的是neuralnet()函式:
bpn <- neuralnet(formula = formula.bpn,
data = data,
hidden = c(2), # 一個隱藏層:2個node
learningrate = 0.01, # learning rate
threshold = 0.01, # partial derivatives of the error function, a stopping criteria
stepmax = 5e5 # 最大的ieration數 = 500000(5*10^5)
)
# bpn模型會長得像這樣
plot(bpn)基本上,這就是一個類神經網路的模型。
Tuning Parameters
當使用不同的隱藏層數和節點數,類神經網路的模型表現與可靠度就會改變。
基本上,當遇到需要tuning parameters的問題時,就會需要觀察不同參數組合的MSE(RMSE);當MSE最小的情況發生時,我們就可以視為是最佳的參數組合(optimal parameters)。
在R裡面,caret是十分強大的套件,許多需要tune parameters的問題都可以靠它來解決,而最常用的函式就是train()。
在繼續做下去之前,我們先把原始的資料集,分成80%的train set和20%的test set。
使用的手法十分簡單:可以想像現在手上資料有一百筆,那我們就隨機從裡面開始抽樣,隨機抽出80筆當成train set,剩下20筆當作test set。
以下就是在做上面的動作:
# nrow()是用來擷取資料筆數,乘上0.8後,表示我們的train set裡面要有多少筆資料(data size)
smp.size <- floor(0.8*nrow(data))
# 因為是抽樣,有可能每次抽樣結果都不一樣,因此這裡規定好亂數表,讓每次抽樣的結果一樣
set.seed(131)
# 從原始資料裡面,抽出train set所需要的資料筆數(data size)
train.ind <- sample(seq_len(nrow(data)), smp.size)
# 分成train/test
train <- data[train.ind, ]
test <- data[-train.ind, ]然後我們根據train set,來進行tune parameters。
(註:下面的code實際上會運行比較長的時間,當使用不同的資料集時,有時候可能會跑數天以上,需要特別留意。)
# tune parameters
model <- train(form=formula.bpn, # formula
data=train, # 資料
method="neuralnet", # 類神經網路(bpn)
# 最重要的步驟:觀察不同排列組合(第一層1~4個nodes ; 第二層0~4個nodes)
# 看何種排列組合(多少隱藏層、每層多少個node),會有最小的RMSE
tuneGrid = expand.grid(.layer1=c(1:4), .layer2=c(0:4), .layer3=c(0)),
# 以下的參數設定,和上面的neuralnet內一樣
learningrate = 0.01, # learning rate
threshold = 0.01, # partial derivatives of the error function, a stopping criteria
stepmax = 5e5 # 最大的ieration數 = 500000(5*10^5)
)
# 會告訴你最佳的參數組合是什麼:第一隱藏層1個node,第二隱藏層2個node
model## Neural Network
##
## 120 samples
## 6 predictor
##
## No pre-processing
## Resampling: Bootstrapped (25 reps)
## Summary of sample sizes: 120, 120, 120, 120, 120, 120, ...
## Resampling results across tuning parameters:
##
## layer1 layer2 RMSE Rsquared
## 1 0 0.0007423786102 NaN
## 1 1 0.0008627906589 NaN
## 1 2 0.0004497492057 NaN
## 1 3 0.0012955926880 NaN
## 1 4 0.0008779908980 NaN
## 2 0 0.0023561522438 NaN
## 2 1 0.0010131220240 NaN
## 2 2 0.0012319808812 NaN
## 2 3 0.0011070212302 NaN
## 2 4 0.0025854087553 NaN
## 3 0 0.0029521505138 NaN
## 3 1 0.0013212727090 NaN
## 3 2 0.0022738998893 NaN
## 3 3 0.0024970339119 NaN
## 3 4 0.0025862084190 NaN
## 4 0 0.0043727076353 NaN
## 4 1 0.0033416069792 NaN
## 4 2 0.0026763713112 NaN
## 4 3 0.0039014647634 NaN
## 4 4 0.0031010533131 NaN
##
## Tuning parameter 'layer3' was held constant at a value of 0
## RMSE was used to select the optimal model using the smallest value.
## The final values used for the model were layer1 = 1, layer2 = 2 and
## layer3 = 0.
# 把參數組合和RMSE畫成圖
plot(model)所以我們就以兩層隱藏層(1,2),重新訓練類神經網路模型:
bpn <- neuralnet(formula = formula.bpn,
data = train,
hidden = c(1,2), # 第一隱藏層1個node,第二隱藏層2個nodes
learningrate = 0.01, # learning rate
threshold = 0.01, # partial derivatives of the error function, a stopping criteria
stepmax = 5e5 # 最大的ieration數 = 500000(5*10^5)
)
# 新的bpn模型會長得像這樣
plot(bpn)預測
接下來,就用訓練好的模型(bpn)預測test set:
# 使用bpn模型,輸入test set後進行預測
# 需要注意的是,輸入的test資料只能包含input node的值
# 所以取前四個欄位,丟入模型進行預測
pred <- compute(bpn, test[, 1:4])
# 預測結果
pred$net.result## [,1] [,2] [,3]
## 1 1.002353670303090 -0.002346053287 0.00006561985903
## 4 0.995909611045799 0.004106464230 0.00005623563832
## 7 0.998769810002052 0.001242511071 0.00006040082942
## 9 0.993590817425006 0.006428301422 0.00005285887373
## 12 0.998537175401193 0.001475451020 0.00006006205314
## 17 1.003558078133413 -0.003552041984 0.00006737378904
## 26 0.996825250360559 0.003189623077 0.00005756904652
## 32 1.001110611235725 -0.001101362622 0.00006380964280
## 33 1.003724978509359 -0.003719161427 0.00006761683925
## 37 1.003611055283178 -0.003605088669 0.00006745093750
## 43 0.998562817346030 0.001449775418 0.00006009939446
## 52 -0.002898552817150 1.004225630734 -0.00139828795967
## 53 -0.003337275046354 1.004664928816 -0.00139892685297
## 60 -0.003276458231027 1.004604032174 -0.00139883828792
## 64 -0.003497684611169 1.004825548929 -0.00139916045087
## 69 -0.003558756655593 1.004886701135 -0.00139924938760
## 84 0.000018921705736 -0.001480487252 1.00146571866874
## 85 -0.003556557180506 1.004884498773 -0.00139924618460
## 86 -0.003308366131395 1.004635981956 -0.00139888475409
## 87 -0.003177624109762 1.004505068327 -0.00139869435982
## 95 -0.003301861376372 1.004629468663 -0.00139887528148
## 99 0.087032871023307 0.914176165874 -0.00126732449451
## 104 0.000008354795626 -0.001469906472 1.00146570328058
## 108 0.000006091916939 -0.001467640623 1.00146569998525
## 109 0.000006109641736 -0.001467658371 1.00146570001106
## 112 0.000011161587291 -0.001472716948 1.00146570736800
## 113 0.000010718746343 -0.001472273525 1.00146570672311
## 116 0.000009500870393 -0.001471054051 1.00146570494957
## 126 0.000011867700662 -0.001473423988 1.00146570839628
## 129 0.000005696967317 -0.001467245155 1.00146569941010
# 四捨五入後,變成0/1的狀態
pred.result <- round(pred$net.result)
pred.result## [,1] [,2] [,3]
## 1 1 0 0
## 4 1 0 0
## 7 1 0 0
## 9 1 0 0
## 12 1 0 0
## 17 1 0 0
## 26 1 0 0
## 32 1 0 0
## 33 1 0 0
## 37 1 0 0
## 43 1 0 0
## 52 0 1 0
## 53 0 1 0
## 60 0 1 0
## 64 0 1 0
## 69 0 1 0
## 84 0 0 1
## 85 0 1 0
## 86 0 1 0
## 87 0 1 0
## 95 0 1 0
## 99 0 1 0
## 104 0 0 1
## 108 0 0 1
## 109 0 0 1
## 112 0 0 1
## 113 0 0 1
## 116 0 0 1
## 126 0 0 1
## 129 0 0 1
# 把結果轉成data frame的型態
pred.result <- as.data.frame(pred.result)把預測結果轉回Species的型態:
# 建立一個新欄位,叫做Species
pred.result$Species <- ""
# 把預測結果轉回Species的型態
for(i in 1:nrow(pred.result)){
if(pred.result[i, 1]==1){ pred.result[i, "Species"] <- "setosa"}
if(pred.result[i, 2]==1){ pred.result[i, "Species"] <- "versicolor"}
if(pred.result[i, 3]==1){ pred.result[i, "Species"] <- "virginica"}
}
pred.result## V1 V2 V3 Species
## 1 1 0 0 setosa
## 4 1 0 0 setosa
## 7 1 0 0 setosa
## 9 1 0 0 setosa
## 12 1 0 0 setosa
## 17 1 0 0 setosa
## 26 1 0 0 setosa
## 32 1 0 0 setosa
## 33 1 0 0 setosa
## 37 1 0 0 setosa
## 43 1 0 0 setosa
## 52 0 1 0 versicolor
## 53 0 1 0 versicolor
## 60 0 1 0 versicolor
## 64 0 1 0 versicolor
## 69 0 1 0 versicolor
## 84 0 0 1 virginica
## 85 0 1 0 versicolor
## 86 0 1 0 versicolor
## 87 0 1 0 versicolor
## 95 0 1 0 versicolor
## 99 0 1 0 versicolor
## 104 0 0 1 virginica
## 108 0 0 1 virginica
## 109 0 0 1 virginica
## 112 0 0 1 virginica
## 113 0 0 1 virginica
## 116 0 0 1 virginica
## 126 0 0 1 virginica
## 129 0 0 1 virginica
接下來,看實際值和預測結果的差異:
# 混淆矩陣 (預測率有96.67%)
table(real = test$Species,
predict = pred.result$Species)## predict
## real setosa versicolor virginica
## setosa 11 0 0
## versicolor 0 10 1
## virginica 0 0 8
總結
類神經網路是一個很強大的方法,屬於機器學習的範疇,因此在預測上有很好的效果,可是最大的問題則是難以解釋。
在資工的領域中,人工智慧就是類神經網路的一個分支,屬於深度學習(deep learning)的範疇。
最近世界知名的AlphaGo(Google的人工智慧),其內部結構,就是一個多達十三層隱藏層的類神經網路。
It’s still a long way to go~