<- function(x) as.numeric(x > 0) step_function
3章 ニューラルネットワーク
活性化関数
ステップ関数の実装
step_function(c(-1.0, 1.0, 2.0))
[1] 0 1 1
curve(step_function, -5, 5)
シグモイド関数の実装
<- function(x) 1 / (1 + exp(-x)) sigmoid
sigmoid(c(-1.0, 1.0, 2.0))
[1] 0.2689414 0.7310586 0.8807971
curve(sigmoid, -5, 5)
ReLU関数
<- function(x) ifelse(x > 0, x, 0) relu
relu(c(-1.0, 1.0, 2.0))
[1] 0 1 2
curve(relu, -5, 5)
出力層の設計
ソフトマックス関数の実装
<- function(a) {
softmax <- exp(a)
exp_a / sum(exp_a)
exp_a }
softmax(c(0.3, 2.9, 4.0))
[1] 0.01821127 0.24519181 0.73659691
オーバーフローに関する問題
softmax(c(1010, 1000, 990))
[1] NaN NaN NaN
対策
<- function(a) {
softmax <- exp(a - max(a))
exp_a / sum(exp_a)
exp_a }
softmax(c(1010, 1000, 990))
[1] 9.999546e-01 4.539787e-05 2.061060e-09
手書き数字認識
MNISTデータセットのダウンロード、読み込みにdslabsパッケージを使う。
ディレクトリmnist_dir
にデータをダウンロードすることにする。
<- "input/mnist/"
mnist_dir file.exists(mnist_dir)
[1] TRUE
データをダウンロードして読み込む。
<- dslabs::read_mnist(download = TRUE, destdir = mnist_dir) mnist
一度ダウンロードすれば、以降はダウンロードしたディレクトリからデータを読み込める。
<- dslabs::read_mnist(path = mnist_dir) mnist
データ構造を確認
str(mnist)
List of 2
$ train:List of 2
..$ images: int [1:60000, 1:784] 0 0 0 0 0 0 0 0 0 0 ...
..$ labels: int [1:60000] 5 0 4 1 9 2 1 3 1 4 ...
$ test :List of 2
..$ images: int [1:10000, 1:784] 0 0 0 0 0 0 0 0 0 0 ...
..$ labels: int [1:10000] 7 2 1 0 4 1 4 9 5 9 ...
MNIST画像を表示してみる。
<- function(img) {
img_show image(matrix(img, nrow = 28)[, 28:1], col = gray(1:12 / 12))
}
ラベルを確認
$train$labels[1] mnist
[1] 5
画像を表示
img_show(mnist$train$images[1, ])
学習済みのパラメータ、sample_weight.pkl
をダウンロード
<- "https://github.com/oreilly-japan/deep-learning-from-scratch/raw/master/ch03/sample_weight.pkl"
url download.file(url, "input/sample_weight.pkl")
reticulateパッケージのpy_load_object関数を使ってpickleファイルを読み込む。
<- reticulate::py_load_object("input/sample_weight.pkl") network
中身を確認
str(network)
List of 6
$ b2: num [1:100(1d)] -0.01471 -0.07215 -0.00156 0.122 0.11603 ...
$ W1: num [1:784, 1:50] -0.00741 -0.0103 -0.01309 -0.01001 0.02207 ...
$ b1: num [1:50(1d)] -0.0675 0.0696 -0.0273 0.0226 -0.22 ...
$ W2: num [1:50, 1:100] -0.1069 0.2991 0.0658 0.0939 0.048 ...
$ W3: num [1:100, 1:10] -0.422 -0.524 0.683 0.155 0.505 ...
$ b3: num [1:10(1d)] -0.06024 0.00933 -0.0136 0.02167 0.01074 ...
推論処理を行うニューラルネットワークの実装
<- function(x, n) matrix(rep(x, n), n, byrow = TRUE)
rep_row
<- function(network, x) {
predict <- nrow(x)
n if (is.null(n)) n <- 1
<- x %*% network$W1 + rep_row(network$b1, n)
a1 <- sigmoid(a1)
z1 <- z1 %*% network$W2 + rep_row(network$b2, n)
a2 <- sigmoid(a2)
z2 <- z2 %*% network$W3 + rep_row(network$b3, n)
a3
softmax(a3)
}
推論を実行
library(tidyverse)
# 正規化
<- mnist$test$images / 255
images
<- 1:nrow(images) %>%
preds map(~ predict(network, images[., ])) %>%
map_int(which.max) - 1
head(preds)
[1] 7 2 1 0 4 1
認識精度
<- mean(preds == mnist$test$labels)
accuracy accuracy
[1] 0.9352
誤認識した画像を確認
<- tibble(actual = mnist$test$labels, pred = preds) %>%
misrecognitions mutate(i = row_number(), .before = 1) %>%
filter(actual != pred)
%>% head(12) misrecognitions
# A tibble: 12 × 3
i actual pred
<int> <int> <dbl>
1 9 5 6
2 34 4 6
3 67 6 2
4 93 9 4
5 125 7 4
6 150 2 9
7 218 6 5
8 234 8 7
9 242 9 8
10 246 3 5
11 248 4 2
12 260 6 0
par(mfrow = c(3, 4))
%>%
misrecognitions head(12) %>%
pull(i) %>%
walk(~ img_show(mnist$test$images[., ]))
バッチ処理による実行
<- 100
batch_size
<- seq(1, nrow(images), batch_size) %>%
preds2 map(~ predict(network, images[.:(. + batch_size - 1), ])) %>%
reduce(rbind) %>%
apply(1, which.max) - 1
identical(preds, preds2)
[1] TRUE