Skip to content

Instantly share code, notes, and snippets.

@mick001
Last active May 7, 2019 09:36
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save mick001/a32f2a5540a7dcca880948a939108bcc to your computer and use it in GitHub Desktop.
Save mick001/a32f2a5540a7dcca880948a939108bcc to your computer and use it in GitHub Desktop.
Image recognition tutorial in R using deep convolutional neural networks (MXNet package). Part 3. Full article at https://firsttimeprogrammer.blogspot.com/2016/08/image-recognition-tutorial-in-r-using.html
# Clean workspace
rm(list=ls())
# Load MXNet
require(mxnet)
# Loading data and set up
#-------------------------------------------------------------------------------
# Load train and test datasets
train <- read.csv("train_28.csv")
test <- read.csv("test_28.csv")
# Set up train and test datasets
train <- data.matrix(train)
train_x <- t(train[, -1])
train_y <- train[, 1]
train_array <- train_x
dim(train_array) <- c(28, 28, 1, ncol(train_x))
test_x <- t(test[, -1])
test_y <- test[, 1]
test_array <- test_x
dim(test_array) <- c(28, 28, 1, ncol(test_x))
# Set up the symbolic model
#-------------------------------------------------------------------------------
data <- mx.symbol.Variable('data')
# 1st convolutional layer
conv_1 <- mx.symbol.Convolution(data = data, kernel = c(5, 5), num_filter = 20)
tanh_1 <- mx.symbol.Activation(data = conv_1, act_type = "tanh")
pool_1 <- mx.symbol.Pooling(data = tanh_1, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
# 2nd convolutional layer
conv_2 <- mx.symbol.Convolution(data = pool_1, kernel = c(5, 5), num_filter = 50)
tanh_2 <- mx.symbol.Activation(data = conv_2, act_type = "tanh")
pool_2 <- mx.symbol.Pooling(data=tanh_2, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
# 1st fully connected layer
flatten <- mx.symbol.Flatten(data = pool_2)
fc_1 <- mx.symbol.FullyConnected(data = flatten, num_hidden = 500)
tanh_3 <- mx.symbol.Activation(data = fc_1, act_type = "tanh")
# 2nd fully connected layer
fc_2 <- mx.symbol.FullyConnected(data = tanh_3, num_hidden = 40)
# Output. Softmax output since we'd like to get some probabilities.
NN_model <- mx.symbol.SoftmaxOutput(data = fc_2)
# Pre-training set up
#-------------------------------------------------------------------------------
# Set seed for reproducibility
mx.set.seed(100)
# Device used. CPU in my case.
devices <- mx.cpu()
# Training
#-------------------------------------------------------------------------------
# Train the model
model <- mx.model.FeedForward.create(NN_model,
X = train_array,
y = train_y,
ctx = devices,
num.round = 480,
array.batch.size = 40,
learning.rate = 0.01,
momentum = 0.9,
eval.metric = mx.metric.accuracy,
epoch.end.callback = mx.callback.log.train.metric(100))
# Testing
#-------------------------------------------------------------------------------
# Predict labels
predicted <- predict(model, test_array)
# Assign labels
predicted_labels <- max.col(t(predicted)) - 1
# Get accuracy
sum(diag(table(test[, 1], predicted_labels)))/40
################################################################################
# OUTPUT
################################################################################
#
# 0.975
#
@sparcycram
Copy link

Great thanks works brilliantly. One issue I pick up is it runs only once then requires a reboot of rstudio a it throws an error.

Error in mx.ctx.default() :
object 'mx.ctx.internal.default.value' not found

restart Rstudio and it works fine. Any ideas

sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

PS any idea why it takes until epoch 211 to start to improve?

@mick001
Copy link
Author

mick001 commented Aug 10, 2016

Hi Sparcycram!

Yeah, that thing can be a little annoying. I noted that when you call "require(mxnet)" it generates the mx.ctx.internal.default (or something similar) variable and if you accidentally delete it from the workspace (for instance using rm(list=ls()) you need to restart R or the entire RStudio in order for mxnet functions to work properly. It looks like that variable is required to run the mxnet models (I think it is not a bug). Try typing "require(mxnet)" with an empty workspace you'll see that precise variable being created.

Mmm, to be honest I do not why it takes so long, especially since around 211 it "jumps" up near 100% in relatively few epochs. In my experience neural networks are the worst for training :) it could help adding a validation set for having some more information.

@you-ruei
Copy link

you-ruei commented Aug 31, 2016

Thank you for your blog,
If I want to save trained model,
I used (save)RDA RDS RData not work,

Sincerely

@rikky2010
Copy link

I have used the code given by use but the problem is that it is not able to test my samples correctly.
The training images consists of pictures of dogs and cats ,whereas the testing images consists of flowers.
Please help

``########TRAINING PART######################################

rm(list=ls())
require(EBImage)

##Setting working directory
setwd("C://Users//ricky.gupta//Documents//ImageReco//imager")

Set d where to save images

save_in <- "C://Users//ricky.gupta//Documents//ImageReco//imagerresized"

Load images names

images <- list.files()

Set width

w <- 28

Set height

h <- 28

Main loop resize images and set them to greyscale

for(i in 1:length(images))
{

Try-catch is necessary since some images

may not work.

result <- tryCatch({
# Image name
imgname <- images[i]
# Read image
img <- readImage(imgname)
# Resize image 28x28
img_resized <- resize(img, w = w, h = h)
# Set to grayscale
grayimg <- channel(img_resized,"gray")
# Path to file
path <- paste(save_in, imgname, sep = "")
# Save image
writeImage(grayimg, path, quality = 70)
# Print status
print(paste("Resizing done",i,sep = " "))},
# Error function
error = function(e){print(e)})
}

######################TESTING PART########################################

##Setting working directory
setwd("C://Users//ricky.gupta//Documents//ImageReco//Flowers")

Set d where to save images

save_in <- "C://Users//ricky.gupta//Documents//ImageReco//Flowerrresize"

Load images names

images <- list.files()

Set width

w <- 28

Set height

h <- 28

Main loop resize images and set them to greyscale

for(i in 1:length(images))
{

Try-catch is necessary since some images

may not work.

result <- tryCatch({
# Image name
imgname <- images[i]
# Read image
img <- readImage(imgname)
# Resize image 28x28
img_resized <- resize(img, w = w, h = h)
# Set to grayscale
grayimg <- channel(img_resized,"gray")
# Path to file
path <- paste(save_in, imgname, sep = "")
# Save image
writeImage(grayimg, path, quality = 70)
# Print status
print(paste("Resizing done",i,sep = " "))},
# Error function
error = function(e){print(e)})
}

################################################################

Generate a train dataset

Clean environment and load required packages

rm(list=ls())
require(EBImage)

Set wd where resized greyscale images are located

setwd("C://Users//ricky.gupta//Documents//ImageReco//imagerresize")

Out file

out_file <- "C://Users//ricky.gupta//Documents//ImageReco//train_28.csv"

List images in path

images <- list.files()

Set up df

df1 <- data.frame()

Set image size. In this case 28x28

img_size <- 28*28

Set label

label <- 1

Main loop. Loop over each image

for(i in 1:length(images))
{

Read image

img <- readImage(images[i])

Get the image as a matrix

img_matrix <- img@.Data

Coerce to a vector

img_vector <- as.vector(t(img_matrix))

Add label

vec <- c(label, img_vector)

Bind rows

df1 <- rbind(df1,vec)

Print status info

print(paste("Done ", i, sep = ""))
}

Set names

names(df1) <- c("label", paste("pixel", c(1:img_size)))

Write out dataset

write.csv(df1, out_file, row.names = FALSE)

############################################################################

######Testing Dataset############################################

Generate a train dataset

Clean environment and load required packages

rm(list=ls())
require(EBImage)

Set wd where resized greyscale images are located

setwd("C://Users//ricky.gupta//Documents//ImageReco//Flowerresize")

Out file

out_file <- "C://Users//ricky.gupta//Documents//ImageReco//test_28.csv"

List images in path

images <- list.files()

Set up df

df2 <- data.frame()

Set image size. In this case 28x28

img_size <- 28*28

Set label

label <- 1

Main loop. Loop over each image

for(i in 1:length(images))
{

Read image

img <- readImage(images[i])

Get the image as a matrix

img_matrix <- img@.Data

Coerce to a vector

img_vector <- as.vector(t(img_matrix))

Add label

vec <- c(label, img_vector)

Bind rows

df2 <- rbind(df2,vec)

Print status info

print(paste("Done ", i, sep = ""))
}

Set names

names(df2) <- c("label", paste("pixel", c(1:img_size)))

Write out dataset

write.csv(df2, out_file, row.names = FALSE)

##########################################################

Set seed for reproducibility purposes

set.seed(100)

Clean workspace

rm(list=ls())

Load MXNet

require(mxnet)

Loading data and set up

#-------------------------------------------------------------------------------

Load train and test datasets

train <- read.csv("train_28.csv")
test <- read.csv("test_28.csv")

Set up train and test datasets

train <- data.matrix(train)
train_x <- t(train[, -1])
train_y <- train[, 1]
train_array <- train_x
dim(train_array) <- c(28, 28, 1, ncol(train_x))

test_x <- t(test[, -1])
test_y <- test[, 1]
test_array <- test_x
dim(test_array) <- c(28, 28, 1, ncol(test_x))

Set up the symbolic model

#-------------------------------------------------------------------------------

data <- mx.symbol.Variable('data')

1st convolutional layer

conv_1 <- mx.symbol.Convolution(data = data, kernel = c(5, 5), num_filter = 20)
tanh_1 <- mx.symbol.Activation(data = conv_1, act_type = "tanh")
pool_1 <- mx.symbol.Pooling(data = tanh_1, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))

2nd convolutional layer

conv_2 <- mx.symbol.Convolution(data = pool_1, kernel = c(5, 5), num_filter = 50)
tanh_2 <- mx.symbol.Activation(data = conv_2, act_type = "tanh")
pool_2 <- mx.symbol.Pooling(data=tanh_2, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))

