In [5]:
import sys, os
import h2o
from h2o.estimators.deepwater import H2ODeepWaterEstimator
import os.path
from IPython.display import Image, display, HTML
import pandas as pd
import random
PATH=os.path.expanduser("~/h2o-3/")
h2o.init(nthreads=-1)
if not H2ODeepWaterEstimator.available(): exit
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 [44]:
frame = h2o.import_file(PATH + "/bigdata/laptop/deepwater/imagenet/cat_dog_mouse.csv")
print(frame.dim)
print(frame.head(5))
Let's look at a random subset of 10 images
In [45]:
images = frame[:,0].as_data_frame(use_pandas=False)
which = list(random.sample(xrange(frame.nrow), 10))
sample = [images[x][0] for x in which]
print(sample)
for x in sample:
display(Image(filename=PATH+x))
Now, we build a classic convolutional neural network, called LeNet
We'll use a GPU to train such a LeNet model in seconds
In [19]:
!nvidia-smi
To build a LeNet image classification model in H2O, simply specify network = "lenet":
In [46]:
model = H2ODeepWaterEstimator(epochs=500, network = "lenet")
model.train(x=[0],y=1, training_frame=frame)
model.show()
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 [6]:
def lenet(num_classes):
import mxnet as mx
data = mx.symbol.Variable('data')
# first conv
conv1 = mx.symbol.Convolution(data=data, kernel=(5,5), num_filter=20)
tanh1 = mx.symbol.Activation(data=conv1, act_type="tanh")
pool1 = mx.symbol.Pooling(data=tanh1, pool_type="max", kernel=(2,2), stride=(2,2))
# second conv
conv2 = mx.symbol.Convolution(data=pool1, kernel=(5,5), num_filter=50)
tanh2 = mx.symbol.Activation(data=conv2, act_type="tanh")
pool2 = mx.symbol.Pooling(data=tanh2, pool_type="max", kernel=(2,2), stride=(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 [48]:
nclasses = frame[1].nlevels()[0]
lenet(nclasses).save("/tmp/symbol_lenet-py.json")
In [23]:
# pip install graphviz
# sudo apt-get install graphviz
import mxnet as mx
import graphviz
mx.viz.plot_network(lenet(3), shape={"data":(1, 1, 28, 28)}, node_attrs={"shape":'rect',"fixedsize":'false'})
Out[23]:
In [49]:
model = H2ODeepWaterEstimator(epochs=500, ## early stopping is on by default and might trigger before
network_definition_file="/tmp/symbol_lenet-py.json", ## specify the model
image_shape=[28,28], ## provide expected (or matching) image size
channels=3) ## 3 for color, 1 for monochrome
model.train(x=[0], y=1, training_frame=frame)
model.show()
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 [50]:
model = H2ODeepWaterEstimator(epochs=10,
network_definition_file="/tmp/symbol_lenet-py.json",
image_shape=[28,28],
channels=3,
gpu = False)
model.train(x=[0], y=1, training_frame=frame)
model.show()