神經網路於 R 中可以透過套件 nnet 來實作,可以用來建構與擬和隱藏層 (Hidden Layers)。
packageName <- c("nnet")
for(i in 1:length(packageName)) {
if(!(packageName[i] %in% rownames(installed.packages()))) {
install.packages(packageName[i])
}
}
lapply(packageName, require, character.only = TRUE)
## Loading required package: nnet
## [[1]]
## [1] TRUE
使用內建的 iris 資料集。iris 以鳶尾花的特徵作為資料來源,共含有 150 筆資料,分成 3 類,每類各 50 筆資料,每筆資料各有 4 個特徵。
類神經網路訓練的規律在樣本中,樣本需要足夠代表性,也需要注意樣本的均衡性及多樣性,盡量讓不同類的樣本數量大致相等為佳。本例中便是針對不同類別分別提取相同數量的樣本。其次透過函式 class.ind 處理分類標籤,回傳一分類向量,以 1,0 代表是否屬於該類別,似 one-hot encoding。
data(iris3)
set.seed(123)
Iris <- rbind(iris3[,,1],iris3[,,2],iris3[,,3])
class_encoding <- class.ind(c(rep("s",50), rep("c",50), rep("v",50)))
head(class_encoding, 5)
## c s v
## [1,] 0 1 0
## [2,] 0 1 0
## [3,] 0 1 0
## [4,] 0 1 0
## [5,] 0 1 0
training_idx <- c(sample(1:50,25), sample(51:100,25), sample(101:150,25))
training_data.label <- class_encoding[training_idx, ]
training_data <- Iris[training_idx,]
testing_data <- Iris[-training_idx,]
# the prototype of nnet
# x: 特徵矩陣
# y: 分類矩陣
# formula: 擬合公式,如 Class(輸出類別) ~ x1(屬性1) + x2(屬性2) + x3(屬性3) + ... 等
# data: 含有特徵與分類的資料框
# weights: 分類類別權重
# subset: 指定用來訓練的樣本
# na.action: 對缺失值的處理,如 na.pass, na.omit 等
# size: 隱藏層的神經元個數
# mask: 邏輯向量,用來表示那些參數需要被考慮用來建網路(默認為所有)
# linout: 線性輸出單元的開關,預設為 logistic 輸出函式
# entropy: 是否符合最大條件似然估計,預設為最小平方法(least-squares)
# softmax: 符合對數線型模型(log-linear model)或最大條件似然估計的開關,而 linout, entropy, softmax 與 censored 為互斥
# censored: softmax 的變種,產生出的結果表示所有可能的分類。舉例若 softmax 分類結果為 (0,1,1) 表示分類結果為第 2 `及`第 3 類,而若 censored 分類結果為 (0,1,1) 表示分類結果為第 2 `或`第 3 類
# skip: 在輸入或輸出之間是否設置跳層連接
# rang: 初始的隨機權重值定義範圍,及 [-rang, rang]
# decay: 權重參數的衰減率,預設為 0
# maxit: 最大反覆計算數值,預設為 100
# Hess: 若為真,則回傳最佳權值的 Hess Matrix
# trace: 列出每次優化過程
# MaxNWs: 設定最大權值,值越大擬合會越耗時
# abstol: 擬合終止條件,低於 abstol,表示達到可接受擬合
# reltol: 若優化一值無法達到設定標準,則當已優化參數已達到 1-reltol 時,則停止
nnet(formula, data, weights, subset, na.action, ...)
nnet(x, y, weights, size, Wts, mask,
linout = FALSE, entropy = FALSE, softmax = FALSE,
censored = FALSE, skip = FALSE, rang = 0.7, decay = 0,
maxit = 100, Hess = FALSE, trace = TRUE, MaxNWts = 1000,
abstol = 1.0e-4, reltol = 1.0e-8, ...)
建立網路模型,隱藏層數為 3, 隨機權重值為 0.1,權值衰減率為 5e-6,最大反覆計算次數為 800。 回傳值中 weights 表示共有幾個參數值(表示 node 間的加權值,此為訓練出的結果),value 表示樣本誤差的值。而若有出現 converged 表示結果已經收斂,若是出現 stopped after N iterations 表示已達最大反覆計算次數,但尚未收斂。
iris.nn <- nnet(training_data, training_data.label,
size = 3, rang = 0.1, decay = 5e-6, maxit = 800)
## # weights: 27
## initial value 55.301436
## iter 10 value 29.067117
## iter 20 value 24.838476
## iter 30 value 24.679822
## iter 40 value 24.227996
## iter 50 value 23.692088
## iter 60 value 15.269172
## iter 70 value 2.341863
## iter 80 value 1.911406
## iter 90 value 0.527444
## iter 100 value 0.152829
## iter 110 value 0.074393
## iter 120 value 0.052010
## iter 130 value 0.051265
## iter 140 value 0.050785
## iter 150 value 0.050455
## iter 160 value 0.047093
## iter 170 value 0.040056
## iter 180 value 0.034578
## iter 190 value 0.032474
## iter 200 value 0.031081
## iter 210 value 0.030705
## iter 220 value 0.030299
## iter 230 value 0.029498
## iter 240 value 0.028170
## iter 250 value 0.027782
## iter 260 value 0.027312
## iter 270 value 0.026024
## iter 280 value 0.025265
## iter 290 value 0.024344
## iter 300 value 0.024214
## iter 310 value 0.023841
## iter 320 value 0.023572
## iter 330 value 0.023276
## iter 340 value 0.022862
## iter 350 value 0.022696
## iter 360 value 0.021970
## iter 370 value 0.021330
## iter 380 value 0.021274
## iter 390 value 0.020983
## iter 400 value 0.020424
## iter 410 value 0.019992
## iter 420 value 0.019920
## iter 430 value 0.019841
## iter 440 value 0.019618
## iter 450 value 0.019581
## iter 460 value 0.019521
## iter 470 value 0.019244
## iter 480 value 0.019136
## iter 490 value 0.019074
## iter 500 value 0.019037
## iter 510 value 0.018965
## iter 520 value 0.018892
## iter 530 value 0.018858
## iter 540 value 0.018841
## iter 550 value 0.018827
## iter 560 value 0.018817
## iter 570 value 0.018768
## iter 580 value 0.018673
## iter 590 value 0.018605
## iter 600 value 0.018586
## iter 610 value 0.018583
## iter 620 value 0.018569
## iter 630 value 0.018526
## iter 640 value 0.018500
## iter 650 value 0.018490
## iter 660 value 0.018484
## iter 670 value 0.018481
## iter 680 value 0.018467
## iter 690 value 0.018444
## iter 700 value 0.018430
## iter 710 value 0.018420
## iter 720 value 0.018418
## iter 730 value 0.018405
## iter 740 value 0.018383
## iter 750 value 0.018361
## iter 760 value 0.018352
## iter 770 value 0.018348
## iter 780 value 0.018333
## iter 790 value 0.018230
## iter 800 value 0.018192
## final value 0.018192
## stopped after 800 iterations
此網路共有 27 個參數,其中 21 個為權重值(weights),5 個為偏差值(bias)。網路建構中 \(b\) 為 bias,\(i_n, n=1...k\) 表示輸入特徵值,而 \(o\) 為 output (輸出)的節點。
# 網路建置方式
summary(iris.nn)
## a 4-3-3 network with 27 weights
## options were - decay=5e-06
## b->h1 i1->h1 i2->h1 i3->h1 i4->h1
## -0.48 -0.90 -2.15 3.42 1.39
## b->h2 i1->h2 i2->h2 i3->h2 i4->h2
## 0.25 0.38 0.59 -1.04 -0.48
## b->h3 i1->h3 i2->h3 i3->h3 i4->h3
## -31.03 2.36 -6.74 0.89 18.69
## b->o1 h1->o1 h2->o1 h3->o1
## -3.58 16.58 -3.16 -24.81
## b->o2 h1->o2 h2->o2 h3->o2
## 4.35 -12.67 2.13 -1.32
## b->o3 h1->o3 h2->o3 h3->o3
## -7.06 -4.74 -4.80 24.54
# 網路層數中各有幾個 node 組成
iris.nn$n
## [1] 4 3 3
# 顯示出學習後的 node 間參數值
iris.nn$wts
## [1] -0.4781871 -0.9007472 -2.1457919 3.4163151 1.3867984
## [6] 0.2493249 0.3775797 0.5929770 -1.0438995 -0.4807341
## [11] -31.0346038 2.3566526 -6.7415599 0.8862190 18.6948434
## [16] -3.5819747 16.5835188 -3.1596877 -24.8122480 4.3491211
## [21] -12.6674290 2.1267045 -1.3185513 -7.0582985 -4.7446825
## [26] -4.8026421 24.5434242
# max.col 會回傳該列(row)資料中值最大的行索引(column index)
iris.nn.test <- function(real, pred) {
real.data <- max.col(real)
pred.data <- max.col(pred)
table(real.data, pred.data)
}
iris.nn.test(class_encoding[-training_idx,], predict(iris.nn, testing_data))
## pred.data
## real.data 1 2 3
## 1 23 0 2
## 2 0 25 0
## 3 3 0 22
由上可以看出此模型分錯了 6 筆資料,sensitivity 約為 92%。
newIris <- data.frame(
rbind(iris3[,,1],iris3[,,2],iris3[,,3]),
Species=factor(c(rep("s",50), rep("c",50), rep("v",50)))
)
head(newIris, 5)
## Sepal.L. Sepal.W. Petal.L. Petal.W. Species
## 1 5.1 3.5 1.4 0.2 s
## 2 4.9 3.0 1.4 0.2 s
## 3 4.7 3.2 1.3 0.2 s
## 4 4.6 3.1 1.5 0.2 s
## 5 5.0 3.6 1.4 0.2 s
newIris.sample <- c(sample(1:50,25), sample(51:100,25), sample(101:150,25))
newIris.nn <- nnet(
Species ~ ., newIris, subset = newIris.sample,
size = 3, rang = 0.1, decay = 5e-6, maxit = 800
)
## # weights: 27
## initial value 82.383168
## iter 10 value 15.180689
## iter 20 value 0.607821
## iter 30 value 0.029309
## iter 40 value 0.022011
## iter 50 value 0.020369
## iter 60 value 0.018536
## iter 70 value 0.018208
## iter 80 value 0.017729
## iter 90 value 0.017310
## iter 100 value 0.016872
## iter 110 value 0.016294
## iter 120 value 0.015957
## iter 130 value 0.015622
## iter 140 value 0.015476
## iter 150 value 0.015126
## iter 160 value 0.014099
## iter 170 value 0.013485
## iter 180 value 0.013101
## iter 190 value 0.012998
## iter 200 value 0.012871
## iter 210 value 0.012762
## iter 220 value 0.012458
## iter 230 value 0.011633
## iter 240 value 0.011490
## iter 250 value 0.011445
## iter 260 value 0.011389
## iter 270 value 0.011308
## iter 280 value 0.011052
## iter 290 value 0.010976
## iter 300 value 0.010966
## iter 310 value 0.010953
## iter 320 value 0.010944
## iter 330 value 0.010911
## iter 340 value 0.010819
## iter 350 value 0.010772
## iter 360 value 0.010744
## iter 370 value 0.010738
## iter 380 value 0.010728
## iter 390 value 0.010708
## iter 400 value 0.010698
## iter 410 value 0.010689
## iter 420 value 0.010678
## iter 430 value 0.010674
## iter 440 value 0.010667
## iter 450 value 0.010619
## iter 460 value 0.010585
## iter 470 value 0.010575
## iter 480 value 0.010565
## iter 490 value 0.010560
## iter 500 value 0.010557
## iter 510 value 0.010554
## iter 520 value 0.010551
## iter 530 value 0.010548
## iter 540 value 0.010541
## iter 550 value 0.010532
## iter 560 value 0.010498
## iter 570 value 0.010474
## iter 580 value 0.010462
## iter 590 value 0.010457
## iter 600 value 0.010451
## iter 610 value 0.010448
## iter 620 value 0.010445
## iter 630 value 0.010444
## iter 640 value 0.010437
## iter 650 value 0.010412
## iter 660 value 0.010402
## iter 670 value 0.010397
## iter 680 value 0.010393
## iter 690 value 0.010387
## iter 700 value 0.010372
## iter 710 value 0.010368
## iter 720 value 0.010363
## iter 730 value 0.010357
## iter 740 value 0.010356
## iter 750 value 0.010354
## iter 760 value 0.010345
## iter 770 value 0.010332
## iter 780 value 0.010329
## iter 790 value 0.010319
## iter 800 value 0.010313
## final value 0.010313
## stopped after 800 iterations
table(
newIris$Species[-newIris.sample],
predict(newIris.nn, newIris[-newIris.sample,], type = "class")
)
##
## c s v
## c 23 0 2
## s 0 25 0
## v 1 0 24