1st fully connected layer

flatten <- mx.symbol.Flatten(data = pool_2)
fc_1 <- mx.symbol.FullyConnected(data = flatten, num_hidden = 500)
tanh_3 <- mx.symbol.Activation(data = fc_1, act_type = "tanh")

2nd fully connected layer

fc_2 <- mx.symbol.FullyConnected(data = tanh_3, num_hidden = 40)

Output. Softmax output since we'd like to get some probabilities.

NN_model <- mx.symbol.SoftmaxOutput(data = fc_2)

Pre-training set up

#-------------------------------------------------------------------------------

Set seed for reproducibility

mx.set.seed(100)

Device used. CPU in my case.

devices <- mx.cpu()

Training

#-------------------------------------------------------------------------------

Train the model

model <- mx.model.FeedForward.create(NN_model,
X = train_array,
y = train_y,
ctx = devices,
num.round = 480,
array.batch.size = 40,
learning.rate = 0.01,
momentum = 0.9,
eval.metric = mx.metric.accuracy,
epoch.end.callback = mx.callback.log.train.metric(100))

Testing

#-------------------------------------------------------------------------------

Predict labels

predicted <- predict(model, test_array)
write.csv(predicted,"predicted.csv")

Assign labels

predicted_labels <- max.col(t(predicted)) - 1

write.csv(predicted_labels,"predictedlabels.csv")

Get accuracy

sum(diag(table(test[, 1], predicted_labels)))/40

@antonysamuelb
Copy link

antonysamuelb commented Jul 14, 2017

Hi,

I tried an implementation for regression. However, there was this following error when i tried to run the model.
Error in t.default(X) : argument is not a matrix

dim(train_mat) # train_array in the above example
10 153 1 3175

class(train_mat)
[1] "array"

class(train.y)
[1] "numeric"

length(train.y)
[1] 3175

Can you suggest what I should try? I am stuck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment