Created
September 30, 2017 02:33
-
-
Save alsrgv/63c173f2d0773eff2365a79fd4e98c41 to your computer and use it in GitHub Desktop.
Keras with Horovod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
import keras | |
from keras.datasets import mnist | |
from keras.models import Sequential | |
from keras.layers import Dense, Dropout, Flatten | |
from keras.layers import Conv2D, MaxPooling2D | |
from keras import backend as K | |
import tensorflow as tf | |
import horovod.tensorflow as hvd | |
# Initialize Horovod. | |
hvd.init() | |
# Pin GPU to be used to process local rank (one GPU per process) | |
config = tf.ConfigProto() | |
config.gpu_options.allow_growth = True | |
config.gpu_options.visible_device_list = str(hvd.local_rank()) | |
K.set_session(tf.Session(config=config)) | |
batch_size = 128 | |
num_classes = 10 | |
# Adjust number of epochs based on number of GPUs. | |
epochs = 12 / hvd.size() | |
# Input image dimensions | |
img_rows, img_cols = 28, 28 | |
# The data, shuffled and split between train and test sets | |
(x_train, y_train), (x_test, y_test) = mnist.load_data() | |
if K.image_data_format() == 'channels_first': | |
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols) | |
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols) | |
input_shape = (1, img_rows, img_cols) | |
else: | |
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1) | |
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1) | |
input_shape = (img_rows, img_cols, 1) | |
x_train = x_train.astype('float32') | |
x_test = x_test.astype('float32') | |
x_train /= 255 | |
x_test /= 255 | |
print('x_train shape:', x_train.shape) | |
print(x_train.shape[0], 'train samples') | |
print(x_test.shape[0], 'test samples') | |
# Convert class vectors to binary class matrices | |
y_train = keras.utils.to_categorical(y_train, num_classes) | |
y_test = keras.utils.to_categorical(y_test, num_classes) | |
model = Sequential() | |
model.add(Conv2D(32, kernel_size=(3, 3), | |
activation='relu', | |
input_shape=input_shape)) | |
model.add(Conv2D(64, (3, 3), activation='relu')) | |
model.add(MaxPooling2D(pool_size=(2, 2))) | |
model.add(Dropout(0.25)) | |
model.add(Flatten()) | |
model.add(Dense(128, activation='relu')) | |
model.add(Dropout(0.5)) | |
model.add(Dense(num_classes, activation='softmax')) | |
# Adjust learning rate based on number of GPUs (naive approach). | |
opt = tf.train.AdadeltaOptimizer(1.0 * hvd.size()) | |
# Add Horovod Distributed Optimizer. | |
opt = hvd.DistributedOptimizer(opt) | |
model.compile(loss=keras.losses.categorical_crossentropy, | |
optimizer=keras.optimizers.TFOptimizer(opt), | |
metrics=['accuracy']) | |
# Broadcast variables from rank 0 to all other processes. | |
K.get_session().run(hvd.broadcast_global_variables(0)) | |
model.fit(x_train, y_train, | |
batch_size=batch_size, | |
epochs=epochs, | |
verbose=1, | |
validation_data=(x_test, y_test)) | |
score = model.evaluate(x_test, y_test, verbose=0) | |
print('Test loss:', score[0]) | |
print('Test accuracy:', score[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment