In [1]:
library(h2o)
h2o.init(nthreads=-1)
if (!h2o.deepwater_available()) return()
For simplicity, H2O Deep Water allows you to specify a list of URIs (file paths) or URLs (links) to images, together with a response column (either a class membership (enum) or regression target (numeric)).
For this example, we use this simple cat/dog/mouse dataset that has a few hundred images, and a label of cardinality 3.
In [2]:
df <- h2o.importFile("/home/ubuntu/h2o-3/bigdata/laptop/deepwater/imagenet/cat_dog_mouse.csv")
print(head(df))
path = 1 ## must be the first column
response = 2
Let's look at a random subset of 10 images
Now, we build a classic convolutional neural network, called LeNet
We'll use a GPU to train such a LeNet model in seconds
To build a LeNet image classification model in H2O, simply specify network = "lenet":
In [4]:
model <- h2o.deepwater(x=path, y=response,
training_frame=df, epochs=50,
learning_rate=1e-3, network = "lenet")
model
If you'd like to build your own LeNet network architecture, then this is easy as well. In this example script, we are using the 'mxnet' backend. Models can easily be imported/exported between H2O and MXNet since H2O uses MXNet's format for model definition.
In [5]:
get_symbol <- function(num_classes = 1000) {
library(mxnet)
data <- mx.symbol.Variable('data')
# first conv
conv1 <- mx.symbol.Convolution(data = data, kernel = c(5, 5), num_filter = 20)
tanh1 <- mx.symbol.Activation(data = conv1, act_type = "tanh")
pool1 <- mx.symbol.Pooling(data = tanh1, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
# second conv
conv2 <- mx.symbol.Convolution(data = pool1, kernel = c(5, 5), num_filter = 50)
tanh2 <- mx.symbol.Activation(data = conv2, act_type = "tanh")
pool2 <- mx.symbol.Pooling(data = tanh2, pool_type = "max", kernel = c(2, 2), stride = c(2, 2))
# first fullc
flatten <- mx.symbol.Flatten(data = pool2)
fc1 <- mx.symbol.FullyConnected(data = flatten, num_hidden = 500)
tanh3 <- mx.symbol.Activation(data = fc1, act_type = "tanh")
# second fullc
fc2 <- mx.symbol.FullyConnected(data = tanh3, num_hidden = num_classes)
# loss
lenet <- mx.symbol.SoftmaxOutput(data = fc2, name = 'softmax')
return(lenet)
}
In [7]:
nclasses = h2o.nlevels(df[,response])
network <- get_symbol(nclasses)
cat(network$as.json(), file = "/tmp/symbol_lenet-R.json", sep = '')
In [8]:
# sudo apt-get install graphviz
graph.viz(network$as.json())
In [9]:
model = h2o.deepwater(x=path, y=response, training_frame = df,
epochs=500, ## early stopping is on by default and might trigger before
network_definition_file="/tmp/symbol_lenet-R.json", ## specify the model
image_shape=c(28,28), ## provide expected (or matching) image size
channels=3) ## 3 for color, 1 for monochrome
In [10]:
summary(model)
To see how much slower training a convolutional neural net is trained without a GPU, disable the 'gpu' flag. Note that using MKL or other optimized implementations of BLAS can make this difference shrink a lot, but generally a GPU is at least 5x faster than the best CPU implementations for realistic workloads, and often 50x faster or even more.
Instead of training for 500 epochs on the GPU, we'll train for 10 epochs on the CPU.
In [11]:
model = h2o.deepwater(x=path, y=response, training_frame = df,
epochs=10,
network_definition_file="/tmp/symbol_lenet-R.json",
image_shape=c(28,28),
channels=3,
gpu=FALSE)
In [12]:
summary(model)