WindowsのRからGPU版MXNetを使う

環境

手順

  • Visual C++ 2015 Build Toolsをインストー
    • CUDA Toolkit 8.0をインストールするためにはVisual Studio 2015が必要と書かれているが実はこれだけインストールしていれば問題なし。
  • CUDA Toolkit 8.0をインストー
  • cuDNN 5.1をダウンロード
    • cuDNN 6.0というのもあるがこちらは試していないのでうまくいくかどうかは不明。
    • ダウンロード後に解凍するとcudnn-8.0-windows10-x64-v5.1\cudaの中に「bin」「include」「lib」フォルダが存在する。
    • C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\内に、cudnn-8.0-windows10-x64-v5.1\cuda内の「bin」「include」「lib」を上書きする。
  • Rから以下を実行
cran <- getOption("repos")
cran["dmlc"] <- "https://s3-us-west-2.amazonaws.com/apache-mxnet/R/CRAN/GPU"
options(repos = cran)
install.packages("mxnet")

2017年7月17日現在、上記で問題なさそう。

RでMXNet(8)

速報

Githubをなんとなくのぞいてみたら、

400 mx.model.FeedForward.create <- 
401 function(symbol, X, y=NULL, ctx=NULL, begin.round=1, 
402          num.round=10, optimizer="sgd", 
403          initializer=mx.init.uniform(0.01), 
404          eval.data=NULL, eval.metric=NULL, 
405          epoch.end.callback=NULL, batch.end.callback=NULL, 
406          array.batch.size=128, array.layout="auto", 
407          kvstore = "local", verbose = TRUE, 
408          arg.params = NULL, aux.params = NULL, fixed.param = NULL, 
409          ...) { 

なんと、mx.model.FeedForward.createのパラメータにfixed.paramが追加された。
きっとこれはfine-tuneをするためのものに違いない。
Python使いにはModule APIというのがあるがRからは使えなかった。
Rを使うことに限界を感じ始めていたところにこの発見。やっぱりRで頑張ろう!!

RでMXNet(7)

Windows10 64bit
Microsoft R Open 3.4.0

ネットワークモデルを変更する方法

  • Fine-tuneをするにあたって大事
  • いつの日かGPU搭載パソコンが手に入ることを夢見て簡単なモデルで練習(泣)
  • 数年前に手に入れたノートパソコン(Intel第3世代 Ivy Bridge搭載)で頑張ってます(笑)

f:id:touch-sp:20170701004222p:plain

  • 「model」という名前のモデルであり訓練済みのパラメータを持っているものとする
  • relu1以降を変更
#layerの書き換え
all_layers <- model$symbol$get.internals()
relu1 <- all_layers[[match("relu1_output",all_layers$outputs)]]
fc2 <- mx.symbol.FullyConnected(data=relu1,num_hidden=100,name="fc2")
fc3 <- mx.symbol.FullyConnected(data=fc2,num_hidden=10,name="fc3")
softmax <- mx.symbol.SoftmaxOutput(fc3, name = "sm")
#パラメータの書き換え
new.params <- model$arg.params
new.params$fc2_weight <- mx.rnorm(c(100,100),0,0.01)
new.params$fc2_bias <- mx.nd.zeros(100)
new.params$fc3_weight <- mx.rnorm(c(100,10),0,0.01)
new.params$fc3_bias <- mx.nd.zeros(10)
#モデルの作成
#そのまま訓練を始めるならmx.model.FeedForward.createを使っても良い
new.model <- list(symbol=softmax,arg.params=new.params,aux.params=list())
class(new.model) <- "MXFeedForwardModel"
#モデルの図示
graph.viz(new.model$symbol,direction="LR")

f:id:touch-sp:20170701011306p:plain

RでMXNet(6)

Windows10 64bit
Microsoft R Open 3.4.0

VGG16訓練後モデルを取得する方法

download.file("http://data.dmlc.ml/models/imagenet/vgg/vgg16-symbol.json","vgg16-symbol.json")
download.file("http://data.dmlc.ml/models/imagenet/vgg/vgg16-0000.params","vgg16-0000.params")

load

vgg16 <- mx.model.load("vgg16",0)

図示

graph.viz(vgg16$symbol)

f:id:touch-sp:20170630122807p:plain

クラス分類

library(EBImage)

my_image <- array(0, c(224, 224, 3, 1))
file <- "D:/rworks/dogcat/dog/dog.0.jpg"
img <- readImage(file)
resize_img <- resize(img, w = 224, h = 224)
my_image[,,, 1] <- resize_img@.Data
my_image <- my_image * 255
#入力は「RGB」(Kerasなどでは「BGR」である)
my_image[,, 1, 1] <- my_image[,, 1, 1] - 123.68
my_image[,, 2, 1] <- my_image[,, 2, 1] - 116.779
my_image[,, 3, 1] <- my_image[,, 3, 1] - 103.939

pred <- apply(predict(vgg16, my_image), 2, which.max) - 1
pred
[1] 192

結果をID、名前に変換

jsonファイルを取得。

download.file("https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json","imagenet_class_index.json")

取得したjsonファイルをいったん「メモ帳」で開いて最後に改行を加えて上書き保存。
その後Rから

library(rjson)
imagenet <- fromJSON(paste(readLines("imagenet_class_index.json"), collapse = ""))
imagenet[[as.character(pred)]]
[1] "n02096177" "cairn"

改行を加えていないと以下のエラーが出る。

incomplete final line found on 'imagenet_class_index.json'

または

imagenet_class_index.json' で不完全な最終行が見つかりました

訓練

と言いたいところであるが・・・。
GPU搭載パソコンを所有していないためここからは何もできない。
クラウドでやるにもお金がないし・・・。

RでMXNet(5)

訓練後のモデルの保存(手動)

mx.model.save(model, "mymodel", 5)

最後の数字は訓練の回数を表す。
同じモデルでも数字を変えればパラメータを別々に保存できる。
たとえば10エポック訓練した後のパラメータ、20エポック訓練した後のパラメータなどなど。
呼び出しは、

model_1 <- mx.model.load("mymodel", 5)

呼び出したモデルで再度訓練を続ける場合にはsymbolとarg.paramsを指定すると良い。

model <- mx.model.FeedForward.create(
	##ここ
	symbol=model_1$symbol,
	##
	X = x_train,
	y = t_train,
	ctx = mx.cpu(),
	num.round = 15,
	array.batch.size = 100,
	learning.rate = 0.1, momentum = 0,
	eval.metric = mx.metric.accuracy,
	eval.data = list(data = x_test, label = t_test),
	##ここ
	arg.params = model_1$arg.params,
	##    
	array.layout = "rowmajor")

厳密にはaux.paramsというのもあるが最初のモデル作成時に指定していなければNULLのまま。

訓練後のモデルの保存(自動)

epoch.end.callbackを指定すれば良い。

model <- mx.model.FeedForward.create(
	softmax, X = x_train,
	y = t_train,
	ctx = mx.cpu(),
	num.round = 15,
	array.batch.size = 100,
	learning.rate = 0.1, momentum = 0,
	eval.metric = mx.metric.accuracy,
	eval.data = list(data = x_test, label = t_test),
	arg.params = new_params,
	##ここ
	epoch.end.callback = mx.callback.save.checkpoint("mymodel",period=5),
	##
	array.layout = "rowmajor")

periodで指定したエポック毎に保存してくれる。

補足

パレメータのみを保存する場合には、

mx.nd.save(model$arg.params, "myparams")

呼び出しは、

newlist <- mx.nd.load("myparams")

RでMXNet(4)

Kaggleの「Dogs vs. Cats」をやってみる。
こちらを参考にさせて頂いた。

  • train.zip(25000枚のjpeg画像)をダウンロードして解凍。
  • 猫、犬の画像をそれぞれcatフォルダ、dogフォルダに分ける。

データの準備

library(EBImage)

#jpeg画像を配列に変換
x_train <- array(0, c(56, 56, 3, 25000))

path <- "D:/rworks/dogcat/train/cat/"
setwd(path)
files_cat <- list.files()

for (i in 1:12500) {
    img <- readImage(files_cat[i])
    resize <- resize(img, w = 56, h = 56)
    x_train[,,,i] <- resize@.Data
}

path <- "D:/rworks/dogcat/train/dog/"
setwd(path)
files_dog <- list.files()

for (i in 1:12500) {
    img <- readImage(files_dog[i])
    resize <- resize(img, w = 56, h = 56)
    x_train[,,, 12500 + i] <- resize@.Data
}

#答え(Cat:0,Dog:1)
t_train <- c(rep(0, 12500), rep(1, 12500))

#25000のうち22500を訓練データにして残りをテストデータにする
sampling <- sample(25000, 22500)
x_train_mini <- x_train[,,, sampling]
t_train_mini <- t_train[sampling]
x_test_mini <- x_train[,,, - sampling]
t_test_mini <- t_train[-sampling]

ニューラルネットワークの構築

library(mxnet)

mydata <- mx.symbol.Variable("data")

conv1 <- mx.symbol.Convolution(
    data = mydata,
    kernel = c(3, 3),
    num_filter = 32)

act1 <- mx.symbol.Activation(data = conv1, act_type = "relu")

pool1 <- mx.symbol.Pooling(
    data = act1,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

conv2 <- mx.symbol.Convolution(
    data = pool1,
    kernel = c(3, 3),
    num_filter = 64)

act2 <- mx.symbol.Activation(data = conv2, act_type = "relu")

pool2 <- mx.symbol.Pooling(
    data = act2,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

fc1 <- mx.symbol.FullyConnected(data = pool2, num_hidden = 200)

drop1 <- mx.symbol.Dropout(data=fc1)

act3 <- mx.symbol.Activation(data = drop1, act_type = "relu")

fc2 <- mx.symbol.FullyConnected(data = act3, num_hidden = 2)

drop2 <- mx.symbol.Dropout(data = fc2)

softmax <- mx.symbol.SoftmaxOutput(data = drop2)

mx.set.seed(1)

model <- mx.model.FeedForward.create(
    softmax, X = x_train_mini,
    y = t_train_mini,
    ctx = mx.cpu(),
    num.round = 30,
    array.batch.size = 100,
    optimizer = "adam",
    eval.metric = mx.metric.accuracy,
    initializer = mx.init.Xavier(factor_type = "in", rnd_type = "gaussian", magnitude = 2),
    eval.data = list(data = x_test_mini, label = t_test_mini),
    array.layout = "auto")

結果

Start training with 1 devices
[1] Train-accuracy=0.557276785714286
[1] Validation-accuracy=0.6684
[2] Train-accuracy=0.627555555555556
[2] Validation-accuracy=0.6976
[3] Train-accuracy=0.663066666666667
[3] Validation-accuracy=0.7332

・・・

[28] Train-accuracy=0.815111111111111
[28] Validation-accuracy=0.7948
[29] Train-accuracy=0.820444444444445
[29] Validation-accuracy=0.7892
[30] Train-accuracy=0.817377777777778
[30] Validation-accuracy=0.796

テストデータのaccuracy:79.6%

> pred <- predict(model, x_train_mini)
> pred_train <- apply(pred, 2, which.max) - 1
> sum(pred_train == t_train_mini) / 22500
[1] 0.9488

訓練データのaccuracy:94.9%

訓練後のデータを保存する場合にはこちらを参照

mx.model.save.RData <- function(model, filename) {
    if (!inherits(model, "MXFeedForwardModel")) stop("Not a MXNet model!")
    model_rdata <- list()
    model_rdata[['symbol_json']] <- model$symbol$as.json()
    model_rdata[['arg.params']] <- lapply(model$arg.params, as.array)
    model_rdata[['aux.params']] <- lapply(model$aux.params, as.array)
    saveRDS(model_rdata, filename)
}

mx.model.load.RData <- function(filename) {
    model_rdata <- readRDS(filename)
    symbol <- mx.symbol.load.json(model_rdata$symbol_json)
    arg.params <- lapply(model_rdata$arg.params, mx.nd.array)
    aux.params <- lapply(model_rdata$aux.params, mx.nd.array)
    model <- list(symbol = symbol, arg.params = arg.params, aux.params = aux.params)
    return(structure(model, class = "MXFeedForwardModel"))
}

(2017年6月27日追記)こちらのほうがおすすめ。

フィルター数32の1番目の畳み込み層をフィルタ数16の二つの畳み込み層に分けてみる

  • わずかに改善
library(mxnet)

mydata <- mx.symbol.Variable("data")

conv1 <- mx.symbol.Convolution(
    data = mydata,
    kernel = c(3, 3),
    num_filter = 16)

conv1_5 <- mx.symbol.Convolution(
    data = conv1,
    kernel = c(3, 3),
    num_filter = 16)

act1 <- mx.symbol.Activation(data = conv1_5, act_type = "relu")

pool1 <- mx.symbol.Pooling(
    data = act1,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

conv2 <- mx.symbol.Convolution(
    data = pool1,
    kernel = c(3, 3),
    num_filter = 64)

act2 <- mx.symbol.Activation(data = conv2, act_type = "relu")

pool2 <- mx.symbol.Pooling(
    data = act2,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

fc1 <- mx.symbol.FullyConnected(data = pool2, num_hidden = 200)

drop1 <- mx.symbol.Dropout(data = fc1)

act3 <- mx.symbol.Activation(data = drop1, act_type = "relu")

fc2 <- mx.symbol.FullyConnected(data = act3, num_hidden = 2)

drop2 <- mx.symbol.Dropout(data = fc2)

softmax <- mx.symbol.SoftmaxOutput(data = drop2)

mx.set.seed(1)

model <- mx.model.FeedForward.create(
    softmax, X = x_train_mini,
    y = t_train_mini,
    ctx = mx.cpu(),
    num.round = 30,
    array.batch.size = 100,
    optimizer = "adam",
    eval.metric = mx.metric.accuracy,
    initializer = mx.init.Xavier(factor_type = "in", rnd_type = "gaussian", magnitude = 2),
    eval.data = list(data = x_test_mini, label = t_test_mini),
    array.layout = "auto")

結果

Start training with 1 devices
[1] Train-accuracy=0.585848214285714
[1] Validation-accuracy=0.7144
[2] Train-accuracy=0.644711111111111
[2] Validation-accuracy=0.7272
[3] Train-accuracy=0.675244444444445
[3] Validation-accuracy=0.7536

・・・

[28] Train-accuracy=0.823822222222223
[28] Validation-accuracy=0.79
[29] Train-accuracy=0.815111111111112
[29] Validation-accuracy=0.7984
[30] Train-accuracy=0.826044444444445
[30] Validation-accuracy=0.806

1番目と2番目の畳み込み層の間に活性化関数を入れてみる

  • ほとんど変わらず
library(mxnet)

mydata <- mx.symbol.Variable("data")

conv1 <- mx.symbol.Convolution(
    data = mydata,
    kernel = c(3, 3),
    num_filter = 16)

act0 <- mx.symbol.Activation(data = conv1, act_type = "relu")

conv1_5 <- mx.symbol.Convolution(
    data = act0,
    kernel = c(3, 3),
    num_filter = 16)

act1 <- mx.symbol.Activation(data = conv1_5, act_type = "relu")

pool1 <- mx.symbol.Pooling(
    data = act1,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

conv2 <- mx.symbol.Convolution(
    data = pool1,
    kernel = c(3, 3),
    num_filter = 64)

act2 <- mx.symbol.Activation(data = conv2, act_type = "relu")

pool2 <- mx.symbol.Pooling(
    data = act2,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

fc1 <- mx.symbol.FullyConnected(data = pool2, num_hidden = 200)

drop1 <- mx.symbol.Dropout(data = fc1)

act3 <- mx.symbol.Activation(data = drop1, act_type = "relu")

fc2 <- mx.symbol.FullyConnected(data = act3, num_hidden = 2)

drop2 <- mx.symbol.Dropout(data = fc2)

softmax <- mx.symbol.SoftmaxOutput(data = drop2)

mx.set.seed(1)

model <- mx.model.FeedForward.create(
    softmax, X = x_train_mini,
    y = t_train_mini,
    ctx = mx.cpu(),
    num.round = 30,
    array.batch.size = 100,
    optimizer = "adam",
    eval.metric = mx.metric.accuracy,
    initializer = mx.init.Xavier(factor_type = "in", rnd_type = "gaussian", magnitude = 2),
    eval.data = list(data = x_test_mini, label = t_test_mini),
    array.layout = "auto")

結果

Start training with 1 devices
[1] Train-accuracy=0.558973214285714
[1] Validation-accuracy=0.6536
[2] Train-accuracy=0.642577777777778
[2] Validation-accuracy=0.7352
[3] Train-accuracy=0.681155555555555
[3] Validation-accuracy=0.7532

・・・

[28] Train-accuracy=0.824933333333334
[28] Validation-accuracy=0.8012
[29] Train-accuracy=0.820311111111112
[29] Validation-accuracy=0.8072
[30] Train-accuracy=0.827511111111112
[30] Validation-accuracy=0.798

2番目の畳み込み層をフィルタ数32、全結合層のニューロン数を300に増やしてみる

  • そろそろCPUの限界を感じ始めた(num.round=20に)
  • 時間の割には改善なし
library(mxnet)

mydata <- mx.symbol.Variable("data")

conv1 <- mx.symbol.Convolution(
    data = mydata,
    kernel = c(3, 3),
    num_filter = 16)

conv1_5 <- mx.symbol.Convolution(
    data = conv1,
    kernel = c(3, 3),
    num_filter = 32)

act1 <- mx.symbol.Activation(data = conv1_5, act_type = "relu")

pool1 <- mx.symbol.Pooling(
    data = act1,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

conv2 <- mx.symbol.Convolution(
    data = pool1,
    kernel = c(3, 3),
    num_filter = 64)

act2 <- mx.symbol.Activation(data = conv2, act_type = "relu")

pool2 <- mx.symbol.Pooling(
    data = act2,
    pool_type = "max",
    kernel = c(2, 2),
    stride = c(2, 2))

fc1 <- mx.symbol.FullyConnected(data = pool2, num_hidden = 300)

drop1 <- mx.symbol.Dropout(data = fc1)

act3 <- mx.symbol.Activation(data = drop1, act_type = "relu")

fc2 <- mx.symbol.FullyConnected(data = act3, num_hidden = 2)

drop2 <- mx.symbol.Dropout(data = fc2)

softmax <- mx.symbol.SoftmaxOutput(data = drop2)

mx.set.seed(1)

model <- mx.model.FeedForward.create(
    softmax, X = x_train_mini,
    y = t_train_mini,
    ctx = mx.cpu(),
    num.round = 20,
    array.batch.size = 100,
    optimizer = "adam",
    eval.metric = mx.metric.accuracy,
    initializer = mx.init.Xavier(factor_type = "in", rnd_type = "gaussian", magnitude = 2),
    eval.data = list(data = x_test_mini, label = t_test_mini),
    array.layout = "auto")

結果

Start training with 1 devices
[1] Train-accuracy=0.5896875
[1] Validation-accuracy=0.7084
[2] Train-accuracy=0.6484
[2] Validation-accuracy=0.7348
[3] Train-accuracy=0.692933333333333
[3] Validation-accuracy=0.74

・・・

[18] Train-accuracy=0.852711111111111
[18] Validation-accuracy=0.7916
[19] Train-accuracy=0.853066666666668
[19] Validation-accuracy=0.7856
[20] Train-accuracy=0.855155555555556
[20] Validation-accuracy=0.7948

訓練データ200~300枚程度を手作業で背景を取り除くようにトリミングしてみる

  • あとで縮小しやすいように正方形でトリミング
  • 結果はわずかに改善
  • 訓練データの重要性を改めて認識した
Start training with 1 devices
[1] Train-accuracy=0.581026785714286
[1] Validation-accuracy=0.6712
[2] Train-accuracy=0.654933333333333
[2] Validation-accuracy=0.7428
[3] Train-accuracy=0.689022222222222
[3] Validation-accuracy=0.7696

・・・

[18] Train-accuracy=0.853777777777778
[18] Validation-accuracy=0.8084
[19] Train-accuracy=0.855688888888889
[19] Validation-accuracy=0.8132
[20] Train-accuracy=0.854355555555556
[20] Validation-accuracy=0.8172

RでMXNet(3)

MNIST 99%以上を目指す!
と言っても下記の本で紹介されているニューラルネットワークをMXNetで書いただけ。

初期設定

library(mxnet)

データの読み込み

#訓練データの読み込み
x_train <- array(t(readRDS("x_train")),c(28,28,1,60000)) / 255
t_train <- apply(readRDS("t_train"), 1, which.max) - 1

#テストデータの読み込み
x_test <- array(t(readRDS("x_test")), c(28, 28, 1, 10000))
t_test <- apply(readRDS("t_test"), 1, which.max) - 1

ニューラルネットワークの構築

mydata <- mx.symbol.Variable("data")

conv1 <- mx.symbol.Convolution(
     data=mydata,
     kernel = c(3,3),
   pad = c(1,1),
   stride = c(1,1),
   num_filter = 16)

act1 <- mx.symbol.Activation(data=conv1, act_type = "relu")

conv2 <- mx.symbol.Convolution(
   data=act1,
   kernel = c(3,3),
   pad = c(1,1),
   stride = c(1,1),
   num_filter = 16)

act2 <- mx.symbol.Activation(data=conv2, act_type = "relu")

pool1 <- mx.symbol.Pooling(
   data=act2,
   pool_type = "max",
   kernel = c(2,2),
   stride = c(2,2))

conv3 <- mx.symbol.Convolution(
   data=pool1,
   kernel = c(3,3),
   pad = c(1,1),
   stride = c(1,1),
   num_filter = 32)

act3 <- mx.symbol.Activation(data=conv3, act_type = "relu")

conv4 <- mx.symbol.Convolution(
   data=act3,
   kernel = c(3,3),
   pad = c(2,2),
   stride = c(1,1),
   num_filter = 32)

act4 <- mx.symbol.Activation(data=conv4, act_type = "relu")

pool2 <- mx.symbol.Pooling(
   data=act4,
   pool_type = "max",
   kernel = c(2,2),
   stride = c(2,2))

conv5 <- mx.symbol.Convolution(
   data=pool2,
   kernel = c(3,3),
   pad = c(1,1),
   stride = c(1,1),
   num_filter = 64)

act5 <- mx.symbol.Activation(data=conv5, act_type = "relu")

conv6 <- mx.symbol.Convolution(
   data=act5,
   kernel = c(3,3),
   pad = c(1,1),
   stride = c(1,1),
   num_filter = 64)

act6 <- mx.symbol.Activation(data=conv6, act_type = "relu")

pool3 <- mx.symbol.Pooling(
   data=act6,
   pool_type = "max",
   kernel = c(2,2),
   stride = c(2,2))

fc1 <- mx.symbol.FullyConnected(data=pool3, num_hidden = 50)

act7 <- mx.symbol.Activation(data=fc1, act_type = "relu")

drop1 <- mx.symbol.Dropout(data=act7)

fc2 <- mx.symbol.FullyConnected(data=drop1, num_hidden = 10)

drop2 <- mx.symbol.Dropout(data=fc2)

softmax <- mx.symbol.SoftmaxOutput(drop2, name = "sm")

mx.set.seed(1)

model <- mx.model.FeedForward.create(
   softmax, X = x_train,
   y = t_train,
   ctx = mx.cpu(),
   num.round = 20,
   array.batch.size = 1000,
   optimizer = "adam",
   eval.metric = mx.metric.accuracy,
   initializer = mx.init.Xavier(factor_type="in",rnd_type="gaussian",magnitude=2),
   eval.data = list(data = x_test, label = t_test),
   array.layout = "auto")

結果

Start training with 1 devices
[1] Train-accuracy=0.233593220338983
[1] Validation-accuracy=0.8341
[2] Train-accuracy=0.354283333333333
[2] Validation-accuracy=0.9439
[3] Train-accuracy=0.411583333333333
[3] Validation-accuracy=0.9697

・・・

[18] Train-accuracy=0.5672
[18] Validation-accuracy=0.9934
[19] Train-accuracy=0.569166666666667
[19] Validation-accuracy=0.9944
[20] Train-accuracy=0.569616666666667
[20] Validation-accuracy=0.9932
  • Train-accuracyの数値があがってこない
  • どうやらTrain-accuracyの計算においてDropout層を無視していない様子
  • Validation-accuracyはDropout層を無視して正確に計算されていそう

実際のTrain-accuracy

> pred <- predict(model,x_train)
> pred_train <- apply(pred,2,which.max) - 1
> sum(pred_train == t_train)/60000
[1] 0.99485
  • predict関数ではDropout層を無視して正確に計算されていそう