読者です 読者をやめる 読者になる 読者になる

RでDeep Learning(5)

環境はWindows10 & R-3.3.3

2層ニューラルネットワークの実装と実行
(数値微分を使っているため時間がかかり過ぎて使い物にならない)

library(dplyr)
library(R6)

#シグモイド関数
sigmoid <- function(x) 1/(1+exp(-x))

#softmax関数
softmax <- function(x){
	sm_in <- function(a){
		m <- max(a)
		exp_x <- exp(a-m)
		sum_exp_x <- sum(exp_x)
		b <- exp_x/sum_exp_x
		return(b)
	}
	y <- apply(x,1,sm_in) %>% t()
	return(y)
}

#交差エントロピー誤差
cross_entropy_error <- function(y,t){

	batch_size <- nrow(y)

	temp <- (-1)*sum(t*log(y))/batch_size
	return(temp)
}

#勾配を求める関数
numerical_gradient <- function(f,x){
	h <- 1e-4
	grad <- matrix(numeric(nrow(x)*ncol(x)),nrow=nrow(x))

	for(i in 1:(nrow(x)*ncol(x))){
		tmp_val <- x[i]
		#f(x+h)の計算
		x[i] <- tmp_val+h
		fxh1 <- f(x)

		#f(x-h)の計算
		x[i] <- tmp_val-h
		fxh2 <- f(x)

		grad[i]=(fxh1-fxh2)/(2*h)
		x[i] <- tmp_val
	}
	return(grad)
}
# input_ size <- 784
# hidden_size <- 50
# output_seze <- 10
# weight_init_std <- 0.01

#パラメータの初期化
W1 <- matrix(rnorm(784*50),nrow=784)*0.01
W2 <- matrix(rnorm(50*10),nrow=50)*0.01
b1 <- matrix(numeric(50),nrow=1)
b2 <- matrix(numeric(10),nrow=1)

#データの読み込み
x_train <- readRDS("x_train")
t_train <- readRDS("t_train")
TwoLayerNet <- R6Class("TwoLayerNet",

	public = list(
		
		predict = function(x,W1,W2,b1,b2){
			if(x %>% is.vector()){
				batch <- 1
			}else{
				batch <- nrow(x)
			}
			a1 <- (x %*% W1) + matrix(rep(b1,batch),nrow=batch,byrow=T)
			z1 <- sigmoid(a1)
			a2 <- (z1 %*% W2) + matrix(rep(b2,batch),nrow=batch,byrow=T)
			y <- softmax(a2)
			return(y)
		},

		loss = function(x,W1,W2,b1,b2,t){
			z <- self$predict(x,W1,W2,b1,b2)
			loss <- cross_entropy_error(z,t)
			return(loss)
		}
	)
)
#ハイパーパラメータ
iters_num <- 10000
train_size <- 60000
batch_size <- 100
learning_rate <- 0.1

network <- TwoLayerNet$new()

#ダミー関数の定義
dummy_W1 <- function(z) network$loss(x_batch,z,W2,b1,b2,t_batch)
dummy_W2 <- function(z) network$loss(x_batch,W1,z,b1,b2,t_batch)
dummy_b1 <- function(z) network$loss(x_batch,W1,W2,z,b2,t_batch)
dummy_b2 <- function(z) network$loss(x_batch,W1,W2,b1,z,t_batch)

for(i in 1:iters_num){

	#ミニバッチの取得
	batch_mask<-sample(train_size,batch_size)
	x_batch <- x_train[batch_mask,]
	t_batch <- t_train[batch_mask,]

	#勾配の計算
	grads_W1 <- numerical_gradient(dummy_W1,W1)
	grads_W2 <- numerical_gradient(dummy_W2,W2)
	grads_b1 <- numerical_gradient(dummy_b1,b1)
	grads_b2 <- numerical_gradient(dummy_b2,b2)

	#パラメータの更新
	W1 <- W1 - (learning_rate * grads_W1)
	W2 <- W2 - (learning_rate * grads_W2)
	b1 <- b1 - (learning_rate * grads_b1)
	b2 <- b2 - (learning_rate * grads_b2)

	#学習経過の記録
	loss <- network$loss(x_batch,W1,W2,b1,b2,t_batch)
	print(paste(i,":",loss))
}